Swift - 自定义导航栏leftBarButtonItems导致滑动返回失效问题解决
作者:hangge | 2016-03-21 21:48
(本文代码已升级至Swift4)
(如何自定义导航栏左侧按钮可以看这篇文章:Swift - 修改导航栏“返回”按钮文字,图标)
1,让滑动返回继续有效
(1)解决办法是让 ViewController 实现 UIGestureRecognizerDelegate 协议。
(2)当这样做还不够,虽然滑动返回功能又恢复了,但这时还会出现另一个问题:即在一级视图(根视图)中,我们用手势滑动一下,然后进入二级视图,会发现画面卡住死在那里了。
所以我们还要判断下当前是处于哪个层级的页面,如果是根视图页面就禁用滑动返回手势。
import UIKit class DetailViewController: UIViewController, UIGestureRecognizerDelegate { override func viewDidLoad() { self.title = "hangge.com" let button = UIButton(type: .system) button.frame = CGRect(x:0, y:0, width:65, height:30) button.setImage(UIImage(named:"back"), for: .normal) button.setTitle("返回", for: .normal) button.addTarget(self, action: #selector(backToPrevious), for: .touchUpInside) let leftBarBtn = UIBarButtonItem(customView: button) //用于消除左边空隙,要不然按钮顶不到最前面 let spacer = UIBarButtonItem(barButtonSystemItem: .fixedSpace, target: nil, action: nil) spacer.width = -10; self.navigationItem.leftBarButtonItems = [spacer,leftBarBtn] //启用滑动返回(swipe back) self.navigationController?.interactivePopGestureRecognizer!.delegate = self } //是否允许手势 func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool { if (gestureRecognizer == self.navigationController?.interactivePopGestureRecognizer) { //只有二级以及以下的页面允许手势返回 return self.navigationController!.viewControllers.count > 1 } return true } //返回按钮点击响应 @objc func backToPrevious(){ self.navigationController?.popViewController(animated: true) } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() } }注意:启用滑动返回(swipe back)对当前 NavigationController 管理的所有 viewController 都有效。不需要每个 ViewController 都调用那个方法,我们只要保证它们在同一个 UINavigationController 里即可。
比如我们可以在根视图(ViewController)中启用滑动返回,效果也是一样的:
import UIKit class ViewController: UIViewController, UIGestureRecognizerDelegate { override func viewDidLoad() { super.viewDidLoad() //启用滑动返回(swipe back) self.navigationController?.interactivePopGestureRecognizer!.delegate = self } //是否允许手势 func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool { if (gestureRecognizer == self.navigationController?.interactivePopGestureRecognizer) { //只有二级以及以下的页面允许手势返回 return self.navigationController!.viewControllers.count > 1 } return true } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() } }
2,与webview手势冲突造成无法滑动返回
正常情况下通过上面的设置后就可以滑动返回了,但有时我们在页面内放置了一个 webview 并加载网页进来后,会发现滑动返回的功能又失效了。(webview如果没加载页面则没有这个问题) 问题原因:由于 webview 加载的这个页面自身内部需要用到手势操作,或者 webview 放大之后需要一些滑动查看操作,于是便造成事件冲突。
解决办法:新建了一个 tap手势,设置代理,同时实现允许多个手势并发的代理方法
import UIKit class DetailViewController: UIViewController, UIGestureRecognizerDelegate { @IBOutlet weak var webView: UIWebView! override func viewDidLoad() { self.title = "hangge.com" let urlobj = URL(string:"http://www.hangge.com") let request = URLRequest(url:urlobj!) webView.loadRequest(request); let button = UIButton(type: .system) button.frame = CGRect(x:0, y:0, width:65, height:30) button.setImage(UIImage(named:"back"), for: .normal) button.setTitle("返回", for: .normal) button.addTarget(self, action: #selector(backToPrevious), for: .touchUpInside) let leftBarBtn = UIBarButtonItem(customView: button) //用于消除左边空隙,要不然按钮顶不到最前面 let spacer = UIBarButtonItem(barButtonSystemItem: .fixedSpace, target: nil, action: nil) spacer.width = -10; self.navigationItem.leftBarButtonItems = [spacer,leftBarBtn] //启用滑动返回(swipe back) self.navigationController?.interactivePopGestureRecognizer!.delegate = self //新建一个滑动手势 let tap = UISwipeGestureRecognizer(target:self, action:nil) tap.delegate = self self.webView.addGestureRecognizer(tap) } //返回true表示所有相同类型的手势辨认都会得到处理 func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool { return true } //是否允许手势 func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool { if (gestureRecognizer == self.navigationController?.interactivePopGestureRecognizer) { //只有二级以及以下的页面允许手势返回 return self.navigationController!.viewControllers.count > 1 } return true } //返回按钮点击响应 @objc func backToPrevious(){ self.navigationController?.popViewController(animated: true) } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() } }源码下载:hangge_1092.zip
全部评论(4)
在rootViewcontroller下,使用侧滑返回手势,会卡住。。。
建议航哥参照http://www.nikest.com/web/jswd/2015/0325/158531.html写一个易懂的解决教程。。。
同时希望航哥能把文章分个类什么的,18页的文章,查找起来太困难了T_T
站长回复:文章代码已更新,加了个视图层级判断,现在在根视图侧滑返回不会卡住了。
非常感谢,正为这个问题苦恼呢
站长回复:不客气:)
感谢!!!
站长回复:不客气!欢迎常来看看。
真心赞航哥。关于这个问题,我在《Swift - 修改导航栏“返回”按钮文字,图标》给你留了言,一直关注,看到你说下周写一篇文章解决。今天早上刚试过,完美解决我的问题,谢谢航哥!
站长回复:不客气!很高兴能帮上忙。