【发布时间】:2013-09-27 14:02:28
【问题描述】:
所以我在为 iOS 7 构建的应用程序中有一个导航控制器。 titleView 是可见的,后退按钮和导航栏也是可见的。出于某种原因,交互式弹出手势(从左边缘滑动)不起作用。什么都没发生。当我记录手势时,它不是零。要启用此功能,我需要做些什么特别的事情吗?什么可能导致它不起作用?
【问题讨论】:
标签: ios uinavigationcontroller ios7 gesture
所以我在为 iOS 7 构建的应用程序中有一个导航控制器。 titleView 是可见的,后退按钮和导航栏也是可见的。出于某种原因,交互式弹出手势(从左边缘滑动)不起作用。什么都没发生。当我记录手势时,它不是零。要启用此功能,我需要做些什么特别的事情吗?什么可能导致它不起作用?
【问题讨论】:
标签: ios uinavigationcontroller ios7 gesture
我发现当使用自定义后退按钮时,交互式弹出手势停止工作(我的看法是 Apple 无法预见您的自定义后退按钮的行为方式,因此他们禁用了该手势)。
如前所述,要解决此问题,您可以将interactivePopGestureRecognizer.delegate 属性设置为nil。
在 Swift 中,这可以通过像这样为 :UINavigationController 添加扩展名来轻松地在整个应用程序中完成
extension UINavigationController {
override public func viewDidLoad() {
super.viewDidLoad()
interactivePopGestureRecognizer?.delegate = nil
}
}
更新答案
似乎将代理设置为 nil 会导致应用 UI 在某些情况下冻结(例如,当用户在导航堆栈的顶部视图控制器上向左或向右滑动时)。
因为 gestureRecognizerShouldBegin 委托方法无法在扩展中处理,子类化 UINavigationController 似乎是最好的解决方案:
class NavigationController: UINavigationController, UIGestureRecognizerDelegate {
/// Custom back buttons disable the interactive pop animation
/// To enable it back we set the recognizer to `self`
override func viewDidLoad() {
super.viewDidLoad()
interactivePopGestureRecognizer?.delegate = self
}
func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
return viewControllers.count > 1
}
}
【讨论】:
UINavigationController。在子类中将 interactivePopGestureRecognizer.delegate 设置为 self 并防止在推送新视图控制器时识别交互式弹出手势。
我的回答基于 Eneko 的回答,但仅使用 UINavigationController 上的扩展并在 Swift 5 中工作:
extension UINavigationController: UIGestureRecognizerDelegate {
override open func viewDidLoad() {
super.viewDidLoad()
interactivePopGestureRecognizer?.delegate = self
}
public func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
return viewControllers.count > 1
}
}
【讨论】:
也许有人会觉得这很有帮助。
如果你想隐藏导航栏但使用普通的滑动手势返回和其他导航控制器功能,你应该使用:(navigationBar)
self.navigationController?.navigationBar.isHidden = true
如果你想禁用导航栏(隐藏导航栏,禁用向后滑动)但想要推送视图控制器,你应该使用:(isNavigationBarHidden)
self.navigationController?.isNavigationBarHidden = true
2018 年 12 月 7 日更新:
推荐方式:
如果您的第一个控制器使用隐藏导航栏,但下一个子控制器使用导航栏,当您返回基本视图控制器时,您将看到一个黑色的过渡条代替导航栏。如果您在第一个视图控制器(父亲)中使用,这将很容易解决:
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.navigationController?.setNavigationBarHidden(true, animated: animated)
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
self.navigationController?.setNavigationBarHidden(false, animated: animated)
}
【讨论】:
一般为整个应用添加交互式弹出手势。
XCODE:9.0,Swift:4.0
最好在 AppDelegate.swift 中创建 UINavigationController
// I created a global variable, however not necessarily you will be doing this way
var nvc: UINavigationController!
UIGestureRecognizerDelegate
class AppDelegate: UIResponder, UIApplicationDelegate, UIGestureRecognizerDelegate {
UINavigationController
nvc=UINavigationController()
// For interactive pop gesture
nvc.navigationBar.isHidden=true
nvc?.interactivePopGestureRecognizer?.delegate=self
window=UIWindow()
window?.rootViewController=nvc
window?.makeKeyAndVisible()
// BaseViewController is sample controller i created with xib
nvc.pushViewController(BaseViewController(), animated: true)
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRequireFailureOf otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}
注意:请参阅本节其他帖子了解两者的区别
self.navigationController?.navigationBar.isHidden=true
和
self.navigationController?.isNavigationBarHidden = true
【讨论】:
在 Swift 4 中,我的视图控制器中有一个 UITableView,我解决了这个问题:
override func viewDidLoad() {
super.viewDidLoad()
self.navigationController?.interactivePopGestureRecognizer?.delegate=nil
}
【讨论】:
更有效的答案是 Aaron 和 lojals
先自定义导航控制器,然后把这段代码放到类中
在 ViewDidload 中输入这一行:
self.navigationController.interactivePopGestureRecognizer.delegate = (id<UIGestureRecognizerDelegate>)self;
在课堂上写这个函数
-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer { return YES;}
【讨论】:
看看这个response 和 cmets。您只需将导航控制器的交互式弹出手势识别器的委托设置为nil:
self.navigationController.interactivePopGestureRecognizer.delegate = nil;
将其设置为将其转换为id<UIGestureRecognizerDelegate> 也可以,因为协议中的所有方法都是可选的,但我认为在这种情况下将委托设置为nil 更合适。
【讨论】:
您可以将此行放在 viewDidLoad 方法中。
self.navigationController.interactivePopGestureRecognizer.delegate = (id<UIGestureRecognizerDelegate>)self;
【讨论】:
嗯,看来我只需要设置手势委托并实现以下内容:
-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
return YES;
}
【讨论】: