How to change UISearchBar Placeholder and image tint color?

前端 未结 12 2378
暖寄归人
暖寄归人 2020-11-29 01:24

I\'ve been trying search results for hours, but I can\'t get this figured out. Perhaps it isn\'t possible. I\'m trying to change the tint color of the placeholder text and m

12条回答
  •  醉话见心
    2020-11-29 02:19

    Details

    • Xcode Version 11.0 (11A420a), iOS 13, swift 5

    Solution

    import UIKit
    
    extension UISearchBar {
    
        func getTextField() -> UITextField? { return value(forKey: "searchField") as? UITextField }
        func set(textColor: UIColor) { if let textField = getTextField() { textField.textColor = textColor } }
        func setPlaceholder(textColor: UIColor) { getTextField()?.setPlaceholder(textColor: textColor) }
        func setClearButton(color: UIColor) { getTextField()?.setClearButton(color: color) }
    
        func setTextField(color: UIColor) {
            guard let textField = getTextField() else { return }
            switch searchBarStyle {
            case .minimal:
                textField.layer.backgroundColor = color.cgColor
                textField.layer.cornerRadius = 6
            case .prominent, .default: textField.backgroundColor = color
            @unknown default: break
            }
        }
    
        func setSearchImage(color: UIColor) {
            guard let imageView = getTextField()?.leftView as? UIImageView else { return }
            imageView.tintColor = color
            imageView.image = imageView.image?.withRenderingMode(.alwaysTemplate)
        }
    }
    
    private extension UITextField {
    
        private class Label: UILabel {
            private var _textColor = UIColor.lightGray
            override var textColor: UIColor! {
                set { super.textColor = _textColor }
                get { return _textColor }
            }
    
            init(label: UILabel, textColor: UIColor = .lightGray) {
                _textColor = textColor
                super.init(frame: label.frame)
                self.text = label.text
                self.font = label.font
            }
    
            required init?(coder: NSCoder) { super.init(coder: coder) }
        }
    
    
        private class ClearButtonImage {
            static private var _image: UIImage?
            static private var semaphore = DispatchSemaphore(value: 1)
            static func getImage(closure: @escaping (UIImage?)->()) {
                DispatchQueue.global(qos: .userInteractive).async {
                    semaphore.wait()
                    DispatchQueue.main.async {
                        if let image = _image { closure(image); semaphore.signal(); return }
                        guard let window = UIApplication.shared.windows.first else { semaphore.signal(); return }
                        let searchBar = UISearchBar(frame: CGRect(x: 0, y: -200, width: UIScreen.main.bounds.width, height: 44))
                        window.rootViewController?.view.addSubview(searchBar)
                        searchBar.text = "txt"
                        searchBar.layoutIfNeeded()
                        _image = searchBar.getTextField()?.getClearButton()?.image(for: .normal)
                        closure(_image)
                        searchBar.removeFromSuperview()
                        semaphore.signal()
                    }
                }
            }
        }
    
        func setClearButton(color: UIColor) {
            ClearButtonImage.getImage { [weak self] image in
                guard   let image = image,
                    let button = self?.getClearButton() else { return }
                button.imageView?.tintColor = color
                button.setImage(image.withRenderingMode(.alwaysTemplate), for: .normal)
            }
        }
    
        var placeholderLabel: UILabel? { return value(forKey: "placeholderLabel") as? UILabel }
    
        func setPlaceholder(textColor: UIColor) {
            guard let placeholderLabel = placeholderLabel else { return }
            let label = Label(label: placeholderLabel, textColor: textColor)
            setValue(label, forKey: "placeholderLabel")
        }
    
        func getClearButton() -> UIButton? { return value(forKey: "clearButton") as? UIButton }
    }
    

    Full Sample

    import UIKit
    
    class ViewController: UIViewController {
        override func viewDidLoad() {
            super.viewDidLoad()
    
            let searchBar = UISearchBar(frame: CGRect(x: 0, y: 20, width: UIScreen.main.bounds.width, height: 44))
            searchBar.searchBarStyle = .default
            view.addSubview(searchBar)
    
            searchBar.placeholder = "placeholder"
            searchBar.set(textColor: .brown)
            searchBar.setTextField(color: UIColor.green.withAlphaComponent(0.3))
            searchBar.setPlaceholder(textColor: .white)
            searchBar.setSearchImage(color: .white)
            searchBar.setClearButton(color: .red)
        }
    }
    

    Result

提交回复
热议问题