【发布时间】:2011-08-08 19:48:19
【问题描述】:
在我的应用程序中,我在某个视图上有一个文本字段,当它出现时它被键盘覆盖。所以我必须滚动视图(甚至重新排列子视图)。为此,我:
-
注册键盘通知:
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(moveViewUp) name:UIKeyboardWillShowNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(moveViewDown) name:UIKeyboardWillHideNotification object:nil]; -
收到通知后,使用如下块动画移动视图:
- (void)moveViewUp { void (^animations)(void) = nil; oldViewFrame = self.view.frame; animations = ^{ CGRect newViewFrame = oldViewFrame; newViewFrame.origin.y -= kViewOffset; self.view.frame = newViewFrame; }; [UIView animateWithDuration:1.0 animations:animations]; } - (void)moveViewDown { void (^animations)(void) = nil; animations = ^{ self.view.frame = oldViewFrame; }; [UIView animateWithDuration:1.0 animations:animations]; }
这很好用,视图会上下滚动,直到我添加更多动画。具体来说,当用户点击按钮时,我正在添加到下一个视图的过渡:
- (IBAction)switchToNextView:(id)sender {
// [self presentModalViewController:nextViewController animated:YES];
[UIView transitionFromView:self.view
toView:self.nextView
duration:1.0
options:UIViewAnimationOptionTransitionFlipFromRight
completion:nil];
}
现在我们解决了问题。
如果在点击按钮时第一个视图发生了移动(这意味着键盘是可见的),那么当键盘向下滑动时会同时开始转换到下一个视图,但视图本身不会向下移动,所以在一瞬间,我们实际上可以看到底层视图。那是不对的。当我以模态方式呈现下一个视图时(参见注释行),所有动画都按照我的意愿进行:即键盘隐藏,视图从右侧翻转 并 向下滚动 - 全部同时时间。这很好,但问题是我实际上没有UIViewController 用于该视图。事实上,我试图在没有UIViewController 的情况下模拟模态行为(为什么会这样?perhaps it's just a bad design, I'll post another question on that)。
那么为什么在这种情况下moveViewDown 方法的动画没有在适当的时间触发呢?
更新 1
我为每个函数添加了一个调试打印来检查调用顺序,这是我得到的:
-[KeyboardAnimationViewController moveViewUp]
__-[KeyboardAnimationViewController moveViewUp]_block_invoke_1 <-- scroll up animation
-[KeyboardAnimationViewController switchToNextView:]
-[KeyboardAnimationViewController moveViewDown]
__-[KeyboardAnimationViewController moveViewDown]_block_invoke_1 <-- scroll down animation
即使我像这样在转换之前明确地将视图向下移动
- (IBAction)switchToNextView:(id)sender {
// [self presentModalViewController:nextViewController animated:YES];
NSLog(@"%s", __PRETTY_FUNCTION__);
if (self.view.frame.origin.x < 0)
[self moveViewDown];
[UIView transitionFromView:self.view
toView:self.nextView
duration:1.0
options:UIViewAnimationOptionTransitionFlipFromRight
completion:nil];
}
我得到完全相同的日志。
更新 2
我又做了一些实验,得出以下结论:
- 如果我显式调用
moveViewDown或resignFirstResponder:,动画将被推迟到当前运行循环结束,此时所有待处理的动画都真正开始播放。虽然动画块立即登录到控制台 -- 我觉得很奇怪! - 方法
transitionFromView:toView:duration:options:completion:(也可能是transitionWithView:duration:options:animations:completion:,没有检查这个)显然会制作“from-view”和“to-view”的快照,并仅使用这些快照创建动画。由于视图的滚动被推迟,因此在视图仍然偏移时进行快照。该方法以某种方式甚至忽略了UIViewAnimationOptionAllowAnimatedContent选项。 - 我设法使用任何
animateWithDuration: ... completion:方法获得了预期的效果。这些方法似乎忽略了转换选项,例如UIViewAnimationOptionTransitionFlipFromRight。 - 键盘开始隐藏(隐式)并在调用
removeFromSuperview时发送相应的通知。
如果我在某处错了,请纠正我。
【问题讨论】:
-
我认为,当您处于视图动画之间时,您会收到键盘关闭通知。两个动画可能相互冲突,结果是视图失真。
-
@Jhaliya,请查看更新后的问题
-
澄清一下:我确实在视图动画之间收到了通知,但是它不会使动画冲突或扭曲视图。我不介意你投票,但@Jhaliya 不正确。
标签: iphone ios animation uiview keyboard