iOS 11 — невозможно изменить высоту панели навигации

Я работаю над приложением, и я только что обновился до Xcode 9/Swift 4, а также обновил свой iPhone до iOS 11. Приложение было установлено, когда я установил iOS 11, и все выглядело нормально, пока я не запустил его из Xcode. Теперь я застрял с высотой NavBar по умолчанию.

Код, который я использовал для изменения высоты, больше не работает:

class CustomNavControllerVC: UINavigationController
{
    let navBarHeight : CGFloat = 64.0
    let navbarBackButtonColor = UIColor(red: 247/255, green: 179/255, blue: 20/255, alpha: 1)

    override func viewDidLoad()
    {
        super.viewDidLoad()

        print("CustomNavControllerVC > viewDidLoad")
    }

    override func viewDidLayoutSubviews()
    {
        print("CustomNavControllerVC > viewDidLayoutSubviews")

        super.viewDidLayoutSubviews()

        navigationBar.frame.size.height = navBarHeight
        navigationBar.tintColor = navbarBackButtonColor
    }

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


// In my VCs

override func viewDidLoad()
{
    customizeNavBar()
}


func customizeNavBar()
{
    let navbarBackItem = UIBarButtonItem()
    navbarBackItem.title = "Înapoi"
    navigationItem.backBarButtonItem = navbarBackItem

    let navbarImageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 55, height: 20))
    navbarImageView.contentMode = .scaleToFill

    let navbarLogo = UIImage(named: "NavBarLogo.png")
    navbarImageView.image = navbarLogo

    navigationItem.titleView = navbarImageView
}

Пока единственное, что я смог найти по этому вопросу, это:

Настройка высоты панели навигации iOS 11

iOS11 настроить высоту панели навигации

Как правильно установить высоту UINavigationBar в iOS 11

Но предоставленная информация не помогает, к сожалению.

Есть идеи/предложения?


person daydr3am3r    schedule 20.09.2017    source источник
comment
Почему нельзя использовать Custom View вместо UINavigationBar ?   -  person Mukesh    schedule 20.09.2017
comment
openradar.appspot.com/32912789 Похоже, что команда UIKit никогда не планировала, чтобы UINavigationBar поддерживали нестандартную высоту. Если вы хотите увеличить размер панели навигации, я бы использовал методы, которые Apple продвигает здесь: developer.apple.com/library/content/samplecode/NavBar/   -  person beyowulf    schedule 20.09.2017
comment
@mukesh_lokare - Изначально предполагалось, что NavBar будет иметь стандартную высоту с изображением логотипа посередине, поэтому я решил использовать стандартный NavBarController. Спустя 30 экранов и множество занятий кто-то решил, что у него должна быть нестандартная высота, поэтому я решил использовать этот метод.   -  person daydr3am3r    schedule 25.09.2017
comment
@beyowulf - я видел это, но надеялся на решение. Я буду использовать предоставленные методы, посмотрим, что произойдет.   -  person daydr3am3r    schedule 25.09.2017
comment
Так грустно, что нам мешают неумелые разработчики Apple. Похоже, единственное, что нужно сделать, это забыть о NavController и снова заниматься своими руками.   -  person amergin    schedule 10.11.2017


Ответы (1)


Обновлено 2017.10.6

У меня такая же проблема. Ниже мое решение. Я предполагаю, что размер роста 66.

Мое решение отлично работает на iOS 10, 11.

Пожалуйста, выберите мой ответ, если он вам поможет.

Создать NavgationBar.swift

import UIKit

class NavigationBar: UINavigationBar {

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

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

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

    }

    override func layoutSubviews() {
        super.layoutSubviews()

        frame = CGRect(x: frame.origin.x, y:  0, width: frame.size.width, height: customHeight)

        // title position (statusbar height / 2)
        setTitleVerticalPositionAdjustment(-10, for: UIBarMetrics.default)

        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: customHeight)
                subview.backgroundColor = .yellow

            }

            stringFromClass = NSStringFromClass(subview.classForCoder)
            if stringFromClass.contains("BarContent") {

                subview.frame = CGRect(x: subview.frame.origin.x, y: 20, width: subview.frame.width, height: customHeight - 20)

                subview.backgroundColor = UIColor(red: 20/255, green: 20/255, blue: 20/255, alpha: 0.4)

            }
        }
    }


}

Установить раскадровку

введите здесь описание изображения

Установить класс NavigationBar

Установить пользовательский класс 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.

И я удалил backgroundColor BarContentView.

введите здесь описание изображения

Это оно.

person Shawn Baek    schedule 23.09.2017
comment
Спасибо. Я попробую. - person daydr3am3r; 25.09.2017
comment
Спасибо. Но верхняя часть Безопасной зоны не обновляется. Верх безопасной зоны по-прежнему 44 пикселя. У тебя есть решение? Я не знаю, как обновить верхнюю часть безопасной зоны после установки высоты панели навигации. - person Shawn Baek; 02.10.2017
comment
@VictorRay Не могли бы вы поделиться своим кодом? Я использую этот код в своем проекте. Я хочу помочь тебе - person Shawn Baek; 09.12.2017
comment
iOS 11.2 ломает это - person dubbeat; 11.12.2017
comment
В моем случае внешний вид работает нормально, но любой элемент управления, который я добавляю в эти дополнительные 22 пикселя, не реагирует на сенсорный ввод. У меня есть большая кнопка, которая выходит за границу, скажем, начинается сверху 25 пикселей и заканчивается внизу 60 пикселей. Я пытаюсь щелкнуть по нему, и только те клики, которые находятся в пределах верхних 44 пикселей (высота полосы по умолчанию), проходят и принимаются. - person frangulyan; 21.12.2017
comment
не работал. на самом деле это выглядит хуже, если переместить вид вверх для iPhone X. - person CodeOverRide; 23.12.2017
comment
установка frame = newValue в `layoutSubviews()' вызовет бесконечный цикл с iOS 11.2, к сожалению - person Bersaelor; 06.01.2018