ios - ¿Cómo habilitar el gesto de deslizamiento hacia atrás/izquierda en UINavigationController después de configurar leftBarButtonItem?
navigation bar ios 11 (9)
Tengo el problema opuesto desde
here
.
De forma predeterminada en
iOS7
, el gesto de deslizar hacia atrás de la pila de
UINavigationController
podría
UINavigationController
el
ViewController
presentado.
Ahora acabo de uniformar todo el estilo
self.navigationItem.leftBarButtonItem
para todos los
ViewControllers
.
Aquí está el código:
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithImage:LOADIMAGE(@"back_button") style:UIBarButtonItemStylePlain target:self action:@selector(popCurrentViewController)];
después de eso,
navigationController.interactivePopGestureRecognizer
está deshabilitado.
¿Cómo podría habilitar el gesto pop sin eliminar el
leftBarButtonItem
personalizado?
¡Gracias!
A mí me funciona cuando configuro el delegado
self.navigationController.interactivePopGestureRecognizer.delegate = self;
y luego implementar
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldBeRequiredToFailByGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
return YES;
}
Esta es la mejor manera de habilitar / deshabilitar el deslizamiento al controlador de vista emergente en iOS 10, Swift 3 :
Para la primera pantalla [donde desea desactivar el gesto de deslizar]:
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
} }
Para la pantalla central [donde desea habilitar el gesto de deslizar]:
class FriendListViewController : UIViewController {
//MARK: - View initializers
override func viewDidLoad() {
super.viewDidLoad()
swipeToPop()
}
func swipeToPop() {
self.navigationController?.interactivePopGestureRecognizer?.isEnabled = true;
self.navigationController?.interactivePopGestureRecognizer?.delegate = nil;
} }
Establecer un botón de retroceso personalizado deshabilita la función de deslizar hacia atrás.
Lo mejor que puede hacer para mantenerlo es subclasificar
UINavigationViewController
y establecerse como el delegado
interactivePopGestureRecognizer
;
entonces puede devolver SÍ desde
gestureRecognizerShouldBegin
para permitir el deslizamiento hacia atrás.
Por ejemplo, esto se hace en https://github.com/fastred/AHKNavigationController
Y una versión Swift aquí: https://.com/a/43433530/308315
Necesita manejar dos escenarios:
- Cuando empujas una nueva vista a la pila
- Cuando muestra el controlador de vista raíz
Si solo necesita una clase base que pueda usar, aquí hay una versión 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 termina necesitando actuar como un
UINavigationControllerDelegate
en otra clase, puede escribir un reenviador de delegado
similar a esta respuesta
.
Adaptado de la fuente en Objective-C: https://github.com/fastred/AHKNavigationController
Para aquellos que todavía tienen problemas con esto, intente separar las dos líneas como se muestra a continuación.
override func viewDidLoad() {
self.navigationController!.interactivePopGestureRecognizer!.delegate = self
...
override func viewWillAppear(_ animated: Bool) {
self.navigationController!.interactivePopGestureRecognizer!.isEnabled = true
...
Obviamente, en mi aplicación,
interactivePopGestureRecognizer! .isEnabled
se restableció a
false
antes de que la vista se mostrara por alguna razón.
Primer conjunto delegado en viewDidLoad:
self.navigationController.interactivePopGestureRecognizer.delegate = self;
Y luego deshabilita el gesto al presionar:
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated {
[super pushViewController:viewController animated:animated];
self.interactivePopGestureRecognizer.enabled = NO;
}
Y habilitar en viewDidDisappear:
self.navigationController.interactivePopGestureRecognizer.enabled = YES;
Además, agregue
UINavigationControllerDelegate
a su controlador de vista.
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)
}
me funciona Swift 3 :
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldBeRequiredToFailBy otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}
y en ViewDidLoad:
self.navigationController?.interactivePopGestureRecognizer?.delegate = self
self.navigationController?.interactivePopGestureRecognizer?.isEnabled = true
This respuesta, pero con soporte de guión gráfico.
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
}