Why is UISearchController changing the navigation bar colors?
Asked Answered
P

1

9

I have tested this on a sample project with 2 view controllers defined in the storyboard using Xcode 11 (iOS 13). The "presenting" view controller is embedded in a navigation controller and has the navigation bar colors set in the viewWillAppear. The "search" view controller adds a UISearchController in the viewDidLoad and is pushed by the presenting view controller (NOT modal).

With just this setup when the search view controller is displayed the navigation bar has the blue background and red tint color as expected. However when scrolling down and the search bar is displayed the background color of the navigation bar is lost (or changed to what appears to be the default iOS grey / translucent). However if you scroll back up (hide the search bar) or focus on the search bar text field the navigation bar color returns!

Also if you focus on the search bar text field and then cancel (by tapping the Cancel button) the tint color of the navigation bar reverts from red to the default iOS blue as can be noticed by the back bar item.

Navigation Bar on Load

Navigation Bar on Search

Focus on Search Bar

Cancel Search Bar

Any suggestions on resolving this issue?

I have set the navigation bar colors in the viewWillAppear of the search controller too which didn't change this behaviour.

I set isTranslucent to true for the navigation bar in the search controller which seemed to prevent the reverting of the background color but it did not change the reverting of the tint color on cancel.

Presenting View Controller

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)

    navigationController?.navigationBar.barTintColor = .blue
    navigationController?.navigationBar.tintColor = .red
}

Search View Controller

override func viewDidLoad() {
    super.viewDidLoad()

    self.title = "Search VC"

    searchController.dimsBackgroundDuringPresentation = false
    searchController.obscuresBackgroundDuringPresentation = false

    navigationItem.searchController = searchController

    definesPresentationContext = true
}

EDIT

Setting the scrollEdgeAppearance, backButtonAppearance and buttonAppearance as suggested works a treat except for system bar buttons that default to the iOS blue. This can be resolved by setting the UINavigationBar.tintColor but neither that resolves the back button chevron color defaulting on cancel of the search.

Navigation Bar on Cancel

if #available(iOS 13.0, *) {
    let buttonAppearance = UIBarButtonItemAppearance()
    buttonAppearance.configureWithDefault(for: .plain)
    buttonAppearance.normal.titleTextAttributes = [.foregroundColor: UIColor.red]

    let navigationBarAppearance = UINavigationBarAppearance()
    navigationBarAppearance.configureWithOpaqueBackground()
    navigationBarAppearance.backgroundColor = .blue
    navigationBarAppearance.titleTextAttributes = [.foregroundColor: UIColor.red]

    navigationBarAppearance.backButtonAppearance = buttonAppearance
    navigationBarAppearance.buttonAppearance = buttonAppearance
    navigationBarAppearance.doneButtonAppearance = buttonAppearance

    navigationController?.navigationBar.scrollEdgeAppearance = navigationBarAppearance
    navigationController?.navigationBar.compactAppearance = navigationBarAppearance
    navigationController?.navigationBar.standardAppearance = navigationBarAppearance
} else {
    navigationController?.navigationBar.barTintColor = .blue
    navigationController?.navigationBar.titleTextAttributes = [.foregroundColor: UIColor.red]
    navigationController?.navigationBar.tintColor = .red
}
Pandanus answered 22/10, 2019 at 1:10 Comment(1)
Many thanks for your answer! But please put your answer into the answer of this question because normally people are looking for answers in answers but in the question, and as you know people don't read everything so I really spent a bit of time to investigate and then, in the end, decided to read your question fully and was lucky to find an answer. Also, I think it's StackOverflow's feature that you can also post an answer to your own question which is totally normal. So I'd highly recommend it.Lohse
W
4

However when scrolling down and the search bar is displayed the background color of the navigation bar is lost

All of that is normal. New in iOS 13, the expanded nav bar (displaying search bar, large title, etc.) has different appearance from the normal nav bar. Your settings applied only to the normal nav bar because you didn't make them the iOS 13 way. If you want the expanded nav bar to look like the normal nav bar, you have to set its appearance separately and explicitly.

To do so, you need to set the navigation bar's scrollEdgeAppearance. Investigate classes UIBarAppearance, UINavigationBarAppearance, and UIBarButtonItemAppearance (you will need to set the backButtonAppearance explicitly).

Waken answered 22/10, 2019 at 1:23 Comment(3)
Thanks @matt. Any documentation you are aware of with regards to this nav bar behaviour on iOS 13?Pandanus
https://mcmap.net/q/1071305/-ios-13-navigationbar-barstyle-is-ignored-when-using-uinavigationbarappearance check this answer , although it is not the exact issue you are facing , the fix that should follow is there , just change your attributes , i think you should do a lilttle check up on Ios 13 changes alot has changed including Tab bar , Navigation Bar, Push notifications , table view hierarchies and much moreLactobacillus
do like that, preferredStatusBarStyle is alway defaultEthics

© 2022 - 2024 — McMap. All rights reserved.