交互式解雇模态时出现故障

时间:2016-05-13 07:22:37

标签: ios uinavigationcontroller modalviewcontroller

当通过UIPercentDrivenInteractiveTransition实现模态视图控制器的交互式解雇(拖动模式向下应该忽略它)时,我们遇到了这个问题。

设定:

  1. UIViewController中嵌入UINavigationControllerUINavigationBar
  2. 中至少有一个按钮
  3. UIViewController
  4. 中至少一个按钮的形式呈现UINavigationController中嵌入的另一个UINavigationBar
  5. 在模拟呈现UIPanGestureRecognizer上设置UINavigationController以驱动UIPercentDrivenInteractiveTransition
  6. 拖动模式"持有"它UINavigationBar
  7. 问题:

    • 在慢慢向下拖动时,动画故障导致模态视图上下跳跃

    • 仅在以下情况下出现毛刺:

      1. 两个UINavigationBar上至少有一个按钮
      2. 你"持有" UINavigationBar
      3. 上的模态

    可以从github repo下载最小的示例。

    有没有人遇到过这样的问题?有没有解决方法?我们的设置有一些缺陷吗?

    更新

    已经使用iOS 9.3OSX 10.11.4在使用Xcode 7.3.1编译的iPhone 5模拟器上运行上面的项目模拟了问题。

    更新2

    进一步调查显示,该问题可能不在动画中:由于某些原因,给定的设置pan.translationInView(view)会返回意外的值,导致动画跳转。

    部分解决方法

    基于弗拉基米尔的想法,我们通过覆盖hitTest的{​​{1}}方法来部分解决了这个问题:

    UINavigationBar

2 个答案:

答案 0 :(得分:1)

非常有趣的故障。我几天前找到了这个问题的部分解决方案,由于没有人找到完整的解决方案,我会发布这个,也许会有所帮助。

如果您覆盖hitTest的{​​{1}}方法,则可以通过按住UINavigationBar拖动模式来解决此问题:

UINavigationBar

不幸的是,如果你通过按住extension UINavigationBar { override public func hitTest(point: CGPoint, withEvent event: UIEvent?) -> UIView? { guard let view = super.hitTest(point, withEvent: event) else { return nil } if view.isKindOfClass(UIControl) { return super.hitTest(point, withEvent: event) } else { return nil } } } 上的UIBarButtonItem来拖动模态,则故障仍然存在。

您也可以尝试其他方法。

正如您所注意到的,UINavigationBar返回的值不正确,导致动画跳转。 您需要在拖动过程中将此值与模态视图的pan.translationInView(view)坐标进行比较。您可以通过检查模态视图控制器的表示层来获取此值:

y

您可以看到,当... let translation = pan.translationInView(view) if let layer = view.layer.presentationLayer() { print(layer.frame.origin.y) } ... 开始显示错误的值时,pan.translationInView(view)在那一刻仍然是正确的。您可以比较这两个值并在值不正确时找到模式,并通过向layer.frame.origin.y值添加几个点来将其更改为正确。

答案 1 :(得分:0)

我没有完整的解决方案,但我能够减少一定数量的故障。我可以使用iOS 9.3.2在iPhone 5s上重现此问题[通过向下拖动导航栏的屏幕]

问题似乎出现在UIView.animateWithDuration的{​​{1}}区块中。通过注释延迟和选项,即将它们保持为默认值,可以减少视图的跳跃。你也可以尝试检查你获得最小跳跃的不同DismissalAnimator

UIViewAnimationOptions

a question似乎正在处理您面临的同一问题。并且响应从禁用自动布局变化,将 UIView.animateWithDuration(0.3, animations: { dismissedView.frame = finalFrame }, completion: { _ in let didComplete = !transitionContext.transitionWasCancelled() transitionContext.completeTransition(didComplete) } ) 放入动画块[尝试过,两者都不起作用]。