Search code examples
iosswiftswiftuiuikit

How to remove grey background from UISearchBar inside UINavigationBar?


Normally, you can customize UISearchBar appearance, including the background color, using UIAppearance API. To customize the background color, you can use theme UISearchTextField, which is a UITextField subclass used in search bars:

UISearchTextField.appearance().backgroundColor = .blue.withAlphaComponent(0.1)

Light blue search bar

However, when UISearchBar is used in a UINavigationController, an additional background view is added with the tertiary system fill color; this will darken your search bar:

Darkened search bar

Inspecting the view hierarchy shows that this is an instance of _UISearchBarSearchFieldBackgroundView. I’ve explored all the existing stack overflow questions on changing the search bar background color and could not find a solution that works with UIAppearance and accounts for this. Is there a way to hide or change the color of the view?


Solution

  • I was able to figure out a combination of UIAppearance styles that can make this work - but it requires an extension on UIView so you can re-apply the corner radius.

    The first step is to set an empty image as the background image of the search bar field. This is sufficient to remove the extra background view:

    UISearchBar.appearance().setSearchFieldBackgroundImage(UIImage(), for: .normal)
    

    However, this results in no corner radius being applied:

    Square search bar

    To style the corner radius using UIAppearance, add the following extension to UIView (or UISearchTextField to keep it more isolated):

    private extension UIView {
        @objc dynamic var cornerRadius: CGFloat {
            get { layer.cornerRadius }
            set { layer.cornerRadius = newValue }
        }
    
        @objc dynamic var cornerCurve: CALayerCornerCurve {
            get { layer.cornerCurve }
            set { layer.cornerCurve = newValue }
        }
    }
    

    Then you can apply the default radius of 10, and a continuous curve, which will match the system:

    Properly themed search bar

    Complete solution:

    UISearchBar.appearance().setSearchFieldBackgroundImage(UIImage(), for: .normal)
    UISearchTextField.appearance().backgroundColor = .blue.withAlphaComponent(0.1)
    UISearchTextField.appearance().cornerRadius = 10
    UISearchTextField.appearance().cornerCurve = .continuous