Search code examples
iosuinavigationbaruisearchbarios12ios13

UISearchBar color in NavigationBar


I feel like I’m taking crazy pills. I want to change the color of the textfield within a UISearchBar, which is hosted in a UINavigationBar. The problem I’m having is that the UISearchBar gets the color of the UINavigationBar but the TextField doesn’t change color. I’ve tried several solutions here, but none of them seem to solve the issue. Any ideas how to change the TextField’s color?

I know there are other questions out there similar to this but I’ve tried every possible solution I’ve come across and haven’t found one that solves my issue.

Current Nav Bar with Attempted Bar tint

Current Code:

        let sc = UISearchController(searchResultsController: nil)
        sc.delegate = self
        let scb = sc.searchBar
        scb.tintColor = UIColor.green
        scb.barTintColor = UIColor.yellow


        if let textfield = scb.value(forKey: "searchField") as? UITextField {
            textfield.textColor = UIColor.blue
            if let backgroundview = textfield.subviews.first {

                // Background color
                backgroundview.backgroundColor = UIColor.red

                // Rounded corner
                backgroundview.layer.cornerRadius = 5;
                backgroundview.clipsToBounds = true;

            }
        }

        navigationController?.navigationBar.barTintColor = UIColor.blue

        navigationItem.searchController = sc
        navigationItem.hidesSearchBarWhenScrolling = false

I’ve created a sample project to show it in action. Any help or guidance would be greatly appreciated!


Solution

  • Maybe the best solution is for creating an extension for UISearchBar if you want to use these settings in more controllers. Here are some example.

    extension UISearchBar {
    
        private func getViewElement<T>(type: T.Type) -> T? {
    
            let svs = subviews.flatMap { $0.subviews }
            guard let element = (svs.filter { $0 is T }).first as? T else { return nil }
            return element
        }
    
        func getSearchBarTextField() -> UITextField? {
            return getViewElement(type: UITextField.self)
        }
    
        func setTextColor(color: UIColor) {
    
            if let textField = getSearchBarTextField() {
                textField.textColor = color
            }
        }
    
        func setTextFieldColor(color: UIColor) {
    
            if let textField = getViewElement(type: UITextField.self) {
                switch searchBarStyle {
                case .minimal:
                    textField.layer.backgroundColor = color.cgColor
                    textField.layer.cornerRadius = 6
                case .prominent, .default:
                    textField.backgroundColor = color
                @unknown default:
                    print("something")
                }
            }
        }
    
        func setPlaceholderTextColor(color: UIColor) {
    
            if let textField = getSearchBarTextField() {
                textField.attributedPlaceholder = NSAttributedString(string: self.placeholder != nil ? self.placeholder! : "", attributes: [NSAttributedString.Key.foregroundColor: color])
            }
        }
    
        func setTextFieldClearButtonColor(color: UIColor) {
    
            if let textField = getSearchBarTextField() {
    
                let button = textField.value(forKey: "clearButton") as! UIButton
                if let image = button.imageView?.image {
                    button.setImage(image.transform(withNewColor: color), for: .normal)
                }
            }
        }
    
        func setSearchImageColor(color: UIColor) {
    
            if let imageView = getSearchBarTextField()?.leftView as? UIImageView {
                imageView.image = imageView.image?.transform(withNewColor: color)
            }
        }
    }
    

    Update:

    Change navigationItem.searchController = sc to navigationItem.titleView = sc.searchBar. enter image description here