首页 文章

如何在设置leftBarButtonItem后在UINavigationController中启用后退/左侧滑动手势?

提问于
浏览
49

我从here得到了相反的问题 . 默认情况下,在 iOS7 中, UINavigationController 堆栈的后滑动手势可以弹出呈现的 ViewController . 现在我只为所有 ViewControllers 制作了所有 self.navigationItem.leftBarButtonItem 样式 .

这是代码:

self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithImage:LOADIMAGE(@"back_button") style:UIBarButtonItemStylePlain target:self action:@selector(popCurrentViewController)];

之后, navigationController.interactivePopGestureRecognizer 被禁用 . 如何在不删除自定义 leftBarButtonItem 的情况下启用弹出手势?

谢谢!

9 回答

  • 0

    首先在viewDidLoad中设置委托:

    self.navigationController.interactivePopGestureRecognizer.delegate = self;
    

    然后在推送时禁用手势:

    - (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated {
        [super pushViewController:viewController animated:animated];
        self.interactivePopGestureRecognizer.enabled = NO;
    }
    

    并在viewDidDisappear中启用:

    self.navigationController.interactivePopGestureRecognizer.enabled = YES;
    
  • 3

    当我设置委托时,它适用于我

    self.navigationController.interactivePopGestureRecognizer.delegate = self;
    

    然后实施

    - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldBeRequiredToFailByGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
    {
        return YES;
    }
    
  • 41

    它对我有用 Swift 3

    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldBeRequiredToFailBy otherGestureRecognizer: UIGestureRecognizer) -> Bool {
            return true
        }
    

    并在ViewDidLoad中:

    self.navigationController?.interactivePopGestureRecognizer?.delegate = self
        self.navigationController?.interactivePopGestureRecognizer?.isEnabled = true
    
  • 32

    您需要处理两种情况:

    • 当您将新视图推入堆栈时

    • 当您显示根视图控制器时

    如果您只需要一个可以使用的基类,这里是一个Swift 3版本:

    import UIKit
    
    final class SwipeNavigationController: UINavigationController {
    
        // MARK: - Lifecycle
    
        override init(rootViewController: UIViewController) {
            super.init(rootViewController: rootViewController)
        }
    
        override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
            super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
    
            delegate = self
        }
    
        required init?(coder aDecoder: NSCoder) { 
            super.init(coder: aDecoder) 
    
            delegate = self 
        }
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            // This needs to be in here, not in init
            interactivePopGestureRecognizer?.delegate = self
        }
    
        deinit {
            delegate = nil
            interactivePopGestureRecognizer?.delegate = nil
        }
    
        // MARK: - Overrides
    
        override func pushViewController(_ viewController: UIViewController, animated: Bool) {
            duringPushAnimation = true
    
            super.pushViewController(viewController, animated: animated)
        }
    
        // MARK: - Private Properties
    
        fileprivate var duringPushAnimation = false
    
    }
    
    // MARK: - UINavigationControllerDelegate
    
    extension SwipeNavigationController: UINavigationControllerDelegate {
    
        func navigationController(_ navigationController: UINavigationController, didShow viewController: UIViewController, animated: Bool) {
            guard let swipeNavigationController = navigationController as? SwipeNavigationController else { return }
    
            swipeNavigationController.duringPushAnimation = false
        }
    
    }
    
    // MARK: - UIGestureRecognizerDelegate
    
    extension SwipeNavigationController: UIGestureRecognizerDelegate {
    
        func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
            guard gestureRecognizer == interactivePopGestureRecognizer else {
                return true // default value
            }
    
            // Disable pop gesture in two situations:
            // 1) when the pop animation is in progress
            // 2) when user swipes quickly a couple of times and animations don't have time to be performed
            return viewControllers.count > 1 && duringPushAnimation == false
        }
    }
    

    如果您最终需要在另一个类中充当 UINavigationControllerDelegate ,则可以编写委托转发器similar to this answer .

    改编自Objective-C的来源:https://github.com/fastred/AHKNavigationController

  • 3

    这是在 iOS 10, Swift 3 中启用/禁用滑动到弹出视图控制器的最佳方法:

    For First Screen [ Where you want to Disable Swipe gesture ] :

    class SignUpViewController : UIViewController,UIGestureRecognizerDelegate {
    
    //MARK: - View initializers
    override func viewDidLoad() {
        super.viewDidLoad()
    }
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        swipeToPop()
    }
    
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
    
    func swipeToPop() {
    
        self.navigationController?.interactivePopGestureRecognizer?.isEnabled = true;
        self.navigationController?.interactivePopGestureRecognizer?.delegate = self;
    }
    
    func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
    
        if gestureRecognizer == self.navigationController?.interactivePopGestureRecognizer {
            return false
        }
        return true
    } }
    

    For middle screen [ Where you want to Enable Swipe gesture ] :

    class FriendListViewController : UIViewController {
    
    //MARK: - View initializers
    override func viewDidLoad() {
    
        super.viewDidLoad()
        swipeToPop()
    }
    
    func swipeToPop() {
    
        self.navigationController?.interactivePopGestureRecognizer?.isEnabled = true;
        self.navigationController?.interactivePopGestureRecognizer?.delegate = nil;
    } }
    
  • 52

    斯威夫特3:

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
    
        self.navigationController?.interactivePopGestureRecognizer?.delegate = self
    }
    
    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
        return true
    }
    
    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRequireFailureOf otherGestureRecognizer: UIGestureRecognizer) -> Bool {
        return (otherGestureRecognizer is UIScreenEdgePanGestureRecognizer)
    }
    
  • 5

    设置自定义后退按钮可禁用滑动后退功能 .

    保持它的最好的方法是子类 UINavigationViewController 并将自己设置为 interactivePopGestureRecognizer 委托;然后你可以从 gestureRecognizerShouldBegin 返回YES以允许滑动 .

    例如,这是在AHKNavigationController中完成的

    这里有一个Swift版本:https://stackoverflow.com/a/43433530/308315

  • 38

    This答案,但有故事板支持 .

    class SwipeNavigationController: UINavigationController {
    
        // MARK: - Lifecycle
    
        override init(rootViewController: UIViewController) {
            super.init(rootViewController: rootViewController)
        }
    
        override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
            super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
    
            self.setup()
        }
    
        required init?(coder aDecoder: NSCoder) {
            super.init(coder: aDecoder)
    
            self.setup()
        }
    
        private func setup() {
            delegate = self
        }
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            // This needs to be in here, not in init
            interactivePopGestureRecognizer?.delegate = self
        }
    
        deinit {
            delegate = nil
            interactivePopGestureRecognizer?.delegate = nil
        }
    
        // MARK: - Overrides
    
        override func pushViewController(_ viewController: UIViewController, animated: Bool) {
            duringPushAnimation = true
    
            super.pushViewController(viewController, animated: animated)
        }
    
        // MARK: - Private Properties
    
        fileprivate var duringPushAnimation = false
    }
    
  • -1

    对于仍然遇到此问题的人,请尝试将两行分开,如下所示 .

    override func viewDidLoad() {
        self.navigationController!.interactivePopGestureRecognizer!.delegate = self
        ...
    
    override func viewWillAppear(_ animated: Bool) {
        self.navigationController!.interactivePopGestureRecognizer!.isEnabled = true
        ...
    

    显然,在我的应用中,

    interactivePopGestureRecognizer!.isEnabled

    在显示视图之前由于某种原因重置为 false .

相关问题