我一直在努力解决UIScrollView的问题。
我有一个UIScrollVIew
,其中包含UITextView
作为子视图。当我选择文本视图时,会弹出一个键盘。我想调整文本视图的大小以完全适合可用空间,并且还滚动滚动视图,以便文本视图完全位于可见空间中(不会被键盘隐藏)。
当键盘出现时,我调用一个方法来计算文本视图的适当大小,然后执行以下代码:
[UIView animateWithDuration:0.3
animations:^
{
self.textView.frame = frame;
}
];
[self.scrollView setContentOffset:CGPointMake(0,frame.origin.y) animated:YES];
(此处框架是文本视图的适当框架)。
不幸的是,滚动视图并不总是滚动到正确的位置,尤其是当我选择文本视图时,它已经处于非零垂直内容偏移。我知道我设置的内容偏移是正确的。
经过大量测试后,我终于意识到发生的事情是动画完成后,滚动视图会自动滚动。
此代码确实有效:
UIView animateWithDuration:0.3
animations:^
{
self.textView.frame = frame;
}
completion:^(BOOL finished) {
[self.scrollView setContentOffset:CGPointMake(0, frame.origin.y) animated:YES];
}
];
但它看起来很奇怪,因为滚动视图滚动到错误的位置,然后滚动到右边的位置。
当文本视图框完成动画时,是否有人知道如何阻止滚动视图更改内容偏移?
我正在使用iOS 5.0进行测试。
这是我发现有效的解决方案。我仍然不完全理解发生了什么,可能与我的弹簧和支柱的设置方式有关。基本上我将滚动视图内容大小缩小了与文本视图缩小相同的量。
- (void)keyboardDidShow:(NSNotification*)aNotification
{
NSDictionary* info = [aNotification userInfo];
// Get the height of the keyboard
CGRect kbRect = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue];
kbRect = [self.view convertRect:kbRect fromView:nil];
CGSize kbSize = kbRect.size;
// Adjust the height of the text view to fit in the visible view
CGRect frame = self.textView.frame;
int visibleHeight = self.view.frame.size.height;
visibleHeight -= kbSize.height;
frame.size.height = visibleHeight;
// Get the new scroll view content size
CGSize contentSize = self.scrollView.contentSize;
contentSize.height = contentSize.height - self.textView.frame.size.height + frame.size.height;
[UIView animateWithDuration:0.1
animations:^
{
self.textView.frame = frame;
// Note that the scroll view content size needs to be reset, or the scroll view
// may automatically scroll to a new position after the animation is complete.
self.scrollView.contentSize = contentSize;
[self.scrollView setContentOffset:CGPointMake(0, frame.origin.y) animated:YES];
}
];
// Turn off scrolling in scroll view
self.scrollView.scrollEnabled = NO;
}
// Called when the UIKeyboardWillHideNotification is sent
- (void)keyboardWillBeHidden:(NSNotification*)aNotification
{
// Update the view layout
[UIView animateWithDuration:0.3 animations:^
{
self.scrollView.contentOffset = CGPointZero;
[self updateViewLayout];
}
];
// Turn on scrolling in the scroll view
self.scrollView.scrollEnabled = YES;
}
([self updateViewLayout]
是一种将文本视图返回到正确高度的方法,并重置滚动视图内容大小,并确保所有其他子视图都已正确定位。
答案 0 :(得分:3)
不要调整文本视图的框架。您需要做的就是滚动滚动视图。如果滚动滚动视图动画,则textView将向上滑动动画。只需执行以下操作:
[self.scrollView setContentOffset:CGPointMake(0, frame.origin.y) animated:YES];
如果你需要滚动视图以特定的速率滚动,那么手动调整动画块中的内容偏移量。(我没有测试过这个,你可能想要调整动画标记,或者逐步调整内容偏移量如果这不起作用,一次只有像素)
[UIView animateWithDuration:0.3f
animations:^{
[self.scrollView setContentOffset:CGPointMake(0, frame.origin.y) animated:YES];
} ];
答案 1 :(得分:3)
我相信我也有类似的东西。我希望我的水平UIScrollView回到它的原始偏移量(0,0),每次我回到它的动画时,它只会关闭几个像素,但只要有人触摸了滚动视图,它就会继续并完成动画(几乎像电子游戏中的滞后)。
由于这个原因,我尝试将它作为主队列放在GCD中,之后它完全正常。这是代码:
- (void)setPageZero{
dispatch_async(dispatch_get_main_queue(), ^{
[UIView animateWithDuration:1.0f
delay:0 options:UIViewAnimationOptionCurveEaseInOut
animations:^{
[self.scrollView setContentOffset:CGPointMake(0, self.scrollView.frame.origin.y) animated:YES];
}
completion:^(BOOL finished) {}];
});
}
基本上做的是,它将动画放入主队列(有点像CPU / GPU中的高速公路),并将其优先于其他事物!
希望这有助于未来的读者!
答案 2 :(得分:2)
我遇到了类似的问题。基本上我有一个包含三个页面的滚动视图,每个页面包含一个自定义UIView
类。自定义UIView
类包含一个图像和一些包含图像信息的叠加视图。叠加层视图包含多个UITextView
字段。
我将自定义视图附加到滚动视图,然后加载图像&使用块操作叠加。我通过删除第一个视图,重新定位接下来的两个视图以及向右添加新视图来向右滑动。
如果我创建UITextField
个对象并禁用滚动,如下所示:
UITextView* view = [[UITextView alloc]
initWithFrame:CGRectMake(position.x,position.y,width,height)];
view.editable = NO;
view.scrollEnabled = NO;
然后当我从块代码返回时,滚动视图在页面之间重新定位。请注意,我没有重新定位滚动视图,在从块退出时,滚动视图位于正确的位置。
但是,如果我注释掉禁用滚动的代码
UITextView* view = [[UITextView alloc]
initWithFrame:CGRectMake(position.x,position.y,width,height)];
view.editable = NO;
// view.scrollEnabled = NO;
这种重新定位不会发生,滚动按预期工作。
答案 3 :(得分:0)
完全破解:可以改善重置问题:
- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView
{
[self setContentOffset:self.contentOffset animated:NO];
}