ios 设置 leftBarButtonItem 后如何在 UINavigationController 中启用向后/向左滑动手势?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/34942571/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to enable back/left swipe gesture in UINavigationController after setting leftBarButtonItem?
提问by Itachi
I got the opposite issue from here.
By default in iOS7
, back swipe gesture of UINavigationController
's stack could pop the presented ViewController
. Now I just uniformed all the self.navigationItem.leftBarButtonItem
style for all the ViewControllers
.
我从这里得到了相反的问题。默认情况下iOS7
,UINavigationController
堆栈的向后滑动手势可以弹出呈现的ViewController
. 现在我只是统一self.navigationItem.leftBarButtonItem
了所有ViewControllers
.
Here is the code:
这是代码:
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithImage:LOADIMAGE(@"back_button") style:UIBarButtonItemStylePlain target:self action:@selector(popCurrentViewController)];
after that, the navigationController.interactivePopGestureRecognizer
is disabled. How could I make the pop gesture enabled without removing the custom leftBarButtonItem
?
之后,将navigationController.interactivePopGestureRecognizer
被禁用。如何在不删除自定义的情况下启用弹出手势leftBarButtonItem
?
Thanks!
谢谢!
回答by Lumialxk
First set delegate in viewDidLoad:
首先在 viewDidLoad 中设置委托:
self.navigationController.interactivePopGestureRecognizer.delegate = self;
And then disable gesture when pushing:
然后在按下时禁用手势:
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated {
[super pushViewController:viewController animated:animated];
self.interactivePopGestureRecognizer.enabled = NO;
}
And enable in viewDidDisappear:
并在 viewDidDisappear 中启用:
self.navigationController.interactivePopGestureRecognizer.enabled = YES;
Also, add UINavigationControllerDelegate
to your view controller.
此外,添加UINavigationControllerDelegate
到您的视图控制器。
回答by iwasrobbed
You need to handle two scenarios:
您需要处理两种情况:
- When you're pushing a new view onto the stack
- When you're showing the root view controller
- 当您将新视图推入堆栈时
- 当您显示根视图控制器时
If you just need a base class you can use, here's a Swift 3 version:
如果你只需要一个可以使用的基类,这里有一个 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
}
}
If you end up needing to act as a UINavigationControllerDelegate
in another class, you can write a delegate forwarder similar to this answer.
如果您最终需要UINavigationControllerDelegate
在另一个类中充当 a ,您可以编写一个类似于此答案的委托转发器。
Adapted from source in Objective-C: https://github.com/fastred/AHKNavigationController
改编自 Objective-C 中的源代码:https: //github.com/fastred/AHKNavigationController
回答by hfossli
It works for me when I set the delegate
当我设置委托时它对我有用
self.navigationController.interactivePopGestureRecognizer.delegate = self;
and then implement
然后执行
Swift
迅速
extension MyViewController:UIGestureRecognizerDelegate {
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldBeRequiredToFailBy otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}
}
Objective-C
目标-C
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldBeRequiredToFailByGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
return YES;
}
回答by Yahya Tabba
it works for me Swift 3:
它适用于我Swift 3:
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldBeRequiredToFailBy otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}
and in ViewDidLoad:
在 ViewDidLoad 中:
self.navigationController?.interactivePopGestureRecognizer?.delegate = self
self.navigationController?.interactivePopGestureRecognizer?.isEnabled = true
回答by Mr. Bean
This is the best way to enable/ disable swipe to pop view controller in iOS 10, Swift 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;
} }
回答by Josh O'Connor
Swift 3:
斯威夫特 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)
}
回答by Axel Guilmin
Setting a custom back button disable the swipe back feature.
设置自定义后退按钮会禁用向后滑动功能。
The best thing to do to keep it is to subclass UINavigationViewController
and set itself as the interactivePopGestureRecognizer
delegate; then you can return YES from gestureRecognizerShouldBegin
to allow the swipe back.
保持它的最好办法是子类化UINavigationViewController
并将自己设置为interactivePopGestureRecognizer
委托;然后您可以返回 YESgestureRecognizerShouldBegin
以允许向后滑动。
For example, this is done in AHKNavigationController
例如,这是在AHKNavigationController 中完成的
And a Swift version here: https://stackoverflow.com/a/43433530/308315
这里有一个 Swift 版本:https: //stackoverflow.com/a/43433530/308315
回答by Burcu Kutluay
I did not need to add gestureRecognizer functions for it. It was enough for me to add following code blocks at viewDidLoad:
我不需要为它添加gestureRecognizer 函数。我在 viewDidLoad 中添加以下代码块就足够了:
override func viewDidLoad() {
super.viewDidLoad()
self.navigationController?.interactivePopGestureRecognizer?.delegate = nil
self.navigationController?.interactivePopGestureRecognizer?.isEnabled = true
}
回答by Jonny
Thisanswer, but with storyboard support.
这个答案,但有故事板支持。
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
}
回答by Andriy Gordiychuk
If you want this behaviour everywhere in your app and don't want to add anything to individual viewDidAppear
etc. then you should create a subclass
如果您希望在您的应用程序中随处可见这种行为,并且不想向个人viewDidAppear
等添加任何内容,那么您应该创建一个子类
class QFNavigationController:UINavigationController, UIGestureRecognizerDelegate, UINavigationControllerDelegate{
override func viewDidLoad() {
super.viewDidLoad()
interactivePopGestureRecognizer?.delegate = self
delegate = self
}
override func pushViewController(_ viewController: UIViewController, animated: Bool) {
super.pushViewController(viewController, animated: animated)
interactivePopGestureRecognizer?.isEnabled = false
}
func navigationController(_ navigationController: UINavigationController, didShow viewController: UIViewController, animated: Bool) {
interactivePopGestureRecognizer?.isEnabled = true
}
// IMPORTANT: without this if you attempt swipe on
// first view controller you may be unable to push the next one
func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
return viewControllers.count > 1
}
}
Now, whenever you use QFNavigationController
you get the desired experience.
现在,无论何时使用,QFNavigationController
您都会获得所需的体验。