Stephen Chen
Stephen Chen

Reputation: 3057

IOS UISearchBar Background Color In iOS 9

I have been search a while for this issue , I want my search bar display like BBC News AppSearchBar In BBC News APP

I try all related method

  for view in searchBar.subviews {
        if view.isKindOfClass(NSClassFromString("UISearchBarBackground")!) {
            view.removeFromSuperview()
            break;
        }
  }

    self.searchBar.tintColor = UIColor.clearColor()
    self.searchBar.backgroundColor = UIColor.clearColor()
    self.searchBar.translucent = true

here is my output enter image description here

Am I miss something ??? Please Help me , thx !

Upvotes: 12

Views: 19844

Answers (5)

Alex Bro
Alex Bro

Reputation: 109

In my case it helped:

searchView.backgroundImage = UIImage()
searchView.searchTextField.backgroundColor = .white

Upvotes: 2

Joshua Sharo
Joshua Sharo

Reputation: 31

The current answers will cause runtime errors if run within iOS 13:

Terminating app due to uncaught exception 'NSGenericException', reason:
'Missing or detached view for search bar layout. The application must not remove
<UISearchBarBackground: 0x102d05050; frame = (0 0; 414 56); alpha = 0; hidden = YES;
userInteractionEnabled = NO; layer = <CALayer: 0x280287420>> from the hierarchy.'

If the code must be run by devices between iOS 9 and iOS 13, then the below is a possible solution.

First, create an extension that allows for the recursive finding of a subview based on a class name:

extension UIView {
/// Find the first subview of the specified class.
/// - Parameter className: The class name to search for.
/// - Parameter usingRecursion: True if the search should continue through the subview tree until a match is found; false otherwise
/// - Returns: The first child UIView of the specified class
func findSubview(withClassName className: String, usingRecursion: Bool) -> UIView? {
    // If we can convert the class name until a class, we look for a match in the subviews of our current view
    if let reflectedClass = NSClassFromString(className) {
        for subview in self.subviews {
            if subview.isKind(of: reflectedClass) {
                return subview
            }
        }
    }

    // If recursion was specified, we'll continue into all subviews until a view is found
    if usingRecursion {
        for subview in self.subviews {
            if let tempView = subview.findSubview(withClassName: className, usingRecursion: usingRecursion) {
                return tempView
            }
        }
    }

    // If we haven't returned yet, there was no match
    return nil
}
}

Then, instead of removing the subview, make it fully transparent. The backgroundColorView view is the color that shows up directly underneath the text, but adjusting it is not a necessary part of the solution.

    // On iOS 9, there is still an image behind the search bar. We want to remove it.
    if let backgroundView = searchBar.findSubview(withClassName: "UISearchBarBackground", usingRecursion: true) {
        backgroundView.alpha = 0
    }

    // The color on iOS 9 is white. This mimics the newer appearance of the post-iOS 9
    // search controllers
    if let backgroundColorView = searchBar.findSubview(withClassName: "_UISearchBarSearchFieldBackgroundView", usingRecursion: true) as? UIImageView {
        backgroundColorView.backgroundColor = UIColor.lightGray
        backgroundColorView.layer.cornerRadius = 8
        backgroundColorView.alpha = 0.3
        backgroundColorView.image = nil
    }

Upvotes: 1

Stephen Chen
Stephen Chen

Reputation: 3057

Thx all , I solve the question by setting the background image to 'nil' , which is a nonexistent image in my app

enter image description here

my final output enter image description here

==================== Update Final Solution ====================

After read more documents . Finally I found a better solution ,

for subView in searchBar.subviews {
        for view in subView.subviews {
            if view.isKindOfClass(NSClassFromString("UINavigationButton")!) {
                let cancelButton = view as! UIButton
                cancelButton.setTitle("取消", forState: UIControlState.Normal)
                cancelButton.setTitleColor(UIColor.whiteColor(), forState: .Normal)
            }
            if view.isKindOfClass(NSClassFromString("UISearchBarBackground")!) {
                let imageView = view as! UIImageView
                imageView.removeFromSuperview()
            }
        }
    }

==================== Update Swift4 ====================

for subView in searchBar.subviews {
        for view in subView.subviews {
            if view.isKind(of: NSClassFromString("UINavigationButton")!) {
                let cancelButton = view as! UIButton
                cancelButton.setTitleColor(.white, for: .normal)
                cancelButton.setTitle("取消", for: .normal)
            }
            if view.isKind(of: NSClassFromString("UISearchBarBackground")!) {
                let imageView = view as! UIImageView
                imageView.removeFromSuperview()
            }
        }
    }

Upvotes: 11

Mari&#225;n Čern&#253;
Mari&#225;n Čern&#253;

Reputation: 15738

Swift 3

To remove the background altogether, set backgroundImage to an empty image:

searchBar.backgroundImage = UIImage()

To set a custom background color, use barTintcolor property:

searchBar.barTintColor = .green

Upvotes: 34

LuAndre
LuAndre

Reputation: 1133

Alternate version as an extension

extension UISearchBar {
    func removeBackgroundImageView(){
        if let view:UIView = self.subviews.first {
            for curr in view.subviews {
                guard let searchBarBackgroundClass = NSClassFromString("UISearchBarBackground") else {
                    return
                }
                if curr.isKind(of:searchBarBackgroundClass){
                    if let imageView = curr as? UIImageView{
                        imageView.removeFromSuperview()
                        break
                    }
                }
            }
        }
    }
}

Upvotes: 5

Related Questions