在iOS 7中更改后退按钮将禁用滑动以向后导航
我有一个iOS 7应用程序,其中我设置了一个自定义后退按钮,如下所示:在iOS 7中更改后退按钮将禁用滑动以向后导航,ios,uinavigationcontroller,ios7,uibarbuttonitem,uiviewanimation,Ios,Uinavigationcontroller,Ios7,Uibarbuttonitem,Uiviewanimation,我有一个iOS 7应用程序,其中我设置了一个自定义后退按钮,如下所示: UIImage *backButtonImage = [UIImage imageNamed:@"back-button"]; UIButton *backButton = [UIButton buttonWithType:UIButtonTypeCustom]; [backButton setImage:backButtonImage forState:UIControlStateNormal];
UIImage *backButtonImage = [UIImage imageNamed:@"back-button"];
UIButton *backButton = [UIButton buttonWithType:UIButtonTypeCustom];
[backButton setImage:backButtonImage forState:UIControlStateNormal];
backButton.frame = CGRectMake(0, 0, 20, 20);
[backButton addTarget:self
action:@selector(popViewController)
forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *backBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:backButton];
viewController.navigationItem.leftBarButtonItem = backBarButtonItem;
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
if (gestureRecognizer == navigationController.interactivePopGestureRecognizer) {
return !navigationController.<#TODO: isPushAnimating#> && [navigationController.viewControllers count] > 1;
}
return YES;
}
但这将禁用iOS 7“从左向右滑动”手势以导航到上一个控制器。有人知道我如何设置自定义按钮并保持此手势处于启用状态吗
编辑:
我尝试改为设置viewController.navigationItem.backBarButtonItem,但这似乎没有显示我的自定义图像。尝试
self.navigationController。
.enabled=YES代码>重要提示:
这是一个黑客。我建议你看看这个
分配leftBarButtonItem
后调用以下行对我有效:
self.navigationController.interactivePopGestureRecognizer.delegate = self;
[self.navigationController pushViewController:vcToPush animated:YES];
// Enabling iOS 7 screen-edge-pan-gesture for pop action
if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)]) {
self.navigationController.interactivePopGestureRecognizer.delegate = nil;
}
编辑:
如果在init
方法中调用,则此操作不起作用。应该在viewDidLoad
或类似方法中调用它。我还隐藏了“后退”按钮,将其替换为自定义的leftBarItem
在推送操作对我起作用后删除interactivePopGestureRecognizer委托:
self.navigationController.interactivePopGestureRecognizer.delegate = self;
[self.navigationController pushViewController:vcToPush animated:YES];
// Enabling iOS 7 screen-edge-pan-gesture for pop action
if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)]) {
self.navigationController.interactivePopGestureRecognizer.delegate = nil;
}
我用
我看到了这个子类UINavigationController的解决方案。这是一个更好的解决方案,因为它可以处理在控制器就位之前刷卡的情况,这会导致崩溃
除此之外,我还注意到,如果您在根视图控制器上进行滑动(在按下一个控制器后,然后再返回),UI将变得无响应(与上面的回答相同)
因此,子类UINavigationController中的代码应该如下所示:
@implementation NavigationController
- (void)viewDidLoad {
[super viewDidLoad];
__weak NavigationController *weakSelf = self;
if ([self respondsToSelector:@selector(interactivePopGestureRecognizer)]) {
self.interactivePopGestureRecognizer.delegate = weakSelf;
self.delegate = weakSelf;
}
}
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated {
// Hijack the push method to disable the gesture
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 {
// Enable the gesture again once the new controller is shown
self.interactivePopGestureRecognizer.enabled = ([self respondsToSelector:@selector(interactivePopGestureRecognizer)] && [self.viewControllers count] > 1);
}
@end
尽可能使用UINavigationBar的Backindicator图像和Backindicator TransitionMaskimage属性。在UIAppearanceProxy上设置这些选项可以轻松修改整个应用程序的行为。问题是,你只能在ios 7上设置这些,但这是可行的,因为你无论如何只能在ios 7上使用弹出手势。您正常的ios 6样式可以保持不变
UINavigationBar* appearanceNavigationBar = [UINavigationBar appearance];
//the appearanceProxy returns NO, so ask the class directly
if ([[UINavigationBar class] instancesRespondToSelector:@selector(setBackIndicatorImage:)])
{
appearanceNavigationBar.backIndicatorImage = [UIImage imageNamed:@"back"];
appearanceNavigationBar.backIndicatorTransitionMaskImage = [UIImage imageNamed:@"back"];
//sets back button color
appearanceNavigationBar.tintColor = [UIColor whiteColor];
}else{
//do ios 6 customization
}
试图操纵InteractivePopGetureRecognizer的代理将导致许多问题。我遇到了一个类似的问题,我将当前视图控制器指定为交互式pop手势的代理,但会在推送的任何视图或导航堆栈中视图下方的视图上打断手势。我解决这个问题的方法是在-viewDidAppear
中设置委托,然后在-viewwilldiscover
中将其设置为nil。这使我的其他视图能够正常工作。想象一下,我们正在使用苹果默认的主/细节项目模板,其中主是一个表视图控制器,点击它将显示细节视图控制器
navigationController.interactivePopGestureRecognizer.delegate = (id<UIGestureRecognizerDelegate>)self;
我们希望自定义显示在“详细视图”控制器中的“后退”按钮。这是如何自定义“后退”按钮的、、文本颜色和
要全局更改图像、图像颜色、文本颜色或字体,请在创建任何视图控制器之前,将以下内容放置在名为的位置(例如应用程序:didFinishLaunchingWithOptions:
是一个好位置)
注意,您可以使用appearancewhen contained in:
来更好地控制哪些视图控制器受到这些更改的影响,但请记住,您不能传递[DetailViewController类]
,因为它包含在UINavigationController中,而不是您的DetailViewController中。这意味着,如果希望对受影响的内容进行更多控制,则需要将UINavigationController子类化
若要自定义特定后退按钮项的文本或字体/颜色,必须在MasterViewController(而不是DetailViewController!)中进行自定义。这似乎不直观,因为按钮出现在DetailViewController上。但是,一旦您了解到定制它的方法是在navigationItem上设置属性,它就开始变得更有意义
- (void)viewDidLoad { // MASTER view controller
[super viewDidLoad];
UIBarButtonItem *buttonItem = [[UIBarButtonItem alloc] initWithTitle:@"Testing"
style:UIBarButtonItemStylePlain
target:nil
action:nil];
NSDictionary *barButtonTitleTextAttributes =
@{
NSFontAttributeName: [UIFont fontWithName:@"HelveticaNeue-Light" size:12.0],
NSForegroundColorAttributeName: [UIColor purpleColor]
};
[buttonItem setTitleTextAttributes:barButtonTitleTextAttributes forState:UIControlStateNormal];
self.navigationItem.backBarButtonItem = buttonItem;
}
注意:在设置self.navigationItem.backBarButtonItem后尝试设置TitleExtAttributes似乎不起作用,因此必须在将值分配给此属性之前设置它们。我没有写这篇文章,但以下博客帮了大忙,并解决了自定义导航按钮的问题:
总之,他实现了一个自定义UINavigationController,该控制器使用pop手势委托。非常干净,便于携带
代码:
创建一个类“TTNavigationViewController”,该类是“UINavigationController”的子类,并将该类的现有导航控制器设置为故事板/类,类中的示例代码-
class TTNavigationViewController: UINavigationController, UIGestureRecognizerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
self.setNavigationBarHidden(true, animated: false)
// enable slide-back
if self.responds(to: #selector(getter: UINavigationController.interactivePopGestureRecognizer)) {
self.interactivePopGestureRecognizer?.isEnabled = true
self.interactivePopGestureRecognizer?.delegate = self
}
}
func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}}
这里是swift3版本的
根视图
override func viewDidAppear(_ animated: Bool) {
self.navigationController?.interactivePopGestureRecognizer?.isEnabled = false
}
儿童视图
override func viewDidLoad() {
self.navigationController?.interactivePopGestureRecognizer?.isEnabled = true
self.navigationController?.interactivePopGestureRecognizer?.delegate = self
}
extension ChildViewController: UIGestureRecognizerDelegate {}
使用此逻辑保持启用或禁用滑动手势
- (void)navigationController:(UINavigationController *)navigationController
didShowViewController:(UIViewController *)viewController
animated:(BOOL)animate
{
if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)])
{
if (self.navigationController.viewControllers.count > 1)
{
self.navigationController.interactivePopGestureRecognizer.enabled = YES;
}
else
{
self.navigationController.interactivePopGestureRecognizer.enabled = NO;
}
}
}
是否在视图控制器上设置此选项?还是导航控制器?我也有同样的问题,但这似乎不起作用?@mixedCase下载您的示例项目后,我现在了解您的问题。只要集合视图的内容不超过视图控制器的水平宽度,代码就可以工作。但是,一旦集合视图成为水平滚动视图,它就会覆盖InteractiveEPGEstureRecognitor。我会看看我是否能找到一个解决办法。我对这个代码有问题。它的工作时间不长,5-10回刷后VC冻结。有什么解决方案吗?Timur Bernikowich我也有同样的经历。您找到原因了吗?将委托设置为self
会将其从类\u UINavigationInteractiveTransition
的对象中取消设置。该对象有责任确保导航控制器在已处于转换状态时不会弹出。仍在调查在自定义“后退”按钮时是否可以启用此手势。不,它已启用。。问题似乎是它的代理不允许启动手势识别器,我在这里添加了我的解决方案作为另一个答案。中航工业能否请您解释一下为什么设置代理会起作用?我遇到了同样的问题。这种方法的一个问题是如果您在根上执行边缘平移
override func viewDidAppear(_ animated: Bool) {
self.navigationController?.interactivePopGestureRecognizer?.isEnabled = false
}
override func viewDidLoad() {
self.navigationController?.interactivePopGestureRecognizer?.isEnabled = true
self.navigationController?.interactivePopGestureRecognizer?.delegate = self
}
extension ChildViewController: UIGestureRecognizerDelegate {}
- (void)navigationController:(UINavigationController *)navigationController
didShowViewController:(UIViewController *)viewController
animated:(BOOL)animate
{
if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)])
{
if (self.navigationController.viewControllers.count > 1)
{
self.navigationController.interactivePopGestureRecognizer.enabled = YES;
}
else
{
self.navigationController.interactivePopGestureRecognizer.enabled = NO;
}
}
}