带有自定义后退按钮的滑动手势冻结根视图控制器
Posted
技术标签:
【中文标题】带有自定义后退按钮的滑动手势冻结根视图控制器【英文标题】:Slide gesture with custom back button freezes the root view controller 【发布时间】:2014-02-26 19:30:38 【问题描述】:我的应用程序中都有自定义后退按钮,看起来导航控制器不喜欢它。
所以,我希望 ios7 滑动返回手势与我的自定义返回按钮一起使用。搜索并尝试了不同的方法,但似乎都没有希望。我能得到的最接近的是http://keighl.com/post/ios7-interactive-pop-gesture-custom-back-button/。 但是,现在当我继续推送和弹出导航堆栈时,堆栈中的 rootViewController 会停止响应任何触摸。
有什么建议吗?
【问题讨论】:
那个链接失效了? 【参考方案1】:继承 UINavigationController,就像 keighl 建议的那样,是 imo 的正确方法。但是他错过了对根视图控制器的检查,以避免在根视图上执行手势时冻结。 这是带有附加检查的修改版本:
CBNavigationController.h:
#import <UIKit/UIKit.h>
@interface CBNavigationController : UINavigationController <UIGestureRecognizerDelegate, UINavigationControllerDelegate>
@end
CBNavigationController.m:
#import "CBNavigationController.h"
@interface CBNavigationController ()
@end
@implementation CBNavigationController
- (void)viewDidLoad
NSLog(@"%s",__FUNCTION__);
__weak CBNavigationController *weakSelf = self;
if ([self respondsToSelector:@selector(interactivePopGestureRecognizer)])
self.interactivePopGestureRecognizer.delegate = weakSelf;
self.delegate = weakSelf;
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated
NSLog(@"%s",__FUNCTION__);
if ([self respondsToSelector:@selector(interactivePopGestureRecognizer)])
self.interactivePopGestureRecognizer.enabled = NO;
[super pushViewController:viewController animated:animated];
#pragma mark UINavigationControllerDelegate
- (void)navigationController:(UINavigationController *)navigationController
didShowViewController:(UIViewController *)viewController
animated:(BOOL)animate
NSLog(@"%s",__FUNCTION__);
// Enable the gesture again once the new controller is shown AND is not the root view controller
if (viewController == self.viewControllers.firstObject)
if ([self respondsToSelector:@selector(interactivePopGestureRecognizer)])
self.interactivePopGestureRecognizer.enabled = NO;
else
if ([self respondsToSelector:@selector(interactivePopGestureRecognizer)])
self.interactivePopGestureRecognizer.enabled = YES;
@end
objective-c
【讨论】:
这应该被标记为正确答案 - 只有一个适用于所有情况。【参考方案2】:我遇到了同样的问题,这是我的解决方案:
在您的自定义 NavigationController 中,例如 MYNavigationController
,因为您将手势委托设置为 navigationController,您可以在其中添加委托方法:
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
if (self.viewControllers.count>1)
return YES;
return NO;
然后它将在根视图控制器中停止弹出动作并避免冻结行为。
【讨论】:
那行不通——当你在动画发生时继续滑动仍然会导致卡顿【参考方案3】:即使我遇到了同样的问题,我也已通过修改您所指链接中提供的代码来解决它。现在我的屏幕很少冻结,但仍然无法找到永久修复。
@implementation PPNavigationController
-(void)viewDidLoad
//[super viewDidLoad];
// Do any additional setup after loading the view.
__weak PPNavigationController *weakSelf = self;
if ([self respondsToSelector:@selector(interactivePopGestureRecognizer)])
self.interactivePopGestureRecognizer.delegate = weakSelf;
self.delegate = weakSelf;
-(void)navigationController:(UINavigationController *)navigationController
didShowViewController:(UIViewController *)viewController
animated:(BOOL)animate
// Enable the gesture again once the new controller is shown
if ([self respondsToSelector:@selector(interactivePopGestureRecognizer)])
self.interactivePopGestureRecognizer.delegate = viewController;
Don't use this method
//-(void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated
//
【讨论】:
嘿阿南德,我之前已经尝试过上面的代码,它确实使情况好一些。但是当你从导航堆栈中推送和弹出很多时,屏幕仍然会冻结。【参考方案4】:这是我对here提出的类似问题的回答
您可以使用一些小技巧来让本机手势正常工作。
创建UINavigationItem
的子类,然后重写leftBarButtonItems
方法:
- (NSArray*)leftBarButtonItems
return nil;
现在将此类用于具有自定义左侧UIBarButtonItem
的项目。手势有效!这是因为UINavigationController
认为没有剩余项目并启用手势。您仍然可以通过 leftBarButtonItem
属性访问您的自定义项。
【讨论】:
【参考方案5】:这是UINavigationController
的一个简单的Swift 子类,您可以使用我改编自@weak 的答案。不需要实现 UIGestureRecognizerDelegate
,因为导航代理的 navigationController(_:didShow:animated:)
处理启用和禁用弹出手势的工作。
在故事板或代码中使用此子类比在嵌入在导航控制器中的其他控制器中一次性禁用更容易。
import UIKit
@objc class LWNavigationController : UINavigationController,
UINavigationControllerDelegate
override func viewDidLoad()
self.delegate = self
override func pushViewController(_ viewController: UIViewController,
animated: Bool)
// Disable this gesture while animating a push.
self.interactivePopGestureRecognizer?.isEnabled = false
super.pushViewController(viewController, animated: animated)
debugPrint("------\(#function) \(viewController)------")
// MARK: - UINavigationControllerDelegate
func navigationController(_ navigationController: UINavigationController,
didShow viewController: UIViewController,
animated: Bool)
if (viewController == self.viewControllers.first)
// Keep the gesture disabled if we're at the root to avoid back swipes
// from corrupting the navigation stack.
self.interactivePopGestureRecognizer?.isEnabled = false
else
self.interactivePopGestureRecognizer?.isEnabled = true
debugPrint("------\(#function) \(viewController) " +
"enabled: \(self.interactivePopGestureRecognizer?.isEnabled)" +
"------")
【讨论】:
以上是关于带有自定义后退按钮的滑动手势冻结根视图控制器的主要内容,如果未能解决你的问题,请参考以下文章
SwiftUI - navigationBarBackButtonHidden - 向后滑动手势?