【问题标题】:iOS 11 navigation bar height customizingiOS 11 导航栏高度自定义
【发布时间】:2017-11-07 07:26:01
【问题描述】:

现在在 iOS 11 中,sizeThatFits 方法不会从 UINavigationBar 子类调用。更改 UINavigationBar 的框架会导致故障和错误的插图。 那么,现在有什么想法可以自定义导航栏的高度吗?

【问题讨论】:

  • 这仍然是 Beta 2 的一个问题,即使 Beta 1 中报告的问题据说已经修复:UINavigationBar 子类没有调用 sizeThatFits。
  • 在 Beta 3 中,调用了 sizeThatFits,但似乎对自定义高度没有任何作用。发行说明中是否确实提到了这个问题?
  • 对我来说 UINavigationBar 得到了调整大小,只有视图仍然认为它是默认的 44 像素高度。所以我的视图在自定义导航栏下方绘制。 p.s.扩展的边缘位于none
  • 是的,自定义高度导航栏在 beta 4 中仍然非常有问题,尽管发行说明指出:“导航栏现在应该看起来正确。(32076094)”。我建议提交一份重复的错误报告。
  • UINavigationBar 有意不再使用 sizeThatFits 来确定其大小,因为 iOS 11 中带有大标题的导航栏高度会动态变化。所以,我不知道除了构建自己的导航栏而不是UINavigationBar 之外,可以做些什么来获得 iOS 11 中的固定高度。我鼓励您提交增强请求,请求 API 影响 iOS 11+ 的导航栏高度。

标签: ios uinavigationbar ios11


【解决方案1】:

根据 Apple 开发人员(查看 hereherehere)的说法,iOS 11 不支持更改导航栏高度。 Here 他们建议做一些变通方法,比如在导航栏下(但在导航栏之外)有一个视图,然后删除导航栏边框。结果,您将在情节提要中看到以下内容:

在设备上看起来像这样:

现在您可以执行其他答案中建议的解决方法:创建UINavigationBar 的自定义子类,将您的自定义大子视图添加到其中,覆盖sizeThatFitslayoutSubviews,然后将additionalSafeAreaInsets.top 设置为导航的顶部控制器与customHeight - 44px 不同,但条形视图仍将是默认的 44px,即使在视觉上一切看起来都很完美。我没有尝试覆盖setFrame,也许它可以工作,但是,正如Apple开发人员在上面的链接之一中所写的那样:“......而且[支持]也没有改变拥有的导航栏的框架通过 UINavigationController (导航控制器会在它认为合适的时候很高兴地踩在你的框架更改上)。”

在我的情况下,上述解决方法使视图看起来像这样(调试视图以显示边框):

如您所见,视觉效果相当不错,additionalSafeAreaInsets 正确地将内容向下推,大导航栏可见,但是我在此栏中有一个自定义按钮,并且只有低于标准的区域44 像素导航栏是可点击的(图像中的绿色区域)。低于标准导航栏高度的触摸不会到达我的自定义子视图,因此我需要调整导航栏本身的大小,Apple 开发人员表示不支持。

【讨论】:

  • 要解决可点击区域的问题,请尝试添加到您的自定义 UINavigationBar 下一个覆盖方法code override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { return subviews.reduce(super.hitTest(point, with: event)) { (result, subview) in return result ?? subview.hitTest(convert(point, to: subview), with: event) } } 抱歉格式化
  • 苹果提供的最新项目不包括扩展导航栏。
  • @Weizhi 你可以从github下载旧版本:github.com/robovm/apple-ios-samples/tree/master/…
  • @Weizhi - 他们仍然包含代码,但故事板场景已被删除..
  • 由于 Apple 现在剩余的示例不完整,您能否 @frangulan 提供一些代码来说明您是如何实际实现的?
【解决方案2】:

2018 年 1 月 7 日更新

此代码支持 XCode 9.2、iOS 11.2

我遇到了同样的问题。下面是我的解决方案。我假设高度大小是 66。

如果对你有帮助,请选择我的答案。

创建 CINavgationBar.swift

   import UIKit

@IBDesignable
class CINavigationBar: UINavigationBar {

    //set NavigationBar's height
    @IBInspectable var customHeight : CGFloat = 66

    override func sizeThatFits(_ size: CGSize) -> CGSize {

        return CGSize(width: UIScreen.main.bounds.width, height: customHeight)

    }

    override func layoutSubviews() {
        super.layoutSubviews()

        print("It called")

        self.tintColor = .black
        self.backgroundColor = .red



        for subview in self.subviews {
            var stringFromClass = NSStringFromClass(subview.classForCoder)
            if stringFromClass.contains("UIBarBackground") {

                subview.frame = CGRect(x: 0, y: 0, width: self.frame.width, height: customHeight)

                subview.backgroundColor = .green
                subview.sizeToFit()
            }

            stringFromClass = NSStringFromClass(subview.classForCoder)

            //Can't set height of the UINavigationBarContentView
            if stringFromClass.contains("UINavigationBarContentView") {

                //Set Center Y
                let centerY = (customHeight - subview.frame.height) / 2.0
                subview.frame = CGRect(x: 0, y: centerY, width: self.frame.width, height: subview.frame.height)
                subview.backgroundColor = .yellow
                subview.sizeToFit()

            }
        }


    }


}

设置故事板

设置自定义 NavigationBar 类

添加 TestView + 设置 SafeArea

ViewController.swift

import UIKit

class ViewController: UIViewController {

    var navbar : UINavigationBar!

    @IBOutlet weak var testView: UIView!

    override func viewDidLoad() {
        super.viewDidLoad()

        //update NavigationBar's frame
        self.navigationController?.navigationBar.sizeToFit()
        print("NavigationBar Frame : \(String(describing: self.navigationController!.navigationBar.frame))")

    }

    //Hide Statusbar
    override var prefersStatusBarHidden: Bool {

        return true
    }

    override func viewDidAppear(_ animated: Bool) {

        super.viewDidAppear(false)

        //Important!
        if #available(iOS 11.0, *) {

            //Default NavigationBar Height is 44. Custom NavigationBar Height is 66. So We should set additionalSafeAreaInsets to 66-44 = 22
            self.additionalSafeAreaInsets.top = 22

        }

    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


}

SecondViewController.swift

import UIKit

class SecondViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.


        // Create BackButton
        var backButton: UIBarButtonItem!
        let backImage = imageFromText("Back", font: UIFont.systemFont(ofSize: 16), maxWidth: 1000, color:UIColor.white)
        backButton = UIBarButtonItem(image: backImage, style: UIBarButtonItemStyle.plain, target: self, action: #selector(SecondViewController.back(_:)))

        self.navigationItem.leftBarButtonItem = backButton
        self.navigationItem.leftBarButtonItem?.setBackgroundVerticalPositionAdjustment(-10, for: UIBarMetrics.default)


    }
    override var prefersStatusBarHidden: Bool {

        return true
    }
    @objc func back(_ sender: UITabBarItem){

        self.navigationController?.popViewController(animated: true)

    }


    //Helper Function : Get String CGSize
    func sizeOfAttributeString(_ str: NSAttributedString, maxWidth: CGFloat) -> CGSize {
        let size = str.boundingRect(with: CGSize(width: maxWidth, height: 1000), options:(NSStringDrawingOptions.usesLineFragmentOrigin), context:nil).size
        return size
    }


    //Helper Function : Convert String to UIImage
    func imageFromText(_ text:NSString, font:UIFont, maxWidth:CGFloat, color:UIColor) -> UIImage
    {
        let paragraph = NSMutableParagraphStyle()
        paragraph.lineBreakMode = NSLineBreakMode.byWordWrapping
        paragraph.alignment = .center // potentially this can be an input param too, but i guess in most use cases we want center align

        let attributedString = NSAttributedString(string: text as String, attributes: [NSAttributedStringKey.font: font, NSAttributedStringKey.foregroundColor: color, NSAttributedStringKey.paragraphStyle:paragraph])

        let size = sizeOfAttributeString(attributedString, maxWidth: maxWidth)
        UIGraphicsBeginImageContextWithOptions(size, false , 0.0)
        attributedString.draw(in: CGRect(x: 0, y: 0, width: size.width, height: size.height))
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return image!
    }




    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }



}

黄色是barbackgroundView。黑色不透明度是 BarContentView。

并且我删除了 BarContentView 的 backgroundColor。

就是这样。

【讨论】:

  • 这个解决方案在iOS 11.2似乎无效,因为导航栏多次调用layoutSubviews(),导致应用死机。
  • 我也面临同样的问题@Michael
  • 这种变通方法完全是骇人听闻的,而且保证在不久的将来会崩溃!
  • 在 iPhone X 上,导航栏高度发生变化,但不再向上延伸到状态栏区域下方。有什么更新可以让它在 iPhone X 上运行吗?
  • 通过类名搜索子视图非常脆弱。任何寻求稳健解决方案的人都应该避免这种情况。
【解决方案3】:

这对我有用:

- (CGSize)sizeThatFits:(CGSize)size {
    CGSize sizeThatFit = [super sizeThatFits:size];
    if ([UIApplication sharedApplication].isStatusBarHidden) {
        if (sizeThatFit.height < 64.f) {
            sizeThatFit.height = 64.f;
        }
    }
    return sizeThatFit;
}

- (void)setFrame:(CGRect)frame {
    if ([UIApplication sharedApplication].isStatusBarHidden) {
        frame.size.height = 64;
    }
    [super setFrame:frame];
}

- (void)layoutSubviews
{
    [super layoutSubviews];

    for (UIView *subview in self.subviews) {
        if ([NSStringFromClass([subview class]) containsString:@"BarBackground"]) {
            CGRect subViewFrame = subview.frame;
            subViewFrame.origin.y = 0;
            subViewFrame.size.height = 64;
            [subview setFrame: subViewFrame];
        }
        if ([NSStringFromClass([subview class]) containsString:@"BarContentView"]) {
            CGRect subViewFrame = subview.frame;
            subViewFrame.origin.y = 20;
            subViewFrame.size.height = 44;
            [subview setFrame: subViewFrame];
        }
    }
}

【讨论】:

    【解决方案4】:

    添加: iOS 11 beta 6 解决了这个问题,所以下面的代码没有用^_^


    原答案:

    用下面的代码解决了:

    (我一直想要navigationBar.height + statusBar.height == 64 statusBar的隐藏是否为真)

     @implementation P1AlwaysBigNavigationBar
    
    - (CGSize)sizeThatFits:(CGSize)size {
        CGSize sizeThatFit = [super sizeThatFits:size];
        if ([UIApplication sharedApplication].isStatusBarHidden) {
            if (sizeThatFit.height < 64.f) {
                sizeThatFit.height = 64.f;
            }
        }
        return sizeThatFit;
    }
    
    - (void)setFrame:(CGRect)frame {
        if ([UIApplication sharedApplication].isStatusBarHidden) {
            frame.size.height = 64;
        }
        [super setFrame:frame];
    }
    
    - (void)layoutSubviews
    {
        [super layoutSubviews];
    
        if (![UIApplication sharedApplication].isStatusBarHidden) {
            return;
        }
    
        for (UIView *subview in self.subviews) {
            NSString* subViewClassName = NSStringFromClass([subview class]);
            if ([subViewClassName containsString:@"UIBarBackground"]) {
                subview.frame = self.bounds;
            }else if ([subViewClassName containsString:@"UINavigationBarContentView"]) {
                if (subview.height < 64) {
                    subview.y = 64 - subview.height;
                }else {
                    subview.y = 0;
                }
            }
        }
    }
    @end
    

    【讨论】:

    • 在 for 中,您的 subview 是一个 UIView。 subview.height 稍后你好吗??
    • 我为 UIView 写了一个帮助类。
    • iOS 11 beta 9 仍然存在此问题。使用此解决方法可以解决问题。但希望他们能解决它。谢谢@CharlieSu
    • 如何将此类设置为我的 uinavigationcontroller 的导航栏?
    • 有这方面的快速例子吗?我认为我使用子类 UINavigationBar?
    【解决方案5】:

    使用 Swift 4 进行简化。

    class CustomNavigationBar : UINavigationBar {
    
        private let hiddenStatusBar: Bool
    
        // MARK: Init
        init(hiddenStatusBar: Bool = false) {
            self.hiddenStatusBar = hiddenStatusBar
            super.init(frame: .zero)
        }
    
        required init?(coder aDecoder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }
    
        // MARK: Overrides
        override func layoutSubviews() {
            super.layoutSubviews()
    
            if #available(iOS 11.0, *) {
                for subview in self.subviews {
                    let stringFromClass = NSStringFromClass(subview.classForCoder)
                    if stringFromClass.contains("BarBackground") {
                        subview.frame = self.bounds
                    } else if stringFromClass.contains("BarContentView") {
                        let statusBarHeight = self.hiddenStatusBar ? 0 : UIApplication.shared.statusBarFrame.height
                        subview.frame.origin.y = statusBarHeight
                        subview.frame.size.height = self.bounds.height - statusBarHeight
                    }
                }
            }
        }
    }
    

    【讨论】:

    • 这段代码给了我一个致命错误 fatalError("init(coder:) has not been implemented")
    【解决方案6】:

    除了覆盖-layoutSubviews-setFrame:,如果您不希望调整大小的导航栏隐藏您的内容,您应该查看新添加的 UIViewController 的additionalSafereaInsets 属性 (Apple Documentation)。

    【讨论】:

    • 这很重要,只需更新导航栏背景高度就会使其与视图控制器中的内容重叠。我无法解决的是如何正确使用addionalSafeAreaInsets,尤其是如何允许不支持此属性的 iOS 10 及以下版本
    • 这很重要,只需更新导航栏背景高度就会使其与视图控制器中的内容重叠。我无法解决的是如何正确使用addionalSafeAreaInsets,尤其是如何允许不支持此属性的 iOS 10 及以下版本
    【解决方案7】:

    虽然它已在 beta 4 中得到修复,但导航栏的背景图像似乎并未随实际视图缩放(您可以通过在视图层次结构查看器中查看来验证这一点)。目前的解决方法是在您的自定义 UINavigationBar 中覆盖 layoutSubviews,然后使用以下代码:

    - (void)layoutSubviews
    {
      [super layoutSubviews];
    
      for (UIView *subview in self.subviews) {
        if ([NSStringFromClass([subview class]) containsString:@"BarBackground"]) {
            CGRect subViewFrame = subview.frame;
            subViewFrame.origin.y = -20;
            subViewFrame.size.height = CUSTOM_FIXED_HEIGHT+20;
            [subview setFrame: subViewFrame];
        }
      }
    }
    

    如果你注意到,栏背景实际上有一个-20 的偏移量,使它出现在状态栏的后面,所以上面的计算把它加进去了。

    【讨论】:

    • 您需要声明/实例化子视图框架吗?还是直接编辑子视图的框架?
    • @MarcoPappalardo 修正错字,需要是局部变量
    【解决方案8】:

    在 Xcode 9 Beta 6 上我仍然有这个问题。 Bar 总是看起来 44 像素高,并被推到状态栏下方。

    为了解决这个问题,我用@strangetimes 代码(在 Swift 中)创建了一个子类

    class NavigationBar: UINavigationBar {
    
      override func layoutSubviews() {
        super.layoutSubviews()
    
        for subview in self.subviews {
          var stringFromClass = NSStringFromClass(subview.classForCoder)
          print("--------- \(stringFromClass)")
          if stringFromClass.contains("BarBackground") {
            subview.frame.origin.y = -20
            subview.frame.size.height = 64
          }
        }
      }
    }
    

    我把状态栏放在低于状态栏的位置

    let newNavigationBar = NavigationBar(frame: CGRect(origin: CGPoint(x: 0,
                                                                           y: 20),
                                                             size: CGSize(width: view.frame.width,
                                                                          height: 64)
          )
        ) 
    

    【讨论】:

      【解决方案9】:

      这适用于常规导航栏。如果您使用 LargeTitle,这将无法正常工作,因为 titleView 大小不会是 44 磅的固定高度。但是对于常规视图,这应该就足够了。

      就像@frangulyan apple 建议在导航栏下方添加一个视图并隐藏细线(阴影图像)。这就是我在下面提出的。我在navigationItem 的titleView 中添加了一个uiview,然后在该uiview 中添加了一个imageView。我删除了细线(阴影图像)。我添加的uiview是same exact color as the navBar。我在该视图中添加了一个 uiLabel ,就是这样。

      这是 3D 图像。扩展视图位于导航栏下方的 usernameLabel 后面。它是灰色的,下面有一条细线。只需将您的 collectionView 或细分隔线下方的任何内容锚定即可。

      上面每一行代码都解释了9个步骤:

      class ExtendedNavController: UIViewController {
      
          fileprivate let extendedView: UIView = {
              let view = UIView()
              view.translatesAutoresizingMaskIntoConstraints = false
              view.backgroundColor = .white
              return view
          }()
      
          fileprivate let separatorLine: UIView = {
              let view = UIView()
              view.translatesAutoresizingMaskIntoConstraints = false
              view.backgroundColor = .gray
              return view
          }()
      
          fileprivate let usernameLabel: UILabel = {
              let label = UILabel()
              label.translatesAutoresizingMaskIntoConstraints = false
              label.font = UIFont.systemFont(ofSize: 14)
              label.text = "username goes here"
              label.textAlignment = .center
              label.lineBreakMode = .byTruncatingTail
              label.numberOfLines = 1
              return label
          }()
      
          fileprivate let myTitleView: UIView = {
              let view = UIView()
              view.backgroundColor = .white
              return view
          }()
      
          fileprivate let profileImageView: UIImageView = {
              let imageView = UIImageView()
              imageView.translatesAutoresizingMaskIntoConstraints = false
              imageView.clipsToBounds = true
              imageView.backgroundColor = .darkGray
              return imageView
          }()
      
          override func viewDidLoad() {
              super.viewDidLoad()
              view.backgroundColor = .white
      
              // 1. the navBar's titleView has a height of 44, set myTitleView height and width both to 44
              myTitleView.frame = CGRect(x: 0, y: 0, width: 44, height: 44)
      
              // 2. set myTitleView to the nav bar's titleView
              navigationItem.titleView = myTitleView
      
              // 3. get rid of the thin line (shadow Image) underneath the navigationBar
              navigationController?.navigationBar.setValue(true, forKey: "hidesShadow")
              navigationController?.navigationBar.layoutIfNeeded()
      
              // 4. set the navigationBar's tint color to the color you want
              navigationController?.navigationBar.barTintColor = UIColor(red: 249.0/255.0, green: 249.0/255.0, blue: 249.0/255.0, alpha: 1.0)
      
              // 5. set extendedView's background color to the same exact color as the navBar's background color
              extendedView.backgroundColor = UIColor(red: 249.0/255.0, green: 249.0/255.0, blue: 249.0/255.0, alpha: 1.0)
      
              // 6. set your imageView to get pinned inside the titleView
              setProfileImageViewAnchorsInsideMyTitleView()
      
              // 7. set the extendedView's anchors directly underneath the navigation bar
              setExtendedViewAndSeparatorLineAnchors()
      
              // 8. set the usernameLabel's anchors inside the extendedView
              setNameLabelAnchorsInsideTheExtendedView()
          }
      
          override func viewWillDisappear(_ animated: Bool) {
              super.viewWillDisappear(true)
      
              // 9. **Optional** If you want the shadow image to show on other view controllers when popping or pushing
              navigationController?.navigationBar.setBackgroundImage(nil, for: .default)
              navigationController?.navigationBar.setValue(false, forKey: "hidesShadow")
              navigationController?.navigationBar.layoutIfNeeded()
          }
      
          func setExtendedViewAndSeparatorLineAnchors() {
      
              view.addSubview(extendedView)
              view.addSubview(separatorLine)
      
              extendedView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true
              extendedView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
              extendedView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
              extendedView.heightAnchor.constraint(equalToConstant: 29.5).isActive = true
      
              separatorLine.topAnchor.constraint(equalTo:  extendedView.bottomAnchor).isActive = true
              separatorLine.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
              separatorLine.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
              separatorLine.heightAnchor.constraint(equalToConstant: 0.5).isActive = true
          }
      
          func setProfileImageViewAnchorsInsideMyTitleView() {
      
              myTitleView.addSubview(profileImageView)
      
              profileImageView.topAnchor.constraint(equalTo: myTitleView.topAnchor).isActive = true
              profileImageView.centerXAnchor.constraint(equalTo: myTitleView.centerXAnchor).isActive = true
              profileImageView.widthAnchor.constraint(equalToConstant: 44).isActive = true
              profileImageView.heightAnchor.constraint(equalToConstant: 44).isActive = true
      
              // round the profileImageView
              profileImageView.layoutIfNeeded()
              profileImageView.layer.cornerRadius = profileImageView.frame.width / 2
          }
      
          func setNameLabelAnchorsInsideTheExtendedView() {
      
              extendedView.addSubview(usernameLabel)
      
              usernameLabel.topAnchor.constraint(equalTo: extendedView.topAnchor).isActive = true
              usernameLabel.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
              usernameLabel.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
          }
      }
      

      【讨论】:

      • navigationController?.navigationBar.setValue(true, forKey: "hidesShadow") 被认为是私有的,被苹果的审查拒绝了?
      • 我在我的一个实时应用中使用它,我从来没有遇到任何问题
      • @ItaiSpector 你不用担心
      【解决方案10】:

      这是我使用的。如果您使用UISearchBar 作为标题或修改栏内容大小的其他视图,它适用于常规内容(44.0 像素),您必须相应地更新值。使用它需要您自担风险,因为它可能会在某个时候刹车。

      这是 90.0px 高度硬编码的导航栏,适用于 iOS 11 和更早版本。您可能需要在 UIBarButtonItem 中添加一些插图,以便 iOS 11 之前的版本看起来相同。

      class NavBar: UINavigationBar {
      
          override init(frame: CGRect) {
              super.init(frame: frame)
      
              if #available(iOS 11, *) {
                  translatesAutoresizingMaskIntoConstraints = false
              }
          }
      
          required init?(coder aDecoder: NSCoder) {
              fatalError("init(coder:) has not been implemented")
          }
      
          override func sizeThatFits(_ size: CGSize) -> CGSize {
              return CGSize(width: UIScreen.main.bounds.width, height: 70.0)
          }
      
          override func layoutSubviews() {
              super.layoutSubviews()
      
              guard #available(iOS 11, *) else {
                  return
              }
      
              frame = CGRect(x: frame.origin.x, y:  0, width: frame.size.width, height: 90)
      
              if let parent = superview {
                  parent.layoutIfNeeded()
      
                  for view in parent.subviews {
                      let stringFromClass = NSStringFromClass(view.classForCoder)
                      if stringFromClass.contains("NavigationTransition") {
                          view.frame = CGRect(x: view.frame.origin.x, y: frame.size.height - 64, width: view.frame.size.width, height: parent.bounds.size.height - frame.size.height + 4)
                      }
                  }
              }
      
              for subview in self.subviews {
                  var stringFromClass = NSStringFromClass(subview.classForCoder)
                  if stringFromClass.contains("BarBackground") {
                      subview.frame = CGRect(x: 0, y: 0, width: self.frame.width, height: 90)
                      subview.backgroundColor = .yellow
                  }
      
                  stringFromClass = NSStringFromClass(subview.classForCoder)
                  if stringFromClass.contains("BarContent") {
                      subview.frame = CGRect(x: subview.frame.origin.x, y: 40, width: subview.frame.width, height: subview.frame.height)
      
                  }
              }
          }
      }
      

      然后将它添加到 UINavigationController 子类中,如下所示:

      class CustomBarNavigationViewController: UINavigationController {
      
          init() {
              super.init(navigationBarClass: NavBar.self, toolbarClass: nil)
          }
      
          override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
              super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
          }
      
          override init(rootViewController: UIViewController) {
              super.init(navigationBarClass: NavBar.self, toolbarClass: nil)
      
              self.viewControllers = [rootViewController]
          }
      
          required public init?(coder aDecoder: NSCoder) {
              fatalError("init(coder:) has not been implemented")
          }
      
      }
      

      【讨论】:

      • 我遇到错误 -> 致命错误:init(coder:) 尚未实现:
      • 如果你正在使用它,只需使用编码器实现 init
      • 感谢您的回复。但是安全区的顶部没有更新。安全区域的顶部仍然是 44px。设置导航栏高度后如何更新安全区域的顶部。
      • 您可以尝试在 UIView 上使用safeAreaInsets 属性来更新您的安全区域。
      【解决方案11】:

      我将导航栏的高度加倍,因此我可以在默认导航控件上方添加一行状态图标,方法是继承 UINavigationBar 并使用 sizeThatFits 覆盖高度。幸运的是,这具有相同的效果,并且更简单,副作用更少。我在 iOS 8 到 11 上对其进行了测试。把它放在你的视图控制器中:

      - (void)viewDidLoad {
          [super viewDidLoad];
          if (self.navigationController) {
              self.navigationItem.prompt = @" "; // this adds empty space on top
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-12-10
        • 2023-04-07
        • 2013-11-19
        • 2018-02-02
        • 1970-01-01
        • 2022-07-18
        • 1970-01-01
        相关资源
        最近更新 更多