Search code examples
iosuibarbuttonitemios13

How to set bar button item background image globally in iOS 13


iOS 13 has a whole new set of classes for configuring navigation bars and bar button items:

  • UIBarAppearance
  • UINavigationBarAppearance
  • UIBarButtonItemAppearance
  • UIBarButtonItemStateAppearance

How do I use these to give bar button items a global appearance? Let's say I want all bar button items to have a common background image. I used to say:

UIBarButtonItem.appearance().setBackgroundImage(im, for:.normal, barMetrics:.default)

This seems to be just what is superseded by these new classes. So what's the right way now?


Solution

  • It's verbose, but in some ways it's clearer. You can configure a navigation bar appearance and assign it to the navigation bar's standardAppearance through the proxy:

        let app = UIBarButtonItemAppearance()
        app.normal.backgroundImage = im
        let navbarapp = UINavigationBarAppearance()
        navbarapp.configureWithOpaqueBackground()
        navbarapp.buttonAppearance = app
        UINavigationBar.appearance().standardAppearance = navbarapp
    

    The only problem with that is that it assigns the same background image to back button items. So if that's not desired, you have to code defensively, assigning back button items an empty (not nil) image:

        let app = UIBarButtonItemAppearance()
        app.normal.backgroundImage = im
        let navbarapp = UINavigationBarAppearance()
        navbarapp.configureWithOpaqueBackground()
        navbarapp.buttonAppearance = app
        let back = UIBarButtonItemAppearance()
        back.normal.backgroundImage = UIImage() // prevent back button item
        navbarapp.backButtonAppearance = back
        UINavigationBar.appearance().standardAppearance = navbarapp