iOS 13 Set UISearchTextField placeholder color

后端 未结 5 1691
执笔经年
执笔经年 2020-12-10 02:20

How do you set the placeholder color of iOS 13\'s UISearchTextField?

I tried the following with no success:

searchField.attributedPlaceh         


        
相关标签:
5条回答
  • 2020-12-10 02:26

    You can try this with Xcode 11, iOS 13

     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 = 8
                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 = ""
                        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)
            placeholderLabel.removeFromSuperview() // To remove existing label. Otherwise it will overwrite it if called multiple times.
            setValue(label, forKey: "placeholderLabel")
        }
    
        func getClearButton() -> UIButton? { return value(forKey: "clearButton") as? UIButton }
    
    }
    

    Use:

        searchBarObj.placeholder = "placeholder text"
        searchBarObj.set(textColor: .blue)
        searchBarObj.setTextField(color: UIColor.gray)
        searchBarObj.setPlaceholder(textColor: .red)
        searchBarObj.setSearchImage(color: .black)
        searchBarObj.setClearButton(color: .red)
    
    0 讨论(0)
  • 2020-12-10 02:28

    I found the following code snippet worked:

    DispatchQueue.main.asyncAfter(deadline: .now()+0.5) {
        // Stackoverflow said the above doesn't work on viewDidLoad style methods, so running it async after a 0.5s delay to workaround.  Works.
        searchField.attributedPlaceholder = NSAttributedString(string:"Search", attributes: attributesDictionary)
    }
    
    0 讨论(0)
  • 2020-12-10 02:37

    UiSearch bar is not updating placeholder colur in viewDidLoad and viewWillAppear so write below code in viewDidAppear:

    let textField = searchbar.value(forKey: "searchField") as? UITextField
    let placeholderAttributes = [NSAttributedString.Key.foregroundColor : UIColor.white.withAlphaComponent(0.6)]
    let attributedPlaceholder = NSAttributedString(string: "SearchTextPlaceholer".localized(), attributes: placeholderAttributes)
    textField?.attributedPlaceholder = attributedPlaceholder
    
    0 讨论(0)
  • 2020-12-10 02:46

    iOS 13

    Use a custom search bar.

    This also works when part of a UISearchController inside a UINavigationItem (with hidesSearchBarWhenScrolling = true).

    We want to apply our changes immediately after UIAppearance proxies are being applied since those are the most likely root cause:

    class MySearchBar : UISearchBar {
        // Appearance proxies are applied when a view is added to a view hierarchy, so apply your tweaks after that:
        override func didMoveToSuperview() {
            super.didMoveToSuperview() // important! - system colors will not apply correctly on ios 11-12 without this
    
            let placeholderColor = UIColor.white.withAlphaComponent(0.75)
            let placeholderAttributes = [NSAttributedString.Key.foregroundColor : placeholderColor]
            let attributedPlaceholder = NSAttributedString(string: "My custom placeholder", attributes: placeholderAttributes)
            self.searchTextField.attributedPlaceholder = attributedPlaceholder
            
            // Make the magnifying glass the same color
            (self.searchTextField.leftView as? UIImageView)?.tintColor = placeholderColor
        }
    }
    
    // Override `searchBar` as per the documentation
    private class MySearchController : UISearchController {
        private lazy var customSearchBar = MySearchBar()
        override var searchBar: UISearchBar { customSearchBar }
    }
    

    Copy of my answer from here

    0 讨论(0)
  • 2020-12-10 02:47

    This works for me XCode 11.1 for placeholder color, remove search icon:

      let textFieldInsideSearchBar = searchbar.value(forKey: "searchField") as? UITextField
        textFieldInsideSearchBar!.attributedPlaceholder = NSAttributedString(string: Constant.Text.search_currency.localized, attributes: [NSAttributedString.Key.foregroundColor: UIColor.white])
        textFieldInsideSearchBar?.textColor = UIColor.white
        textFieldInsideSearchBar?.leftViewMode = UITextField.ViewMode.never
        searchbar.setImage(UIImage(), for: .search, state: .normal)
        searchbar.setPositionAdjustment(UIOffset(horizontal: -20, vertical: 0), for: .search)
    
    0 讨论(0)
提交回复
热议问题