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

问题描述 投票:60回答:9

我从here得到了相反的问题。默认情况下,在iOS7中,UINavigationController堆栈的向后轻扫手势可能会弹出显示的ViewController。现在,我统一了所有self.navigationItem.leftBarButtonItem的所有ViewControllers样式。

这里是代码:

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

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

谢谢!

ios objective-c uinavigationcontroller uinavigationbar uinavigationitem
9个回答
67
投票
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;

此外,将UINavigationControllerDelegate添加到您的视图控制器。


59
投票

当您将新视图推入堆栈时

    显示根视图控制器时
  • 如果您只需要可以使用的基类,则为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

  • 52
    投票
    self.navigationController.interactivePopGestureRecognizer.delegate = self;

    然后执行

    Swift

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

    Objective-C

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


    48
    投票
    Swift 3:

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

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

    12
    投票

    iOS 10,Swift 3:

    中启用/禁用滑动弹出视图控制器的最佳方法。对于第一屏幕[您要禁用滑动手势的地方]:

    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 } }

    对于中间屏幕[您要启用滑动手势的位置]:

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


    4
    投票
    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) }

    3
    投票
    要做的最好的办法是继承UINavigationViewController的子类并将其自身设置为interactivePopGestureRecognizer的委托;那么您可以从gestureRecognizerShouldBegin中返回“是”以允许向后滑动。

    例如,在AHKNavigationController中完成

    以及此处的Swift版本:https://stackoverflow.com/a/43433530/308315


    1
    投票
    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
    © www.soinside.com 2019 - 2024. All rights reserved.