【问题标题】:iOS 11 prefersLargeTitles not updating until scrolliOS 11 prefersLargeTitles 直到滚动才更新
【发布时间】:2017-11-10 21:39:07
【问题描述】:

我用封装在 UINavigationController 中的 UITableView 实现了一个基本的 UIViewController。我将prefersLargeTitles 设置为true:

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.

    navigationController?.navigationBar.prefersLargeTitles = true
    navigationItem.title = "Coffees"
}

但是,在我滚动视图之前,标题一直很小,此时它会放大。我尝试将该调用移至创建 UINavigationController 的位置,但没有任何效果。当我设置prefersLargeTitles 时,我确定navigationController 不为零。

我应该在其他地方更新该属性吗?还是我应该提交雷达?

更新:

这似乎只有在我的视图包含 UITableView 或本身是 UITableViewController 时才会发生

【问题讨论】:

  • navigationBar 混在一起通常应该在viewWillAppear(_:) 中完成,而不是viewDidLoad()
  • 同样的问题
  • 我尝试将其移至viewWillAppear。同样的问题。
  • @JohnBreen 我有同样的问题。你找到解决办法了吗?
  • 也有同样的问题,似乎是iOS错误,我还没有找到解决办法

标签: ios swift cocoa-touch uinavigationcontroller uikit


【解决方案1】:

我最近遇到了同样的问题,但没有任何建议对我有用。相反,我需要做的就是调用sizeToFit()。示例代码:

private func configureNavigator() {
    guard let navigationController = navigationController else { return }
    navigationController.navigationBar.prefersLargeTitles = true
    navigationItem.largeTitleDisplayMode = .automatic
    navigationController.navigationBar.sizeToFit()
}

我希望这会有所帮助!

【讨论】:

  • 当 ViewController 在 UITabBarController 中时,这对我也有用。
  • 这是完美的navigationController?.navigationBar.sizeToFit()
  • 完美。我花了很多时间试图解决这个问题,这很奏效。谢谢
  • 完美运行。非常简单的 UITableViewController。只有当我有一个 tableFooterView 时,大标题才起作用。谢谢
  • 使用带有大标题的搜索控制器也为我工作。我不得不从 viewWillAppear 调用并设置 navigationItem.hidesSearchBarWhenScrolling = false,然后在 viewDidAppear 中调用 navigationItem.hidesSearchBarWhenScrolling = true。
【解决方案2】:

对我来说,唯一可行的解​​决方案是:

DispatchQueue.main.async { [weak self] in
    self?.navigationController?.navigationBar.sizeToFit()
}

viewWillAppear()

【讨论】:

  • 我讨厌这解决了我的问题。 +1
  • 也解决了我的问题。
  • 也解决了我的问题
  • 为我工作,XCode 12 和 iOS 14。虽然 viewWillAppear() 已经从主队列中调用了,但不需要将其发送到主队列
  • 是的,只要在 viewWillAppear() 而不是 viewDidLoad() 中,可以确认在没有 DispatchQueue 的情况下调用 sizeToFit() 可以正常工作
【解决方案3】:

我只在一个 tableview 上遇到了同样的问题...

我必须设置:

self.tableView.contentInsetAdjustmentBehavior = .never

这样我的 tableview 在加载 uiviewcontroller 时停止滚动。

是tableview自动滚动导致大标题被隐藏

希望对你有帮助

【讨论】:

  • 这覆盖了带有大标题的导航栏后面的第一行?
  • edgesForExtendedLayout = []
  • 兄弟,您的解决方案帮助了我。谢谢!
  • 这对我不起作用,实际上导致我的内容在导航栏下移动(它是一个半透明的导航栏)
【解决方案4】:

我遇到了同样的问题。虽然您没有使用故事板,但我希望这可以帮助某人。我检查了导航控制器(而不是视图控制器)的“首选大标题”,我将 TableViewController 嵌入其中。导航控制器转动后的所有视图控制器都有大标题,它应该可以工作。

【讨论】:

  • 完美!谢谢!
  • 我的问题是不同的 - 在第一个 VC 中隐藏大标题并在 secondVC 中显示大标题,在第二个 VC 中第一次截断大标题,通过禁用它来为我工作的情节提要
  • 我已经一年多没有编写 iOS 代码了,但我大部分时间都放弃了编程视图,尽管我很沮丧,但我还是回到了故事板。
  • 上帝保佑你!
【解决方案5】:

top:1修改tableView的contentInset会强制NavigationBar展开并显示大标题。

Obj-C

-(void) viewWillAppear:(BOOL)animated {
    if (@available(iOS 11.0, *)) {
        tableView.contentInset = UIEdgeInsetsMake(1, 0, 0, 0);
    }
}

斯威夫特

override func viewWillAppear(_ animated: Bool) {
    if #available(iOS 11.0, *) {
        tableView.contentInset = UIEdgeInsetsMake(1, 0, 0, 0)
    }
}

注意:如果您的viewWillAppear 中有tableView.reloadData(),请确保在编辑contentInset 后调用它

【讨论】:

  • 这个它自己做任何事情,我认为你应该添加你在tableView和导航栏中设置的配置
【解决方案6】:

在我的情况下,解决方案是将 tableView 的顶部对齐设置为安全区域而不是 Superview

【讨论】:

  • 这是正确的 - 但它破坏了 11 之前的 iOS 版本的表格视图
  • 阿诺,很好的答案。以及 Stackoverflow 上的最佳个人资料图片。
【解决方案7】:

与 Swift 5.2 相同的问题

我的视图包含 tableView 并且 prefersLargeTitles 在滚动之前不会更新,我通过设置修复它

self.tableView.contentInsetAdjustmentBehavior = .never

【讨论】:

    【解决方案8】:

    我遇到了同样的问题,发现通常最好从设置它的视图控制器或对象中设置 prefersLargeTitles 属性,并在呈现之前这样做。

    例如,如果有问题的视图控制器在应用启动时显示:

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    
        let window = UIWindow(frame: UIScreen.main.bounds)
    
        let someViewController: UIViewController = CustomViewController()
    
        let theNavController = UINavigationController(rootViewController: someViewController)
        theNavController.navigationBar.prefersLargeTitles = true
    
        window.rootViewController = theNavController
        window.makeKeyAndVisible()
    
        return true
    }
    

    或者如果呈现一个特定的视图控制器:

    let someViewController: UIViewController = CustomViewController()
    
    let theNavController = UINavigationController(rootViewController: someViewController)
    theNavController.navigationBar.prefersLargeTitles = true
    
    present(theNavController, animated: true, completion: nil)
    

    我发现这种方法是一种更可靠的方法,可以确保相应地显示导航标题。希望这可以帮助! :)

    【讨论】:

    • 添加到您的第二个示例:我发现如果您创建另一个视图控制器并立即将其推送到导航控制器上,如果您通过点击后退按钮返回到第一个视图控制器,则会出现导致标题文本消失的故障。您必须在第一个 ViewController 上调用 layoutIfNeeded() 才能修复此问题。
    【解决方案9】:

    我在这方面浪费了相当多的时间,因为prefersLargeTitle saga 按预期在某些视图控制器上工作,并且在某些情况下会产生与上述相同的问题。

    对我来说,解决方案是取消选中 IB 中顶部栏下的扩展边缘 - 对于那些在加载表格视图的内容之前暂时显示大标题的视图控制器,然后导航栏跳回常规大小。它只在向下滚动表格视图时显示大标题。

    这向后兼容 iOS 10,并且不会在表格视图的第一行上方留下任何空白。

    我只在 IB 中检查了导航控制器属性检查器上的 prefersLargeTitle - 代码中没有任何内容。 largeTitleDisplayMode = .always也一样

    至于为什么某些视图控制器会发生这种情况,而其他视图控制器不会,我完全不知道!

    【讨论】:

      【解决方案10】:

      在故事板中,我将导航项的 Large Title 设置为 Never

      在我的 ViewController 的 viewDidLoad 方法中,我设置了以下内容:

      navigationController?.navigationBar.prefersLargeTitles = true
      navigationItem.largeTitleDisplayMode = .always
      

      【讨论】:

      • 我没有使用故事板
      • 即使在 Xcode 9 GM 中也需要解决此问题。似乎导航栏的大标题字体也被忽略了。
      【解决方案11】:

      我尝试了所有其他答案,但对我有用的是在viewDidLoad 中将我的UITableView 的内容偏移设置为CGPoint(x: 0, y: -1)

      tableView.setContentOffset(CGPoint(x: 0, y: -1), animated: false)
      

      【讨论】:

        【解决方案12】:

        我刚刚遇到了同样的问题,就我而言,事实证明,在 iOS 10 和 Swift 3 中运行的 Storyboard 结构(以及在 iOS 11 和 Swift 3 中运行)导致了 iOS 11 上的问题斯威夫特 4.

        详细说明:

        我的故事板中有一个常规的 UIViewController,我已将其设置为 UINavigationController 子类(我的层次结构与您的相似,具有 UITabBarController 子类 → UINavigationController 子类 → UITableViewController 子类)。

        在 iOS 10 中,这很好用。

        在 iOS 11 中,当您运行现有的 Swift 3 应用程序时,这也可以正常工作。

        但是,在 iOS 11 上运行的 Swift 4 应用程序中,我看到了与您描述的相同的症状(大标题仅在您向下拉/滚动视图时出现)。

        为了解决这个问题,我将 Storyboard 中基于 UIViewController 的元素替换为实际的 UINavigationController 实例(在 Storyboard 中明确包含一个 UINavigationBar - 我有一种预感,这就是问题的症结所在,因为 UIViewController 实例没有'没有在情节提要中明确声明该元素)。

        无论如何,这为我解决了问题。

        我将归档雷达,因为这看起来像是基于 Swift 4 的回归,因为对我来说,它既适用于带有 Swift 3 的 iOS 10,也适用于带有 Swift 3 的 iOS 11。

        【讨论】:

        • 我没有使用故事板,所以我不认为这是我的应用程序发生的事情
        【解决方案13】:

        一般更改navigationBar 的行为应在viewWillAppear(_:) 中完成

        override func viewWillAppear(_ animated: Bool) {
            super.viewWillAppear(animated)
            self.navigationController?.navigationBar.prefersLargeTitles = true
        }
        

        这样做后它对我来说很好。

        【讨论】:

          【解决方案14】:

          另一种可能的解决方案是在您的 refreshHandler() 中结束刷新。像这样-

          @objc func refreshPage() {
              self.refreshControl?.endRefreshing() //End here
              self.loadTableData() //Get fresh data and reload table
          }
          

          【讨论】:

            【解决方案15】:

            我通过故事板解决了这个问题

            1. 导航控制器 -> 导航栏 -> 属性检查器 -> 首选大标题(已选中)
            2. 视图控制器 -> 导航项 -> 属性检查器 -> 大标题(自动或始终选中)

            【讨论】:

              【解决方案16】:

              我觉得它看起来确实有点假,但我有效地解决了这个问题:

              self.navigationItem.prompt = ""
              
              self.navigationItem.prompt = nil
              

              这就像 navigationBar 需要在它的一个元素中进行某种更新来更新布局。

              有时要更新导航栏中的某些内容,我需要隐藏和取消隐藏它。这就是为什么我认为有最好的方法来做到这一点。目前这是我的解决方法。

              【讨论】:

                【解决方案17】:

                以编程方式:

                1. 在 AppDelegate.swift 中:
                        window = UIWindow(frame: UIScreen.main.bounds)
                        window?.makeKeyAndVisible()
                
                        let navigationController = UINavigationController.init(rootViewController: ViewController())
                        window?.rootViewController = navigationController
                
                1. 在 ViewController 中:
                    override func viewWillAppear(_ animated: Bool) {
                        super.viewWillAppear(animated)
                
                        navigationController?.navigationBar.prefersLargeTitles = true
                        navigationItem.largeTitleDisplayMode = .automatic
                    }
                
                   override func loadView() {
                        super.loadView()
                
                        view.addSubview(tableView)
                        view.addSubview(loadingView)
                
                        NSLayoutConstraint.activate([
                            tableView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor),
                            tableView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
                            tableView.widthAnchor.constraint(equalTo: view.safeAreaLayoutGuide.widthAnchor),
                            tableView.heightAnchor.constraint(equalTo: view.safeAreaLayoutGuide.heightAnchor)
                            ])
                    }
                

                确保您的 tableView 之前已添加到您的视图中。

                【讨论】:

                • 这个,这解决了我两个月的问题。谢谢!
                【解决方案18】:

                导航栏有类似的问题,但在我的情况下,它有一个自定义标题视图,并且导航栏保持为空,直到向下滚动表格视图,这触发 UILayoutContainerView 布局其子视图,其中一个是导航控制器的视图和导航栏。我假设它的根源与大标题导航栏问题相同。

                tableView 锚定到safeAreaLayoutGuide 对我来说不起作用,largeTitleDisplayMode 只能是.never

                所以我设法通过在顶部呈现的控制器的viewDidAppear(animated:) 函数中调用self.navigationController?.view.setNeedsUpdateConstraints 来修复它,或者将此调用安排在viewWillAppear(animated:) 中的下一个运行循环中,例如:

                DispatchQueue.main.async {
                    self.navigationController?.view.setNeedsUpdateConstraints()
                }
                

                在这种情况下,导航栏显示正确的内容和大小以及呈现过渡,而不是在过渡完成后弹出

                【讨论】:

                  【解决方案19】:

                  如果父视图在导航之前未滚动,则上述表格视图的答案也适用于集合视图:

                  self.collectionView.contentInsetAdjustmentBehavior = .never
                  

                  如果父视图在导航之前滚动,则上述解决方案在我的情况下不起作用。我不得不将上面的答案添加为:

                  override func viewWillAppear(_ animated: Bool) {
                      super.viewWillAppear(animated)
                      self.navigationController?.navigationBar.sizeToFit()
                  }
                  

                  【讨论】:

                    【解决方案20】:

                    一开始这似乎是一种奇怪的行为,但请尝试将navigationItem.largeTitleDisplayMode 设置为always。默认值为automatic - 在docs 中没有定义它是如何工作的。

                    还写了/将更新关于大标题的答案here

                    【讨论】:

                    • 我也试过了。它对我也不起作用:(
                    【解决方案21】:

                    我有类似的问题。该视图是一个表格视图。 prefersLargeTitles 的属性在viewDidLoad 事件中设置。然后我在viewWillAppear 事件中设置视图的标题。

                    override open func viewDidLoad() {
                       if #available(iOS 11.0, *) {
                            self.navigationController?.navigationBar.prefersLargeTitles = true
                        } else {
                            // Fallback on earlier versions
                        }
                        ...
                    }
                    
                    override open func viewWillAppear(_ animated: Bool) {
                        self.navigationItem.title = "something"
                        ...
                    }
                    

                    在我的准备 segue 事件中,我将导航项的磁贴设置为 nil,以便下一个视图左侧导航 var 项自动显示“返回”。

                    override func prepare(for segue: UIStoryboardSegue,
                                          sender: Any?) {
                        self.navigationItem.title = nil
                        ...
                    }
                    

                    表格视图第一次正确显示大标题。但是,如果我选择一行到下一个视图并返回到表格视图,导航项的标题将变为空。

                    经过几个小时的挣扎,我终于发现视图的标题应该设置在viewDidAppear事件中!似乎在Will 事件中设置为视图标题的任何内容都将由 UIKit 在内部重置为零。所以它必须在不同的事件中设置。

                    override func viewDidAppear(_ animated: Bool) {
                       self.navigationItem.title = "something"
                       ...
                    }
                    
                    override open func viewWillAppear(_ animated: Bool) {
                        // self.navigationItem.title = "something" // Remove it and set title in Did event!
                        ...
                    }
                    

                    在我介绍这个 iOS 11 新功能之前,我的应用运行良好。新功能似乎在 UIKit 中发生了一些变化,因此之前版本的应用程序可能需要一些更新/更改才能使其工作。

                    【讨论】:

                      【解决方案22】:

                      我遇到了同样的问题,并通过在 InterfaceBuilder 中更改 ViewController 中的视图顺序来解决它。

                      似乎如果 Hierarchy 中的第一个视图不是 ScrollView,那么 NavigationBar 会以 LargeTitle 模式出现,并且不会与滚动视图一起动画。如果您需要导航栏标题来反映您的滚动,那么您需要将滚动视图作为视图层次结构中的第一个。

                      另外,我对此并不完全确定,但看起来标准或大标题模式下的导航栏外观取决于先前控制器的视图层次结构。

                      【讨论】:

                        【解决方案23】:

                        UITableViewController 添加到 UIViewController 对我来说是类似的问题。在我的例子中,这些视图控制器本身嵌入在UITabBarController 中,只有正确显示的第一个选项卡使用了大标题。其他选项卡需要手动滚动才能显示大标题。

                        我唯一能开始工作的就是根据@pau-senabre 的回答调整contentInset,但top 插入对我没有帮助。相反,我设置了left inset,然后在下一个运行循环中将其重置。

                        private var isFirstAppearance = true
                        
                        override func viewWillAppear(_ animated: Bool) {
                            super.viewWillAppear(animated)
                        
                            if isFirstAppearance {
                                applyLargeTitlesFix()
                            }
                        }
                        
                        private func applyLargeTitlesFix() {
                            let originalInset = tableViewController.tableView.contentInset
                            tableViewController.tableView.contentInset = UIEdgeInsets(top: 0, left: 1, bottom: 0, right: 0)
                            DispatchQueue.main.async { [weak self] in
                                self?.tableViewController.tableView.contentInset = originalInset
                            }
                            isFirstAppearance = false
                        }
                        

                        【讨论】:

                          【解决方案24】:

                          Swift 4.2、iOS 12 和重构的 Storyboard 也存在同样的问题。

                          尝试将prefersLargeTitles = true 添加到viewWillAppearviewDidLoad,但都没有解决我的问题。

                          相反,我将重构的故事板复制回 main.storyboard,并找到了在 IB 中启用大标题的选项。设置该选项,然后重构故事板,现在一切正常。出于某种原因,最初的重构去掉了该选项,我无法以编程方式启用它。

                          【讨论】:

                            【解决方案25】:

                            对我有用的是在调用 tableviews reload 方法之前设置self.navigationController?.navigationBar.prefersLargeTitles = true

                            【讨论】:

                              【解决方案26】:

                              我遇到了同样的问题(iOS 14、Xcode 12.2)。

                              它只影响显示表格视图的导航控制器。

                              我最初设置tableView.tableFooterView = UIView() 是为了去掉最后一个单元格之后的额外分隔符。 将页脚视图设置为nil 修复了向上滚动的导航标题。

                              【讨论】:

                                【解决方案27】:

                                我有同样的问题。

                                我在 viewdidload 方法中设置了以下代码。它得到了修复。

                                self.navigationController?.navigationBar.prefersLargeTitles = true

                                self.navigationItem.largeTitleDisplayMode = .never

                                【讨论】:

                                  猜你喜欢
                                  • 2018-06-24
                                  • 1970-01-01
                                  • 1970-01-01
                                  • 1970-01-01
                                  • 1970-01-01
                                  • 1970-01-01
                                  • 1970-01-01
                                  • 1970-01-01
                                  • 1970-01-01
                                  相关资源
                                  最近更新 更多