mih*_*hai 75 xcode objective-c uinavigationcontroller uigesturerecognizer ios
我喜欢在UINavigationController中嵌入视图所继承的滑动包.不幸的是,我似乎找不到隐藏导航栏的方法,但仍然有触摸平移向后滑动手势.我可以编写自定义手势但我不喜欢和依赖UINavigationController后滑动手势.
如果我在故事板中取消选中它,则后滑动不起作用

或者如果我以编程方式隐藏它,相同的场景.
- (void)viewDidLoad
{
[super viewDidLoad];
[self.navigationController setNavigationBarHidden:YES animated:NO]; // and animated:YES
}
Run Code Online (Sandbox Code Playgroud)
有没有办法隐藏顶部导航栏仍然有滑动?
Hor*_*seT 92
正在工作的一个黑客是设置interactivePopGestureRecognizer的委托的UINavigationController,以nil这样的:
[self.navigationController.interactivePopGestureRecognizer setDelegate:nil];
Run Code Online (Sandbox Code Playgroud)
但在某些情况下,它可能会产生奇怪的效果.
Hun*_*onk 63
设置interactivePopGestureRecognizer.delegate = nil有意想不到的副作用.
设置navigationController?.navigationBar.hidden = true确实有效,但不允许隐藏导航栏中的更改.
最后,创建一个UIGestureRecognizerDelegate适用于导航控制器的模型对象通常是更好的做法.将其设置为UINavigationController堆栈中的控制器是导致EXC_BAD_ACCESS错误的原因.
首先,将此类添加到项目中:
class InteractivePopRecognizer: NSObject, UIGestureRecognizerDelegate {
var navigationController: UINavigationController
init(controller: UINavigationController) {
self.navigationController = controller
}
func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
return navigationController.viewControllers.count > 1
}
// This is necessary because without it, subviews of your top controller can
// cancel out your gesture recognizer on the edge.
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}
}
Run Code Online (Sandbox Code Playgroud)
然后,将导航控制器设置interactivePopGestureRecognizer.delegate为新InteractivePopRecognizer类的实例.
var popRecognizer: InteractivePopRecognizer?
override func viewDidLoad() {
super.viewDidLoad()
setInteractiveRecognizer()
}
private func setInteractiveRecognizer() {
guard let controller = navigationController else { return }
popRecognizer = InteractivePopRecognizer(controller: controller)
controller.interactivePopGestureRecognizer?.delegate = popRecognizer
}
Run Code Online (Sandbox Code Playgroud)
享受一个没有副作用的隐藏导航栏,即使您的顶级控制器具有表格,集合或滚动视图子视图也可以使用.
sar*_*pol 53
在我的情况下,以防止奇怪的效果
根视图控制器
override func viewDidLoad() {
super.viewDidLoad()
// Enable swipe back when no navigation bar
navigationController?.interactivePopGestureRecognizer?.delegate = self
}
func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
if(navigationController!.viewControllers.count > 1){
return true
}
return false
}
Run Code Online (Sandbox Code Playgroud)
http://www.gampood.com/pop-viewcontroller-with-out-navigation-bar/
Chr*_*lli 17
我发现其他已发布的解决方案覆盖了委托,或者将其设置为nil会导致一些意外行为.
在我的情况下,当我在导航堆栈的顶部并尝试使用手势再弹出一次时,它将失败(如预期的那样),但随后尝试推入堆栈将开始导致奇怪的图形故障导航栏.这是有道理的,因为委托被用来处理的不仅仅是在隐藏导航栏时是否阻止手势被识别,以及所有其他行为被抛出.
从我的测试中看来,这gestureRecognizer(_:, shouldReceiveTouch:)是原始委托实现的方法,用于阻止在隐藏导航栏时识别手势,而不是gestureRecognizerShouldBegin(_:).gestureRecognizerShouldBegin(_:)在其委托工作中实现的其他解决方案,因为缺少实现gestureRecognizer(_:, shouldReceiveTouch:)将导致接收所有触摸的默认行为.
@Nathan Perry的解决方案已经接近,但是如果没有实现respondsToSelector(_:),向代理发送消息的UIKit代码将相信没有任何其他委托方法的实现,并且forwardingTargetForSelector(_:)永远不会被调用.
因此,我们在我们想要修改行为的一个特定场景中控制`gestureRecognizer(_:,shouldReceiveTouch :),否则将其他所有内容转发给委托.
import Foundation
class AlwaysPoppableNavigationController: UINavigationController {
private let alwaysPoppableDelegate = AlwaysPoppableDelegate()
override func viewDidLoad() {
super.viewDidLoad()
alwaysPoppableDelegate.originalDelegate = interactivePopGestureRecognizer?.delegate
alwaysPoppableDelegate.navigationController = self
interactivePopGestureRecognizer?.delegate = alwaysPoppableDelegate
}
}
final class AlwaysPoppableDelegate: NSObject, UIGestureRecognizerDelegate {
weak var navigationController: UINavigationController?
weak var originalDelegate: UIGestureRecognizerDelegate?
override func responds(to aSelector: Selector!) -> Bool {
if aSelector == #selector(gestureRecognizer(_:shouldReceive:)) {
return true
} else if let responds = originalDelegate?.responds(to: aSelector) {
return responds
} else {
return false
}
}
override func forwardingTarget(for aSelector: Selector!) -> Any? {
return originalDelegate
}
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
if let nav = navigationController, nav.isNavigationBarHidden, nav.viewControllers.count > 1 {
return true
} else if let result = originalDelegate?.gestureRecognizer?(gestureRecognizer, shouldReceive: touch) {
return result
} else {
return false
}
}
}
Run Code Online (Sandbox Code Playgroud)
Yog*_*ari 16
您可以将UINavigationController子类化如下:
@interface CustomNavigationController : UINavigationController<UIGestureRecognizerDelegate>
@end
Run Code Online (Sandbox Code Playgroud)
执行:
@implementation CustomNavigationController
- (void)setNavigationBarHidden:(BOOL)hidden animated:(BOOL)animated {
[super setNavigationBarHidden:hidden animated:animated];
self.interactivePopGestureRecognizer.delegate = self;
}
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
if (self.viewControllers.count > 1) {
return YES;
}
return NO;
}
@end
Run Code Online (Sandbox Code Playgroud)
基于Hunter Maximillion Monk的答案,我为UINavigationController创建了一个子类,然后在我的故事板中为我的UINavigationController设置了自定义类.这两个类的最终代码如下所示:
InteractivePopRecognizer:
class InteractivePopRecognizer: NSObject {
// MARK: - Properties
fileprivate weak var navigationController: UINavigationController?
// MARK: - Init
init(controller: UINavigationController) {
self.navigationController = controller
super.init()
self.navigationController?.interactivePopGestureRecognizer?.delegate = self
}
}
extension InteractivePopRecognizer: UIGestureRecognizerDelegate {
func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
return (navigationController?.viewControllers.count ?? 0) > 1
}
// This is necessary because without it, subviews of your top controller can cancel out your gesture recognizer on the edge.
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}
}
Run Code Online (Sandbox Code Playgroud)
HiddenNavBarNavigationController:
class HiddenNavBarNavigationController: UINavigationController {
// MARK: - Properties
private var popRecognizer: InteractivePopRecognizer?
// MARK: - Lifecycle
override func viewDidLoad() {
super.viewDidLoad()
setupPopRecognizer()
}
// MARK: - Setup
private func setupPopRecognizer() {
popRecognizer = InteractivePopRecognizer(controller: self)
}
}
Run Code Online (Sandbox Code Playgroud)
故事板:

看起来@ChrisVasseli提供的解决方案是最好的.我想在Objective-C中提供相同的解决方案,因为问题是关于Objective-C(参见标签)
@interface InteractivePopGestureDelegate : NSObject <UIGestureRecognizerDelegate>
@property (nonatomic, weak) UINavigationController *navigationController;
@property (nonatomic, weak) id<UIGestureRecognizerDelegate> originalDelegate;
@end
@implementation InteractivePopGestureDelegate
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
if (self.navigationController.navigationBarHidden && self.navigationController.viewControllers.count > 1) {
return YES;
} else {
return [self.originalDelegate gestureRecognizer:gestureRecognizer shouldReceiveTouch:touch];
}
}
- (BOOL)respondsToSelector:(SEL)aSelector
{
if (aSelector == @selector(gestureRecognizer:shouldReceiveTouch:)) {
return YES;
} else {
return [self.originalDelegate respondsToSelector:aSelector];
}
}
- (id)forwardingTargetForSelector:(SEL)aSelector
{
return self.originalDelegate;
}
@end
@interface NavigationController ()
@property (nonatomic) InteractivePopGestureDelegate *interactivePopGestureDelegate;
@end
@implementation NavigationController
- (void)viewDidLoad
{
[super viewDidLoad];
self.interactivePopGestureDelegate = [InteractivePopGestureDelegate new];
self.interactivePopGestureDelegate.navigationController = self;
self.interactivePopGestureDelegate.originalDelegate = self.interactivePopGestureRecognizer.delegate;
self.interactivePopGestureRecognizer.delegate = self.interactivePopGestureDelegate;
}
@end
Run Code Online (Sandbox Code Playgroud)
我的解决方案是直接扩展UINavigationController类:
import UIKit
extension UINavigationController: UIGestureRecognizerDelegate {
override open func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
self.interactivePopGestureRecognizer?.delegate = self
}
public func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
return self.viewControllers.count > 1
}
}
Run Code Online (Sandbox Code Playgroud)
这样,所有导航控制器都可以通过滑动关闭。
小智 6
尽管此处的大多数答案都不错,但它们似乎具有意想不到的副作用(应用程序中断)或过于冗长。
我能想到的最简单但功能最全的解决方案是:
在要隐藏NavigationBar的ViewController中,
class MyNoNavBarViewController: UIViewController {
// needed for reference when leaving this view controller
var initialInteractivePopGestureRecognizerDelegate: UIGestureRecognizerDelegate?
override func viewDidLoad() {
super.viewDidLoad()
// we will need a reference to the initial delegate so that when we push or pop..
// ..this view controller we can appropriately assign back the original delegate
initialInteractivePopGestureRecognizerDelegate = self.navigationController?.interactivePopGestureRecognizer?.delegate
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(true)
// we must set the delegate to nil whether we are popping or pushing to..
// ..this view controller, thus we set it in viewWillAppear()
self.navigationController?.interactivePopGestureRecognizer?.delegate = nil
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(true)
// and every time we leave this view controller we must set the delegate back..
// ..to what it was originally
self.navigationController?.interactivePopGestureRecognizer?.delegate = initialInteractivePopGestureRecognizerDelegate
}
}
Run Code Online (Sandbox Code Playgroud)
其他答案建议仅将委托设置为nil。向后滑动到导航堆栈上的初始视图控制器会导致所有手势被禁用。可能是对UIKit / UIGesture开发人员的某种监督。
同样,我在此处执行的一些答案也导致了非标准的Apple导航行为(特别是允许在向上或向下滚动的同时还向后滑动)。这些答案似乎也有些冗长,在某些情况下还不完整。
小智 5
Hunter Monk 的回答真的很赞,可惜在iOS 13.3.1 中不行。
我将解释另一种隐藏UINavigationBar而不是丢失的方法swipe to back gesture。我已经在 iOS 13.3.1 和 12.4.3 上进行了测试,并且可以正常工作。
你需要创建一个自定义类UINavigationController,并设置类UINavigationController中Storyboard
不要隐藏NavigationBar在Storyboard
示例Storyboard:
最后,把这个:navigationBar.isHidden = true在viewDidLoad的CustomNavigationController类。
确保不要使用此方法setNavigationBarHidden(true, animated: true)隐藏NavigationBar.
import UIKit
class CustomNavigationController: UINavigationController {
override func viewDidLoad() {
super.viewDidLoad()
navigationBar.isHidden = true
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
36710 次 |
| 最近记录: |