UIView在显示/隐藏键盘上使用动画内容阻止动画过渡

在我的应用程序中,我在某个视图上有一个文本字段,键盘在显示时会被覆盖。 所以我必须滚动视图(甚至重新排列子视图)。 要做到这一点我:

  1. 注册键盘通知:

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(moveViewUp) name:UIKeyboardWillShowNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(moveViewDown) name:UIKeyboardWillHideNotification object:nil]; 
  2. 收到通知后,使用块动画移动视图,如下所示:

     - (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情况下模拟模态行为(为什么会这样? 也许它只是一个糟糕的设计,我会发布另一个问题 )。

那么为什么在这种情况下, 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

我已经进行了一些实验并做出了以下结论:

  1. 如果我显式地调用moveViewDownresignFirstResponder:动画被推迟到当前运行循环结束,此时所有挂起的动画实际上都开始播放。 虽然动画块立即登录到控制台 – 对我来说似乎很奇怪!
  2. 方法transitionFromView:toView:duration:options:completion:也许transitionWithView:duration:options:animations:completion:也是,没有检查这个)显然是制作了“from-view”和“to-view”的快照“并仅使用这些快照创建动画。 由于视图的滚动被推迟,因此在视图仍然偏移时进行快照。 该方法甚至忽略了UIViewAnimationOptionAllowAnimatedContent选项
  3. 我设法使用任何animateWithDuration: ... completion:获得所需的效果animateWithDuration: ... completion:方法。 这些方法似乎忽略了 UIViewAnimationOptionTransitionFlipFromRight转换选项
  4. 键盘开始隐藏(隐式)并在调用removeFromSuperview时发送相应的通知。

如果我错了,请纠正我。

如果你试图在没有UIViewController情况下模拟模态行为,我猜你想让你的下一个视图从屏幕底部出现吗? 如果我错了,请纠正我。 如果你想要这样一个动画你可以尝试一个解决方法,你可以在animation块中更改下一个视图的框架,使其看起来好像它与presentModalViewController类似