Установите высоту UINavigationBar пропорционально размеру экрана

avatar
Maray97
8 августа 2021 в 21:57
73
1
0

У меня есть 5 вкладок в UITabBarController, и каждая из них встроена в UINavigationController. Я хотел бы установить высоту этой вкладки на 8% экрана, но я не могу установить ограничения для StoryBoard, также, если я попытаюсь установить его из кода, он станет черным и сломает элементы управления пользовательского интерфейса. Код для моего UINavigationController таков:


class NavBarController: UINavigationController {
    override func viewDidLayoutSubviews() {
        self.navigationBar.topItem?.titleView = UIImageView(image: UIImage(named: "image"))
        self.navigationBar.topItem?.titleView?.contentMode = .scaleAspectFit
        let gradient = CAGradientLayer()
        var bounds = self.navigationBar.bounds
        bounds.size.height += self.view.window?.windowScene?.statusBarManager?.statusBarFrame.height ?? 0
        bounds.origin.y -= self.view.window?.windowScene?.statusBarManager?.statusBarFrame.height ?? 0
        gradient.frame = bounds
        gradient.colors = [UIColor.black, UIColor.white]
        gradient.locations = [0.0, 1.0]
        self.navigationBar.setBackgroundImage(image(fromLayer: gradient), for: .default)
    }
    
    func image(fromLayer layer: CALayer) -> UIImage {
        UIGraphicsBeginImageContext(layer.frame.size)
        layer.render(in: UIGraphicsGetCurrentContext()!)
        let outputImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return outputImage!
    }
}

Я пытался установить:

self.navigationBar.frame.size.height = (self.view.superview?.frame.height)! * 0.08
self.navigationBar.layoutIfNeeded()

в начале viewDidLayoutSubviews, но это не работает, а также нарушает градиентный фон. Кто-нибудь может мне помочь? Идеальным решением было бы использование раскадровки, но я не могу просто установить ограничение высоты UINavigationItem на его высоту просмотра.

Источник
user1922718
9 августа 2021 в 05:42
0

Вы пытались выполнить этот код, переопределив layout() или updateConstraints()? Я считаю, что viewDidLayoutSubviews() слишком поздно в цикле рендеринга. Вы захотите создать подкласс UINavigationBar и выполнить переопределение в своем пользовательском подклассе.

Maray97
9 августа 2021 в 07:21
0

@user1922718 user1922718 нет, я не пробовал, потому что у меня были некоторые проблемы с градиентом, но я попробую. Спасибо. Как получить доступ к высоте супервизора? self.navigationController.view.superview...?

user1922718
9 августа 2021 в 18:14
0

Вызов superview для любого представления даст вам его родительское представление, если представление находится в иерархии представлений. Таким образом, вы можете получить высоту супервизора, позвонив по телефону view.superview.frame.height

Maray97
10 августа 2021 в 11:16
0

@user1922718 user1922718 Я пробовал по-разному, переопределяя layoutSubviews(), updateConstraints() и т. д., а также снова пробовал в контроллере. Ничего, я не могу установить эту чертову высоту полосы.

user1922718
10 августа 2021 в 16:09
0

Еще одна вещь, которую вы можете попробовать, это создать подкласс UINavigationBar и написать наблюдатель didSet для переменной frame. Затем установите точку останова в отладчике и отмечайте каждый раз, когда эта переменная изменяется и в какой момент цикла рендеринга. Это даст вам подсказки относительно того, когда вам нужно установить высоту полосы.

Ответы (1)

avatar
user1922718
11 августа 2021 в 00:46
1

Потратив некоторое время на изучение этого вопроса, я обнаружил, что в процессе перехода UINavigationBar несколько раз присваивается высота 44 пункта. Так как UIKit настаивает на высоте 44, я решил немного поэкспериментировать с пользовательским сеттером.

class NavigationBar: UINavigationBar {
    private var _frame: CGRect!
    override var frame: CGRect {
        set {
            _frame = CGRect(origin: newValue.origin, size: CGSize(width: newValue.width, height: 22))
        }
        get {
            _frame
        }
    }
}

Здесь я увеличиваю высоту панели навигации до 22 пунктов. Однако после компиляции и запуска навигационная панель по-прежнему 44. Почему? Поскольку UIKit также устанавливает ограничение, заставляя высоту равняться 44. Это означает, что AutoLayout возвращает высоту к 44 при компоновке. Кажется, это то, что Apple действительно не хочет, чтобы вы меняли. enter image description here

Maray97
11 августа 2021 в 01:39
1

Спасибо, несколько минут назад я прочитал то же самое в документации, думаю, тогда я создам свой собственный NavBar, потому что мне нужно следовать макету. Спасибо за ваше время