Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bar Button tint color in iOS 13

In iOS 13, they have changed the way that the nav bar colors operate. Now they use UINavigationBarAppearance along with UIBarButtonItemAppearance to customize the nav bar, along with standardAppearance & scrollEdgeAppearance.

I'm looking for a way to have different nav bar tint colors for standardAppearance & scrollEdgeAppearance. Or the ability to change bar button icon colors for each appearance.

        //set the standard nav bar appearance
        let navBarAppearance = UINavigationBarAppearance()
        navBarAppearance.configureWithOpaqueBackground()
        navBarAppearance.titleTextAttributes = [.foregroundColor: UIColor.white]
        navBarAppearance.largeTitleTextAttributes = [.foregroundColor: UIColor.white]
        navBarAppearance.backgroundColor = UIColor.mainAppColorForNavBar

        //set bar button appearance
        let buttonAppearance = UIBarButtonItemAppearance()
        buttonAppearance.normal.titleTextAttributes = [.foregroundColor : UIColor.white]
        navBarAppearance.buttonAppearance = buttonAppearance

        UINavigationBar.appearance(whenContainedInInstancesOf: [UINavigationController.self]).standardAppearance = navBarAppearance



        //set the scroll edge nav bar appearance
        let scrollNavBarAppearance = UINavigationBarAppearance()
        scrollNavBarAppearance.configureWithOpaqueBackground()
        scrollNavBarAppearance.titleTextAttributes = [.foregroundColor: UIColor.label]
        scrollNavBarAppearance.largeTitleTextAttributes = [.foregroundColor: UIColor.label]

        //set bar button appearance
        let scrollButtonAppearance = UIBarButtonItemAppearance()
        scrollButtonAppearance.normal.titleTextAttributes = [.foregroundColor : UIColor.label]
        scrollNavBarAppearance.buttonAppearance = scrollButtonAppearance

        UINavigationBar.appearance(whenContainedInInstancesOf: [UINavigationController.self]).scrollEdgeAppearance = scrollNavBarAppearance

This will set the nav bar tint color but does not distinguish between standardAppearance & scrollEdgeAppearance.

UINavigationBar.appearance().tintColor = UIColor.white

currently in scrollEdgeAppearance (looks the way I want, no changes needed) enter image description here

currently in standardAppearance (the button is lost because it's the same color as the background, I want to change the icon color to white in standardAppearance ) enter image description here

Any help is appreciated.

Thanks,

like image 957
user1184205 Avatar asked Sep 15 '19 01:09

user1184205


1 Answers

I ran into a similar issue for the back button and solved it with setting an image with a different rendering mode for each appearance. This avoids a tintColor being applied.

// demo image
let image = UIImage(systemName: "ellipsis.circle")!

// image with .alwaysOriginal rendering mode to avoid tintColor application
let imageForNavBarAppearance = image
    .withTintColor(.black)
    .withRenderingMode(.alwaysOriginal)
let imageForScrollNavBarAppearance = image
    .withTintColor(.green)
    .withRenderingMode(.alwaysOriginal)

// your UINavigationBarAppearance instances
navBarAppearance.setBackIndicatorImage(imageForNavBarAppearance, transitionMaskImage: imageForNavBarAppearance)
scrollNavBarAppearance.setBackIndicatorImage(imageForScrollNavBarAppearance, transitionMaskImage: imageForScrollNavBarAppearance)

This solves it for back buttons only.

There are two other options to set background images for bar item appearances.

UINavigationBarAppearance.buttonAppearance The appearance configuration with the background image would be applied to all bar items. This should be fine, since you only have one bar item.

UINavigationBarAppearance.doneButtonAppearance If you'd create a done-style bar item for your top-right "+" symbol, this appearance configuration should apply.

let ap = UIBarButtonItemAppearance()
ap.normal.backgroundImage = image.withTintColor(.black).withRenderingMode(.alwaysOriginal)

let scrollAp = UIBarButtonItemAppearance()
scrollAp.normal.backgroundImage = image.withTintColor(.green).withRenderingMode(.alwaysOriginal)

// apply to all bar items
navBarAppearance.buttonAppearance = ap
scrollNavBarAppearance.buttonAppearance = scrollAp

// or apply to done buttons
navBarAppearance.doneButtonAppearance = ap
scrollNavBarAppearance.doneButtonAppearance = scrollAp

like image 185
Philipp Kinschel Avatar answered Nov 09 '22 23:11

Philipp Kinschel