iOS 11 - 使用大标题模式时的 UINavigationItem titleView

Posted

技术标签:

【中文标题】iOS 11 - 使用大标题模式时的 UINavigationItem titleView【英文标题】:iOS 11 - UINavigationItem titleView when using Large Titles mode 【发布时间】:2018-03-08 07:45:07 【问题描述】:

我试图了解这是错误还是预期行为。

iOS 10 及更早版本中,我们可以使用 navigationItem.titleView 设置自定义标题。 在 iOS 11 上,当设置我们的 navigationItem.largeTitleDisplayMode = .always 和设置 navigationItem.titleView = <Some cool UIButton> 时,它会显示 普通导航标题栏和大导航标题。

插图:

总结一下:

如何在大导航标题上使用自定义 titleView?

编辑:这是预期的结果:

【问题讨论】:

"我们如何在大导航标题上使用自定义 titleView?"你在做。这就是重点!以前,您不能同时拥有标题和标题视图。现在你可以。别担心,开心就好。 @matt 我明白了。但我正在寻找使用自定义视图更改大标题的选项。更新了预期结果 好吧,别再期待这个结果了!您误解了此功能。 【参考方案1】:

我找不到这方面的任何文档,所以我玩了一下。似乎在 ios 11 中,您将无法将该标题设置为按钮并在左侧大显示。

我不知道这是一个错误还是预期的结果,因为它似乎是一个新功能。最新的 (iOS 11) Human Interface Guidelines (HIG) 讨论了较大的标题标签是一种为用户提供清晰上下文的方式。 HIG 还讨论了按钮之间的空间。但是,没有讨论使用按钮作为标题。


为了重新创建,我设置了一个单一视图项目。我将视图控制器嵌入到导航控制器中。

ViewController.swiftviewDidLoad中,我添加了这段代码:

    let titleButton = UIButton(type: .roundedRect)
    titleButton.setTitle("Hello Button!", for: UIControlState.normal)

    let navController = parent as! UINavigationController

    navController.navigationBar.topItem!.title = "Hello???"
    navController.navigationBar.topItem!.titleView = titleButton
    navController.navigationBar.prefersLargeTitles = true

这最终看起来像你的例子。

如果我

.title设置为空字符串,或者注释掉行:导航栏被拉伸,并且没有标题文本显示(或在Interface Builder中设置的标题文本显示)

注释掉.prefersLargeTitles,或设置为false:导航栏为正常高度,按钮显示,但不显示标题文本。

注释掉titleView 行,并且:

.prefersLargeTitles 设置为truetitle 文本在左侧显示较大,并且导航栏的高度被拉伸。 将.prefersLargeTitles设置为falsetitle文本显示在顶部中心,导航栏为正常高度。

更新:链接到sample project on GitHub

【讨论】:

嗨 Leanne,很好的调查。所以据我了解,不可能实现可点击的大标题? :\ 就是这个样子。你可以试试reporting it as a bug to Apple 看看他们怎么说。随意链接到我的示例作为演示,或者如果您想添加更多自己的信息,请分叉它。【参考方案2】:

通过使用UINavigationBar 的子类并手动更改视图层次结构,我能够用自定义视图替换导航栏大标题:

@interface MYNavigationBar : UINavigationBar

@end
@implementation MYNavigationBar

// ...

- (void)layoutIfNeeded

    [self setupTitle];
    [super layoutIfNeeded];


- (void)setupTitle

    // UINavigationBar
    // -> ...
    // -> _UINavigationBarLargeTitleView
    //   -> UILabel << Big Title Label
    //   -> UIView
    //     -> UILabel << Big Title Label animating from back button during transitions

    for (UIView *view in self.subviews) 
        NSString *className = NSStringFromClass(view.classForCoder);
        if ([className containsString:@"LargeTitleView"]) 
            for (UIView *view2 in view.subviews) 
                if ([view2 isKindOfClass:[UILabel class]]) 
                    [self convertLabel:(UILabel *)view2];
                
                for (UIView *view3 in view2.subviews) 
                    if ([view3 isKindOfClass:[UILabel class]]) 
                        [self convertLabel:(UILabel *)view3];
                    
                
            
        
    


- (void)convertLabel:(UILabel*)label

    // I kept the original label in the hierarchy (with the background color as text color)
    // and added my custom view as a subview. 
    // This allow the transformations applied to the original label to be also applied to mine.

请注意,Apple 可能会因为这个技巧而拒绝您的应用。

【讨论】:

尽管它可能会导致拒绝,但这是一个很好的答案!无论如何,Apple 似乎不会这么快更改私有类名称,如果 UI 看起来不错,我敢打赌他们不会在意。干得好! 想知道您是否可以通过此更改将应用​​程序提交到应用商店,因为类名是私有的 我在审核过程中没有遇到任何问题,但我不能说 100% 安全

以上是关于iOS 11 - 使用大标题模式时的 UINavigationItem titleView的主要内容,如果未能解决你的问题,请参考以下文章

应用程序未运行时的iOS后台模式?

iOS11 上的Programmatic beginRefreshing() 有largeTitles 模式的问题

加入两个大表时的性能问题

UITabBarController中的UITableViewController = iOS 11上不需要的填充

控制器在 iOS 13 中呈现模式时的 UINavigationBar 高度

使用休眠时的 DAO 模式