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

Jak*_*ano 7 uinavigationcontroller modalviewcontroller ios

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

建立:

  1. 用至少一个按钮UIViewController嵌入的设置UINavigationControllerUINavigationBar
  2. 模态地呈现另一个UIViewController嵌入在UINavigationController中的至少一个按钮UINavigationBar
  3. UIPanGestureRecognizer在modaly上设置UINavigationController驱动器UIPercentDrivenInteractiveTransition
  4. 拖动模态向下"按住"它 UINavigationBar

问题:

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

  • 毛刺只出现在:

    1. 两者UINavigationBar都至少有一个按钮
    2. 你通过点"按住"模态 UINavigationBar

最小的例子可以从github repo下载.

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

更新

问题已经模拟了与iPhone 5的模拟器上面跑项目iOS 9.3,OSX 10.11.4与Xcode的编译7.3.1.

更新2

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

部分解决方法

根据弗拉基米尔的想法,我们通过重写hitTest方法部分解决了这个问题UINavigationBar:

class DraggableNavigationBar: UINavigationBar {

    override func hitTest(point: CGPoint, withEvent event: UIEvent?) -> UIView? {
        guard let view = super.hitTest(point, withEvent: event) else { return nil }

        if view is UIControl || pointIsInsideNavigationButton(point) {
            return view
        } else {
            return nil
        }
    }

    private func pointIsInsideNavigationButton(point: CGPoint) -> Bool {
        return subviews
            .filter { $0.frame.contains(point) }
            .filter { String($0.dynamicType) == "UINavigationItemButtonView" }
            .isEmpty == false
    }
}
Run Code Online (Sandbox Code Playgroud)

Vla*_*r K 1

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

如果您覆盖hitTest方法,则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
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

不幸的是,如果您按住 拖动模态UIBarButtonItemUINavigationBar故障仍然存在。

您还可以尝试另一种方法。

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

...

let translation = pan.translationInView(view)

if let layer = view.layer.presentationLayer() {
            print(layer.frame.origin.y)
}

...
Run Code Online (Sandbox Code Playgroud)

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