В iOS13 цвет фона строки состояния отличается от панели навигации в режиме большого текста

Problems demo

Предварительные условия для воспроизведения проблемы:

  1. Xcode 11 beta + iOS 13 (последняя версия до 12 июня 2019 г.)
  2. Панель навигации находится в режиме большого текста
  3. Укажите цвет панели навигации.

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

Решения, которые я пробовал:

  1. Вернуть его обратно на iOS12 поможет, но в конечном итоге мы столкнемся с iOS13...
  2. отключение режима большого текста решит эту проблему...
  3. скрыть строку состояния исправит это, но это приведет к перекрытию текста статуса с элементом панели навигации.

Есть идеи? ценю любую помощь.

Ответ 1

Никаких хаков или фанков здесь не требуется. Ключ определяет желаемый внешний вид и устанавливает это значение в ОБА навигационной панели standardAppearance И ее scrollEdgeAppearance. В инициализации моего базового подкласса контроллера навигации для всего моего приложения есть следующее:

if #available(iOS 13.0, *) {
    let navBarAppearance = UINavigationBarAppearance()
    navBarAppearance.configureWithOpaqueBackground()
    navBarAppearance.titleTextAttributes = [.foregroundColor: UIColor.white]
    navBarAppearance.largeTitleTextAttributes = [.foregroundColor: UIColor.white]
    navBarAppearance.backgroundColor = <insert your color here>
    navigationBar.standardAppearance = navBarAppearance
    navigationBar.scrollEdgeAppearance = navBarAppearance
}

enter image description here

Ответ 2

На iOS 13 навигационные панели, использующие большое название, имеют прозрачный цвет в соответствии с рекомендациями по интерфейсу пользователя Apple. Больше информации здесь:

В iOS 13 и более поздних версиях большая панель навигации заголовка не включает фоновый материал или тень по умолчанию. Кроме того, большой заголовок переходит к стандартному заголовку, когда люди начинают прокручивать контент.

Ответ 3

Если проблема в том, что вы хотите придать навигационной панели цвет при отображении большого заголовка, используйте новый класс UINavigationBarAppearance.

    let app = UINavigationBarAppearance()
    app.backgroundColor = .blue
    self.navigationController?.navigationBar.scrollEdgeAppearance = app

Ответ 4

Универсальный код

        let navBarAppearance = UINavigationBarAppearance()
        navBarAppearance.configureWithOpaqueBackground()
        navBarAppearance.backgroundColor = // your color
        navBarAppearance.shadowImage = nil // line
        navBarAppearance.shadowColor = nil // line
        UINavigationBar.appearance(whenContainedInInstancesOf: [UINavigationController.self]).standardAppearance = navBarAppearance
        UINavigationBar.appearance(whenContainedInInstancesOf: [UINavigationController.self]).scrollEdgeAppearance = navBarAppearance

Ответ 5

Для iOS 13 у меня была проблема с появлением линии тени бара. Установка теневого изображения Bars на nil решила эту проблему.

До

func configureNavigation() {
        let navBarAppearance = UINavigationBarAppearance()
        navBarAppearance.configureWithOpaqueBackground()
        navBarAppearance.largeTitleTextAttributes = [.foregroundColor: UIColor.myColor,
                                                     .font: UIFont(name: "MyFont", size: 42)!]
        navBarAppearance.backgroundColor = .white
        navigationController?.navigationBar.isTranslucent = false
        navigationController?.navigationBar.scrollEdgeAppearance = navBarAppearance
    }

Image with shadow

После

func configureNavigation() {
        let navBarAppearance = UINavigationBarAppearance()
        navBarAppearance.configureWithOpaqueBackground()
        navBarAppearance.largeTitleTextAttributes = [.foregroundColor: UIColor.myColor,
                                                     .font: UIFont(name: "MyFont", size: 42)!]
        navBarAppearance.backgroundColor = .white
        navBarAppearance.shadowColor = nil
        navigationController?.navigationBar.isTranslucent = false
        navigationController?.navigationBar.scrollEdgeAppearance = navBarAppearance
    }

Image without shadow

Ответ 6

Решения Objective C и iOS 13

UINavigationBarAppearance* navBarAppearance = [self.navigationController.navigationBar standardAppearance];
        [navBarAppearance configureWithOpaqueBackground];
        navBarAppearance.titleTextAttributes = @{NSForegroundColorAttributeName:TitleColor};
        navBarAppearance.largeTitleTextAttributes = @{NSForegroundColorAttributeName: TitleColor};
        navBarAppearance.backgroundColor = TopColor;
        self.navigationController.navigationBar.standardAppearance = navBarAppearance;
        self.navigationController.navigationBar.scrollEdgeAppearance = navBarAppearance;

Ответ 7

Я обнаружил, что с раскадровками вы должны подделывать навигационную панель (действительно работает только с непрозрачными навигационными панелями, предполагая, что ваш зеленый непрозрачен). Лучший способ, который я нашел, - создать вид заполнителя (фиолетовый), который подходит для вставок в безопасной области, а затем добавить поддельный вид за панелью навигации (голубой/синий), то есть оставшуюся высоту. Работает на мой проект, но да, это немного взломать. Screenshot from Xcode 11 beta 4 displaying constraints required for status bar hack

Изменение: Это в основном для LaunchScreen.storyboard, где вы не можете использовать пользовательский класс контроллера представления.

Ответ 8

Спасибо Майк и Ганс ответ. Мой случай - полупрозрачная строка состояния и панель навигации с альфа 0,5. iOS13 кажется сложным. Ниже приведен мой результат теста, будет работать, если вы хотите прозрачный для обоих.

if #available(iOS 13.0, *) {
                let navBarAppearance = UINavigationBarAppearance()
                // This only set top status bar as transparent, not the nav bar.
                navBarAppearance .configureWithTransparentBackground()
                // This set the color for both status bar and nav bar(alpha 1).
                navBarAppearance.backgroundColor = UIColor.red.withAlphaComponent(0.5)
                navigationController?.navigationBar.standardAppearance = navBarAppearance
                navigationController?.navigationBar.scrollEdgeAppearance = navBarAppearance
                // Nav bar need sets to translucent for both nav bar and status bar to be translucent.
                navigationController?.navigationBar.isTranslucent = true
                // // Need to reset nav bar color to make it clear to display navBarAppearance color
                navigationController?.navigationBar.backgroundColor = UIColor.clear
               } 

Ответ 9

Swift 5

override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
    super.traitCollectionDidChange(previousTraitCollection)

    let userInterfaceStyle = traitCollection.userInterfaceStyle
    modeDetect(userInterfaceStyle: userInterfaceStyle)

}

override func viewDidAppear(_ animated: Bool) {
    navigationController?.navigationBar.barStyle = .black
    navigationController?.navigationBar.titleTextAttributes = [.foregroundColor: UIColor.white]
}

func modeDetect(userInterfaceStyle: UIUserInterfaceStyle) {
    switch userInterfaceStyle {
    case .light:
        navigationController?.navigationBar.barTintColor = .systemPink
    case .dark:
        navigationController?.navigationBar.barTintColor = .systemBackground
    default:
        break
    }
}

Ответ 10

Следующий код заставил навигационную панель iOS 13 вести себя так же, как и предыдущая версия:

if #available(iOS 13.0, *) {
    // Setup iOS 13 navigation bar
    sharedSelector.navigationBar.scrollEdgeAppearance = sharedSelector.navigationBar.standardAppearance;
} else {
    <#fallback statements#>
}

Ответ 11

мое расширение навигационной панели, iOS 13 Swift 5

extension UIViewController {
func configureNavigationBar(largeTitleColor: UIColor, backgoundColor: UIColor, tintColor: UIColor, title: String, preferredLargeTitle: Bool) {
    if #available(iOS 13.0, *) {
        let navBarAppearance = UINavigationBarAppearance()
        navBarAppearance.configureWithOpaqueBackground()
        navBarAppearance.largeTitleTextAttributes = [.foregroundColor: largeTitleColor]
        navBarAppearance.titleTextAttributes = [.foregroundColor: largeTitleColor]
        navBarAppearance.backgroundColor = backgoundColor

        navigationController?.navigationBar.standardAppearance = navBarAppearance
        navigationController?.navigationBar.compactAppearance = navBarAppearance
        navigationController?.navigationBar.scrollEdgeAppearance = navBarAppearance

        navigationController?.navigationBar.prefersLargeTitles = preferredLargeTitle
        navigationController?.navigationBar.isTranslucent = false
        navigationController?.navigationBar.tintColor = tintColor
        navigationItem.title = title

    } else {
        // Fallback on earlier versions
        navigationController?.navigationBar.barTintColor = backgoundColor
        navigationController?.navigationBar.tintColor = tintColor
        navigationController?.navigationBar.isTranslucent = false
        navigationItem.title = title
    }
}}

Как использовать:

configureNavigationBar(largeTitleColor: .yourColor, backgoundColor: .yourColor, tintColor: .yourColor, title: "YourTitle", preferredLargeTitle: true)

Установите строку состояния на основе ViewController...... на NO в info.plist, если вы хотите легкий контент

Если вы не хотите, чтобы для LargeTitles было задано значение false

Проверено на iOS 13, надеюсь, это поможет :)