带有 UINavigationController 的独立 UINavigationBar 中的后退按钮

Posted

技术标签:

【中文标题】带有 UINavigationController 的独立 UINavigationBar 中的后退按钮【英文标题】:Back button in standalone UINavigationBar with UINavigationController 【发布时间】:2013-10-10 09:09:46 【问题描述】:

我正在尝试实现一个上推式 UINavigationBar,其中导航栏的位置附加到 UIScrollView 的 contentOffset(类似于 safari 在 ios7 中的工作方式)。

为了使动态运动正常工作,我使用了一个以编程方式创建的 UINavigationBar,并将其添加为 UIViewController 的view 的子视图(它可以作为self.navbar 访问)。

UIViewController 在 UINavigationController 层次结构中,所以我将内置的self.navigationController.navigationBar 隐藏在-viewWillAppear: 的顶部。

我要解决的问题是向这个新的独立导航栏添加一个后退按钮。我宁愿简单地从 navigationController 及其隐藏的内置导航栏中复制按钮甚至是 navigationItems,但这似乎不起作用

将我的独立导航栏上的 leftBarButtonItem 设置为假后退按钮的唯一解决方案是(当 navController 的导航栏中有 backItem 时)?这似乎有点 hacky,我宁愿使用内置的 backButton 功能。

【问题讨论】:

【参考方案1】:

另一种方法是,一旦您设置了自己的UINavigationBar,在您的导航栏上两个UINavigationItems,导致后退按钮出现。然后,您可以自定义按下后退按钮时发生的情况。

我是这样做的

1 - 一些UINavigationItem 子类,用于定义额外行为/自定义参数

@interface MyNavigationItem : UINavigationItem

//example : some custom back action when 'back' is pressed
@property (nonatomic, copy) void (^onBackClickedAction)(void);

@end

2 - 然后将其连接到您的 UINavigationBarDelegate

- (BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPopItem:(UINavigationItem *)item

    if ([item isKindOfClass:[MyNavigationItem class]]) 
        MyNavigationItem *navItem = (MyNavigationItem *)item;


        //custom action
        if (navItem.backAction) 
            navItem.backAction();
        
        return YES;// return NO if you don't want your bar to animate to previous item
     else 
        return YES;
    

您可以调整该方案,在返回操作时调用您的 UINavigationController pop 方法。 这仍然是hacky

【讨论】:

好主意,我会试试的。你在哪里推 UINavigationItems - 在 vi​​ewWillAppear: 中?我确定是否应该有后退按钮的方法是 self.navigationController.viewControllers.count > 1(并从 count-1 ViewController 获取标题)......你在做类似的事情吗? 不,我的 UINavigationBar 不在我的内容 UIViewController 中,而是在它的容器父级中。在您的情况下,您可以将 UINavigationBar 移动到 UINavigationController 子类中 我没有 UINavigationController 子类。上推式导航栏仅用于特定类的 UIViewController(列表)。事实上,我正在导航到一个视图控制器,该控制器可以返回使用标准导航栏(静态内容)。而且我需要能够在 list->list 或 list->static->list 之间导航。所以对我来说,列表 ViewController 拥有和管理导航栏是有意义的。 到目前为止它大部分都在工作,但我无法让后退按钮成为可点击并触发 popItem 事件(奇怪的是它确实触发了向右滑动的弹出)。有什么想法吗? 请注意,缺乏可点击性是我实现导航栏的一个问题(我添加了一个彩色子视图以增强颜色,但启用了 userInteraction :P)【参考方案2】:

Vinzzz 的回答是一个很好的解决方案。这是我的实现,因为上下文略有不同。

在 UIViewController 的 viewDidLoad 方法中,我将导航栏的导航项设置如下:

NSMutableArray* navItems = [@[] mutableCopy];
if (self.navigationController.viewControllers.count > 1)

    NSInteger penultimateIndex = (NSInteger)self.navigationController.viewControllers.count - 2;
    UIViewController* prevVC =  (penultimateIndex >= 0) ? self.navigationController.viewControllers[penultimateIndex] : nil;

    UINavigationItem* prevNavItem = [[UINavigationItem alloc] init];
    prevNavItem.title = prevVC.title;

    [navItems addObject:prevNavItem];


UINavigationItem* currNavItem = [[UINavigationItem alloc] init];

... <Add any other left/right buttons to the currNavItem> ...

[navItems addObject:currNavItem];
[self.navbar setItems:navItems];

...self.navbar 是我的浮动独立 UINavigationBar。

我还将当前视图控制器分配为self.navbar的委托,然后监听按下返回按钮时触发的-navigationBar:shouldPopItem:事件:

- (BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPopItem:(UINavigationItem *)item

    if (navigationBar == self.navbar)
    
        [self.navigationController popViewControllerAnimated:YES];
        return NO;
    
    return YES;

(如果返回YES,在ios7中使用滑动手势会崩溃)。

【讨论】:

以上是关于带有 UINavigationController 的独立 UINavigationBar 中的后退按钮的主要内容,如果未能解决你的问题,请参考以下文章

在 UINavigationController 中添加带有标题的图像

带有自定义 NavigationBar 的 UINavigationController

带有 uinavigationcontroller 和 uitabbarcontroller 的 iphone 应用程序

UINavigationController 推送带有隐藏导航栏的视图控制器

带有自定义垂直按钮栏的 UINavigationController

带有 UINavigationController 作为选项卡的 UITabViewController