我从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
的情况下启用弹出手势?
谢谢!
答案 0 :(得分:63)
首先在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;
另外,将UINavigationControllerDelegate
添加到视图控制器。
答案 1 :(得分:46)
当我设置代理
时,它适用于我self.navigationController.interactivePopGestureRecognizer.delegate = self;
然后实施
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldBeRequiredToFailByGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
return YES;
}
答案 2 :(得分:46)
您需要处理两种情况:
如果您只需要一个可以使用的基类,这里是一个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 :(得分:43)
它适用于我 Swift 3 :
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldBeRequiredToFailBy otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}
并在ViewDidLoad中:
self.navigationController?.interactivePopGestureRecognizer?.delegate = self
self.navigationController?.interactivePopGestureRecognizer?.isEnabled = true
答案 4 :(得分:11)
这是在 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;
} }
答案 5 :(得分:6)
在Swift中,您可以执行以下代码
import UIKit
extension UINavigationController: UIGestureRecognizerDelegate {
open override func viewDidLoad() {
super.viewDidLoad()
interactivePopGestureRecognizer?.delegate = self
}
public func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
return viewControllers.count > 1
}
}
以上代码可帮助您快速向左返回到Facebook,Twitter等以前的控制器。
答案 6 :(得分:3)
设置自定义后退按钮可禁用滑动后退功能。
保持它的最好方法是继承UINavigationViewController
并将自己设置为interactivePopGestureRecognizer
委托;然后你可以从gestureRecognizerShouldBegin
返回YES以允许滑动。
例如,这是在AHKNavigationController
中完成的这里有一个Swift版本:https://stackoverflow.com/a/43433530/308315
答案 7 :(得分: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)
}
答案 8 :(得分:3)
如果您希望在应用程序中的任何位置都具有这种行为,并且不想向单个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
}
}
现在,每当您使用QFNavigationController
时,您都会获得理想的体验。
答案 9 :(得分:1)
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
}
答案 10 :(得分:0)
我不需要为其添加gestureRecognizer函数。对于我来说,在viewDidLoad中添加以下代码块就足够了:
override func viewDidLoad() {
super.viewDidLoad()
self.navigationController?.interactivePopGestureRecognizer?.delegate = nil
self.navigationController?.interactivePopGestureRecognizer?.isEnabled = true
}
答案 11 :(得分:0)
我们正在努力解决some old bugs,因为它是“有意设计的”,因此尚未得到解决。在尝试取消interactivePopGestureRecognizer
的委托时,我遇到了其他地方提到的冻结问题@iwasrobbed,这似乎应该可行。如果您想重新使用backBarButtonItem
,您可以可以自定义滑动行为。
当interactivePopGestureRecognizer
隐藏时,我也遇到UINavigationBar
无法正常工作的情况。如果您担心隐藏导航栏,请在实现错误的解决方法之前重新考虑您的设计。
答案 12 :(得分:0)
大多数答案都与在代码上执行有关。但我给你一个可以在Storyboard上运行的软件。是!您没看错。
单击主UINavigationController
并导航至其Identity Inspector
标签。
在User Defined Runtime Attributes
下,将名为interactivePopGestureRecognizer.enabled
的单个运行时属性设置为true
。或者以图形方式,您必须启用下图所示的复选框。
就是这样。你很好您的后向手势将一直有效。
答案 13 :(得分:0)
Swift 5,在 viewDidLoad 方法中只添加这两个:
override func viewDidLoad() {
super.viewDidLoad()
navigationController?.interactivePopGestureRecognizer?.delegate = self
navigationController?.interactivePopGestureRecognizer?.isEnabled = true
}
答案 14 :(得分:0)
我在启用和禁用与弹出视图控制器的滑动交互时遇到问题。
我有一个基本的导航控制器,我的应用流程就像推送 Splash VC、推送 Main VC,然后推送 Some VC 一样。
我想滑动以从 Some VC 返回到 Main VC。还要禁用滑动以防止从主 VC 返回飞溅。
经过下面的一些尝试对我有用。
extension MainViewController : UIGestureRecognizerDelegate{
func disableSwipeToPop() {
self.navigationController?.interactivePopGestureRecognizer?.isEnabled = true
self.navigationController?.interactivePopGestureRecognizer?.delegate = self
}
func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
if gestureRecognizer == self.navigationController?.interactivePopGestureRecognizer {
return false
}
return true
}
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
self.disableSwipeToPop()
}
extension SomeViewController{
func enableSwipeToPop() {
self.navigationController?.interactivePopGestureRecognizer?.isEnabled = true
self.navigationController?.interactivePopGestureRecognizer?.delegate = nil
}
}
override func viewDidLoad() {
super.viewDidLoad()
self.enableSwipeToPop()
}
就是这样。此外,如果您尝试在 viewWillAppear 上禁用滑动,当用户停止滑动以取消操作时,您可能会失去再次滑动的能力。
答案 15 :(得分:-1)
对于仍然遇到此问题的人,请尝试将两行分开,如下所示。
override func viewDidLoad() {
self.navigationController!.interactivePopGestureRecognizer!.delegate = self
...
override func viewWillAppear(_ animated: Bool) {
self.navigationController!.interactivePopGestureRecognizer!.isEnabled = true
...
显然,在我的应用中,
interactivePopGestureRecognizer!.isEnabled
由于某种原因在显示视图之前已重置为false
。