iOS 11 navigation bar height customizing

后端 未结 11 890
无人共我
无人共我 2020-11-28 01:27

Now in iOS 11, the sizeThatFits method is not called from UINavigationBar subclasses. Changing the frame of UINavigationBar causes gli

11条回答
  •  伪装坚强ぢ
    2020-11-28 01:43

    Updated 07 Jan 2018

    This code is support XCode 9.2, iOS 11.2

    I had the same problem. Below is my solution. I assume that height size is 66.

    Please choose my answer if it helps you.

    Create 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()
    
                }
            }
    
    
        }
    
    
    }
    

    Set Storyboard

    Set Custom NavigationBar class

    Add TestView + Set 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.
        }
    
    
    
    }
    

    Yellow is barbackgroundView. Black opacity is BarContentView.

    And I removed BarContentView's backgroundColor.

    That's It.

提交回复
热议问题