web-dev-qa-db-fra.com

Comment activer le geste de balayage arrière/gauche dans UINavigationController après la définition de leftBarButtonItem?

J'ai eu le problème opposé de ici . Par défaut, dans iOS7, le mouvement de balayage arrière de la pile de UINavigationController pourrait faire apparaître la ViewController présentée. Maintenant, je viens d’appliquer tout le style self.navigationItem.leftBarButtonItem pour tous les ViewControllers.

Voici le code:

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

après cela, le navigationController.interactivePopGestureRecognizer est désactivé. Comment activer le geste pop sans supprimer la variable personnalisée leftBarButtonItem?

Merci!

53
Itachi

Définissez d'abord le délégué dans viewDidLoad:

self.navigationController.interactivePopGestureRecognizer.delegate = self;

Et puis désactivez le geste lorsque vous appuyez sur:

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

Et activez dans viewDidDisappear:

self.navigationController.interactivePopGestureRecognizer.enabled = YES;

Ajoutez également UINavigationControllerDelegate à votre contrôleur de vue. 

56
Lumialxk

Cela fonctionne pour moi quand je fixe le délégué

self.navigationController.interactivePopGestureRecognizer.delegate = self;

puis mettre en œuvre

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

Vous devez gérer deux scénarios:

  1. Lorsque vous placez une nouvelle vue sur la pile
  2. Lorsque vous affichez le contrôleur de vue racine

Si vous avez juste besoin d’une classe de base que vous puissiez utiliser, voici une version de 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
    }
}

Si vous finissez par devoir jouer le rôle de UINavigationControllerDelegate dans une autre classe, vous pouvez écrire un transitaire délégué semblable à cette réponse .

Adapté de la source dans Objective-C: https://github.com/fastred/AHKNavigationController

39
iwasrobbed

ça marche pour moi Swift 3 :

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

et dans ViewDidLoad:

    self.navigationController?.interactivePopGestureRecognizer?.delegate = self
    self.navigationController?.interactivePopGestureRecognizer?.isEnabled = true
39
Yahya Tabba

C’est le meilleur moyen d’activer/désactiver le balayage pour afficher le contrôleur de vue dansiOS 10, Swift 3:

Pour le premier écran [Où vous voulez désactiver le geste de balayage]:  

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

Pour l'écran central [Où vous voulez activer le geste de balayage]:

class FriendListViewController : UIViewController {

//MARK: - View initializers
override func viewDidLoad() {

    super.viewDidLoad()
    swipeToPop()
}

func swipeToPop() {

    self.navigationController?.interactivePopGestureRecognizer?.isEnabled = true;
    self.navigationController?.interactivePopGestureRecognizer?.delegate = nil;
} }
8
Mr. Bean

La définition d’un bouton Retour personnalisé désactive la fonctionnalité de balayage.

La meilleure chose à faire est de sous-classer UINavigationViewController et de se définir en tant que délégué interactivePopGestureRecognizer; vous pouvez alors retourner OUI à partir de gestureRecognizerShouldBegin pour autoriser le balayage.

Par exemple, cela se fait dans AHKNavigationController

Et une version Swift ici: https://stackoverflow.com/a/43433530/308315

3
Axel Guilmin

Swift 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)
}
3
Josh O'Connor

Ceci répondre, mais avec le support du storyboard.

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