【问题标题】:UINavigationController Interactive Pop Gesture Not Working?UINavigationController 交互式弹出手势不起作用?
【发布时间】:2013-09-27 14:02:28
【问题描述】:

所以我在为 iOS 7 构建的应用程序中有一个导航控制器。 titleView 是可见的,后退按钮和导航栏也是可见的。出于某种原因,交互式弹出手势(从左边缘滑动)不起作用。什么都没发生。当我记录手势时,它不是零。要启用此功能,我需要做些什么特别的事情吗?什么可能导致它不起作用?

【问题讨论】:

    标签: ios uinavigationcontroller ios7 gesture


    【解决方案1】:

    我发现当使用自定义后退按钮时,交互式弹出手势停止工作(我的看法是 Apple 无法预见您的自定义后退按钮的行为方式,因此他们禁用了该手势)。

    如前所述,要解决此问题,您可以将interactivePopGestureRecognizer.delegate 属性设置为nil

    在 Swift 中,这可以通过像这样为 UINavigationController 添加扩展名来轻松地在整个应用程序中完成

    extension UINavigationController {
    
        override public func viewDidLoad() {
            super.viewDidLoad()
            interactivePopGestureRecognizer?.delegate = nil
        }
    
    }
    

    更新答案

    似乎将代理设置为 nil 会导致应用 UI 在某些情况下冻结(例如,当用户在导航堆栈的顶部视图控制器上向左或向右滑动时)。

    因为 gestureRecognizerShouldBegin 委托方法无法在扩展中处理,子类化 UINavigationController 似乎是最好的解决方案:

    class NavigationController: UINavigationController, UIGestureRecognizerDelegate {
    
        /// Custom back buttons disable the interactive pop animation
        /// To enable it back we set the recognizer to `self`
        override func viewDidLoad() {
            super.viewDidLoad()
            interactivePopGestureRecognizer?.delegate = self
        }
    
        func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
            return viewControllers.count > 1
        }
    
    }
    

    【讨论】:

    • 这似乎可行,但事实证明在某些情况下它会冻结应用程序。我认为在推送视图控制器时触发交互式弹出手势时会发生这种情况。更安全的方法是继承UINavigationController。在子类中将 interactivePopGestureRecognizer.delegate 设置为 self 并防止在推送新视图控制器时识别交互式弹出手势。
    • 确实,我也发现了这个问题,似乎只影响导航控制器堆栈的顶视图控制器。我已经用基于子类化的不同解决方案更新了我的答案。
    • @Eneko Alonso 完美!正如您所说,如果用户向左或向右滑动然后点击按钮 - 推送视图控制器会出现故障。子类化可以 100% 解决问题
    • @EnekoAlonso 当我将导航栏设置为隐藏时,我遇到了类似的问题。我失去了向后滑动的功能。无论如何你可以帮助解决这个问题吗?为了清楚起见,我发布了这个问题:stackoverflow.com/questions/48954413/…
    【解决方案2】:

    如果你觉得你已经尝试了所有的解决方案并伸展你的头,那么你来对地方了。

    Goto simulator > Window > Enable Show Device Bezels
    

    现在尝试模拟向后滑动手势。

    【讨论】:

    • 这太愚蠢了,但它确实有效!为什么苹果改变了这一点?......谢谢一堆!
    • 非常感谢 SoftDesigner ✅。
    【解决方案3】:

    我的回答基于 Eneko 的回答,但仅使用 UINavigationController 上的扩展并在 Swift 5 中工作:

    extension UINavigationController: UIGestureRecognizerDelegate {
    
        override open func viewDidLoad() {
            super.viewDidLoad()
            interactivePopGestureRecognizer?.delegate = self
        }
    
        public func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
            return viewControllers.count > 1
        }
    }
    

    【讨论】:

    • IOS 13 对我不起作用。您有什么建议吗?
    • 使用 ios 13.1
    【解决方案4】:

    也许有人会觉得这很有帮助。

    如果你想隐藏导航栏但使用普通的滑动手势返回和其他导航控制器功能,你应该使用:(navigationBar)

    self.navigationController?.navigationBar.isHidden = true
    

    如果你想禁用导航栏(隐藏导航栏,禁用向后滑动)但想要推送视图控制器,你应该使用:(isNavigationBarHidden)

    self.navigationController?.isNavigationBarHidden = true
    

    2018 年 12 月 7 日更新:

    推荐方式:

    如果您的第一个控制器使用隐藏导航栏,但下一个子控制器使用导航栏,当您返回基本视图控制器时,您将看到一个黑色的过渡条代替导航栏。如果您在第一个视图控制器(父亲)中使用,这将很容易解决:

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        self.navigationController?.setNavigationBarHidden(true, animated: animated)
    }
    
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        self.navigationController?.setNavigationBarHidden(false, animated: animated)
    }
    

    【讨论】:

      【解决方案5】:

      一般为整个应用添加交互式弹出手势。

      XCODE:9.0,Swift:4.0

      最好在 AppDelegate.swift 中创建 UINavigationController

      1. 创建导航控制器
      // I created a global variable, however not necessarily you will be doing this way
      var nvc: UINavigationController!
      
      1. 实现UIGestureRecognizerDelegate
      class AppDelegate: UIResponder, UIApplicationDelegate, UIGestureRecognizerDelegate {
      
      1. 在应用程序 didFinishLaunchingWithOptions 函数中实例化 UINavigationController
      nvc=UINavigationController()
      
      // For interactive pop gesture
      nvc.navigationBar.isHidden=true
      nvc?.interactivePopGestureRecognizer?.delegate=self
      
      1. 额外步骤,在应用程序 didFinishLaunchingWithOptions 函数中将控制器添加到导航控制器
      window=UIWindow()
      window?.rootViewController=nvc
      window?.makeKeyAndVisible()
      
      // BaseViewController is sample controller i created with xib
      nvc.pushViewController(BaseViewController(), animated: true)
      
      1. 实现手势识别器,将以下代码添加到 AppDelegate.swift
      func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRequireFailureOf otherGestureRecognizer: UIGestureRecognizer) -> Bool {
              return true
          }
      



      注意:请参阅本节其他帖子了解两者的区别

      self.navigationController?.navigationBar.isHidden=true
      

      self.navigationController?.isNavigationBarHidden = true
      

      【讨论】:

        【解决方案6】:

        在 Swift 4 中,我的视图控制器中有一个 UITableView,我解决了这个问题:

        override func viewDidLoad() {
            super.viewDidLoad()
            self.navigationController?.interactivePopGestureRecognizer?.delegate=nil
        }
        

        【讨论】:

          【解决方案7】:

          更有效的答案是 Aaron 和 lojals

          先自定义导航控制器,然后把这段代码放到类中

          在 ViewDidload 中输入这一行:

          self.navigationController.interactivePopGestureRecognizer.delegate = (id<UIGestureRecognizerDelegate>)self;
          

          在课堂上写这个函数

          -(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer { return YES;}
          

          【讨论】:

            【解决方案8】:

            看看这个response 和 cmets。您只需将导航控制器的交互式弹出手势识别器的委托设置为nil

            self.navigationController.interactivePopGestureRecognizer.delegate = nil;
            

            将其设置为将其转换为id&lt;UIGestureRecognizerDelegate&gt; 也可以,因为协议中的所有方法都是可选的,但我认为在这种情况下将委托设置为nil 更合适。

            【讨论】:

            • 我只在 viewDidAppear 中成功了
            • 这个“有效”但不久之后会导致非常奇怪的问题,以至于冻结应用程序(在 iOS 8 设备上测试)
            【解决方案9】:

            您可以将此行放在 viewDidLoad 方法中。

            self.navigationController.interactivePopGestureRecognizer.delegate = (id<UIGestureRecognizerDelegate>)self;
            

            【讨论】:

              【解决方案10】:

              嗯,看来我只需要设置手势委托并实现以下内容:

              -(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
              
                  return YES;
              
              }
              

              【讨论】:

              • 我已经检查过这个但非常令人毛骨悚然的问题,当我修复这个问题时,如果用户滑动一半然后回来,我会看到下一个控制器与前一个视图控制器重叠。我看到了上一个视图控制器,下一个重叠的像透明玻璃一样透明。所以用户恰好被锁定在这个状态。任何想法。这是 View 确实出现/将出现的处理问题。
              猜你喜欢
              • 1970-01-01
              • 2014-06-22
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2014-10-15
              • 2019-08-01
              • 1970-01-01
              相关资源
              最近更新 更多