UINavigationBar слишком низкий при использовании UIScreen.main.bounds в качестве фрейма UIWindow

#ios #swift #uinavigationbar #appdelegate #uiscreen

#iOS #swift #uinavigationbar #appdelegate #uiscreen

Вопрос:

Я создаю приложение для iOS, цель развертывания 12.1, swift 4.2. Приложение использует представления контейнеров и имеет панель навигации в верхней части основных экранов, предпочтительно прямо под строкой состояния. В раскадровке launchscreen я ограничил Navigation Bar.top до Safe.Area.Top. Это работает нормально. Но после того, как я установил ContainerViewController в качестве RootViewController в AppDelegate, панель навигации, поскольку я ограничил ее в Main.storyboard (Navigation Bar.top в Safe.Area.Top) отображается намного ниже, где оно должно быть.

Единственный способ заставить панель навигации отображаться прямо под строкой состояния — создать пользовательский фрейм для моего окна в AppDelegate с отрицательным значением y — и это определенно НЕ то решение, которое меня устраивает.

Похоже, это приводит к слишком низкому значению y:

     func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.
        window = UIWindow(frame: UIScreen.main.bounds)
        let containerViewController = ContainerViewController()
        window!.rootViewController = containerViewController
        window!.makeKeyAndVisible()
        return true
    }
  

И это вопиющий взлом, который приближает панель навигации к тому месту, где она должна быть:

     func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.
        //window = UIWindow(frame: UIScreen.main.bounds)
        let hackedFrame = CGRect(x: 0, y: -44, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height)
        window = UIWindow(frame: hackedFrame)
        let containerViewController = ContainerViewController()
        window!.rootViewController = containerViewController
        window!.makeKeyAndVisible()
        //window!.windowLevel = UIWindow.Level.statusBar
        return true
    }
  

Захват экрана:

экран запуска, панель навигации исправлены

сообщение на главном экране завершило запуск с параметрами, панель навигации слишком низкая

Вероятно, я здесь упускаю что-то действительно очевидное, но я был бы признателен за любую помощь, которую кто-либо может оказать.

Спасибо.

Комментарии:

1. Если мы создаем «window» и его «RootViewController» с помощью кода внутри «делегата приложения», main.storyboard станет бесполезным. Приложение покажет только те изменения, которые вы внесете внутри класса viewcontroller.

2. Пожалуйста, поделитесь также кодом вашего класса ContainerViewController, это поможет нам дать лучший ответ.

3. Действительно ли раскадровка становится бесполезной? Как вы видите на скриншотах, которые я опубликовал, панель навигации и кнопка, которые я создаю, все еще существуют. Кнопка работает отлично. Он просто установил ~ 44 точки слишком низко.

4. По моему опыту, это становится бесполезным, если amp; пока вы специально не вызовете раскадровку в своем коде где-нибудь. Учитывая ваш сценарий, я думаю, вы, должно быть, добавили «панель навигации» где-нибудь в свой «ContainerViewController» класс «code» также.

5. Я понимаю, о чем ты говоришь. Я действительно выяснил основную причину проблемы. Я основываю свой проект на уже существующем коде другого пользователя (всегда опасно). Они были нацелены на более раннюю версию ОС и использовали руководства по компоновке, которые сейчас устарели. Короче говоря, я обрабатываю пользовательский интерфейс в основном программно, и у меня нет проблем. В любом случае, спасибо за вашу помощь!

Ответ №1:

В iOS 11 Apple представила большие заголовки на панели навигации, что означает, что ее можно растянуть, если потянуть. Вы должны попробовать установить

 navigationItem.largeTitleDisplayMode = .never
  

В вашем viewDidLoad и установите для prefersLargeTitles вашей панели навигации значение false

 if #available(iOS 11.0, *) {
   navigationItem.largeTitleDisplayMode = .always
   navigationController?.navigationBar.prefersLargeTitles = true
} 
  

Комментарии:

1. Спасибо за ответ, но это не решило проблему.

2. Вы пытались сделать верхнее ограничение навигационной панели относительно ее супервизора вместо безопасной области?

3. ДА. Пробовал как безопасную область, так и супервизор. Ни то, ни другое, похоже, не сработало.

Ответ №2:

попробуйте добавить панель навигации в ViewController вместо AppDelegate следующим образом:

 var screenWidth : CGFloat!
var screenHeight : CGFloat!
let screenSize: CGRect = UIScreen.main.bounds
  

внутри viewDidLoad:

 screenWidth = screenSize.width
screenHeight = screenSize.height

navigationBar = UINavigationBar(frame: CGRect(x: 0, y: 20, width: screenWidth, height: screenWidth / 3))
  

для добавления заголовка и кнопки:

 view.addSubview(navigationBar)
    let navItem = UINavigationItem(title: "MainController")
    let doneItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonItem.SystemItem.cancel, target: nil, action: #selector(DismissViewController))
    navItem.leftBarButtonItem = doneItem
    UINavigationBar.appearance().barTintColor = .white
    navigationBar.setItems([navItem], animated: false)
  

Комментарии:

1. Да, похоже, это сработало. Признаюсь, я новичок в iOS и xcode, но, черт возьми, мне ужасно повезло с interface builder. Программные решения проблем пользовательского интерфейса обычно работают лучше всего для меня. Спасибо.

2. Я делаю то же самое с прошлой недели, теперь я делаю весь пользовательский интерфейс в коде, я удаляю раскадровку сразу после запуска нового проекта, я рекомендую вам использовать библиотеку Snapkit для управления пользовательским интерфейсом, это действительно упрощает для вас