ios 如何更改 UISearchBar 占位符和图像色调颜色?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/29375696/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 05:26:43  来源:igfitidea点击:

How to change UISearchBar Placeholder and image tint color?

iosiphonexcodeswiftuikit

提问by Kyle Bashour

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 magnifying glass of a UISearchBar. I'm only targeting iOS 8.0+ if that matters. Here's my code and what it looks like now:

我已经尝试了几个小时的搜索结果,但我无法弄清楚。也许这是不可能的。我正在尝试更改 UISearchBar 的占位符文本和放大镜的色调。如果这很重要,我只针对 iOS 8.0+。这是我的代码以及它现在的样子:

let searchBar = UISearchBar()
searchBar.placeholder = "Search"
searchBar.searchBarStyle = UISearchBarStyle.Minimal
searchBar.tintColor = UIColor.whiteColor()

a busy cat

一只忙碌的猫

I'd like for the search and magnifying glass to be white, or perhaps a dark green.

我希望搜索和放大镜是白色的,或者是深绿色的。

回答by Vasily Bodnarchuk

Details

细节

  • Xcode Version 11.0 (11A420a), iOS 13, swift 5
  • Xcode 版本 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

结果

enter image description hereenter image description here

enter image description hereenter image description here

回答by c_rath

If you have a custom image you could use, you can set the image and change the placeholder text color using something similar to the following:

如果您有可以使用的自定义图像,则可以使用类似于以下内容的内容设置图像并更改占位符文本颜色:

[searchBar setImage:[UIImage imageNamed:@"SearchWhite"] forSearchBarIcon:UISearchBarIconSearch state:UIControlStateNormal];

UITextField *searchTextField = [searchBar valueForKey:@"_searchField"];    
if ([searchTextField respondsToSelector:@selector(setAttributedPlaceholder:)]) {
    UIColor *color = [UIColor purpleColor];
    [searchTextField setAttributedPlaceholder:[[NSAttributedString alloc] initWithString:@"Search" attributes:@{NSForegroundColorAttributeName: color}]];
}

In that example I used purpleColor, instead you can use the + (UIColor *)colorWithRed:(CGFloat)red green:(CGFloat)green blue:(CGFloat)blue alpha:(CGFloat)alphamethod to create your custom dark green color.

在该示例中,我使用了 PurpleColor,而您可以使用该+ (UIColor *)colorWithRed:(CGFloat)red green:(CGFloat)green blue:(CGFloat)blue alpha:(CGFloat)alpha方法来创建您的自定义深绿色。

EDIT: I just realized you were writing it in swift... duh. Quickly typed this out so I didn't leave the answer in just Obj-C.

编辑:我刚刚意识到你写得很快......呃。快速输入这个,所以我没有只在 Obj-C 中留下答案。

    searchBar.setImage(UIImage(named: "SearchWhite"), forSearchBarIcon: UISearchBarIcon.Search, state: UIControlState.Normal);

    var searchTextField: UITextField? = searchBar.valueForKey("searchField") as? UITextField
    if searchTextField!.respondsToSelector(Selector("attributedPlaceholder")) {
        var color = UIColor.purpleColor()
        let attributeDict = [NSForegroundColorAttributeName: UIColor.purpleColor()]
        searchTextField!.attributedPlaceholder = NSAttributedString(string: "search", attributes: attributeDict)
    }

Swift 3.0

斯威夫特 3.0

    var searchTextField: UITextField? = searchBar.value(forKey: "searchField") as? UITextField
    if searchTextField!.responds(to: #selector(getter: UITextField.attributedPlaceholder)) {
        let attributeDict = [NSForegroundColorAttributeName: UIColor.white]
        searchTextField!.attributedPlaceholder = NSAttributedString(string: "Search", attributes: attributeDict)
    }

回答by phitsch

Swift 3: If you want to change the placeholder, clearbutton and magnifier glass

Swift 3:如果您想更改占位符、清除按钮和放大镜玻璃

    let textFieldInsideSearchBar = searchBar.value(forKey: "searchField") as? UITextField
    textFieldInsideSearchBar?.textColor = UIColor.white

    let textFieldInsideSearchBarLabel = textFieldInsideSearchBar!.value(forKey: "placeholderLabel") as? UILabel
    textFieldInsideSearchBarLabel?.textColor = UIColor.white

    let clearButton = textFieldInsideSearchBar?.value(forKey: "clearButton") as! UIButton
    clearButton.setImage(clearButton.imageView?.image?.withRenderingMode(.alwaysTemplate), for: .normal)
    clearButton.tintColor = UIColor.white

    let glassIconView = textFieldInsideSearchBar?.leftView as? UIImageView

    glassIconView?.image = glassIconView?.image?.withRenderingMode(.alwaysTemplate)
    glassIconView?.tintColor = UIColor.white

回答by netshark1000

You can change the color of the text without violating the private api rule:

您可以在不违反私有 api 规则的情况下更改文本的颜色:

UILabel.appearanceWhenContainedInInstancesOfClasses([UITextField.self]).textColor = UIColor.whiteColor()

回答by m_katsifarakis

I could not make it work properly with any of the above solutions.

我无法使用上述任何解决方案使其正常工作。

I created the following UISearchBar category which works properly on iOS 8.4and 10.3:

我创建了以下 UISearchBar 类别,它在iOS 8.410.3上正常工作:

UISearchBar+PlaceholderColor.h

UISearchBar+PlaceholderColor.h

#import <UIKit/UIKit.h>

@interface UISearchBar (PlaceholderColor)

- (void)setPlaceholderColor:(UIColor *)placeholderColor;

@end

UISearchBar+PlaceholderColor.m

UISearchBar+PlaceholderColor.m

#import "UISearchBar+PlaceholderColor.h"

@implementation UISearchBar (PlaceholderColor)

- (void)setPlaceholderColor:(UIColor *)placeholderColor {
    UILabel *labelView = [self searchBarTextFieldLabelFromView:self];
    [labelView setTextColor:placeholderColor];
}

- (UILabel *)searchBarTextFieldLabelFromView:(UIView *)view {
    for (UIView *v in [view subviews]) {
        if ([v isKindOfClass:[UILabel class]]) {
            return (UILabel *)v;
        }

        UIView *labelView = [self searchBarTextFieldLabelFromView:v];
        if (labelView) {
            return (UILabel *)labelView;
        }
    }

    return nil;
}

@end

USAGE:

用法

[mySearchBar setPlaceholderColor:[UIColor redColor]];

IMPORTANT NOTE:

重要的提示:

Make sure that you call setPlaceholderColor: AFTERyour UISearchBar has been added to the view and has created its view hierarchy.

确保在将 UISearchBar 添加到视图并创建其视图层次结构之后调用 setPlaceholderColor: 。

If you open your search bar programmatically, call it AFTERyour becomeFirstResponder call, as such:

如果您以编程方式打开搜索栏,请在 becomeFirstResponder 调用之后调用它,如下所示:

[mySearchBar becomeFirstResponder];
[searchBar setPlaceholderColor:[UIColor redColor]];

Otherwise, if you are leveraging UISearchBarDelegate:

否则,如果您正在利用UISearchBarDelegate

- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar {
    [searchBar setPlaceholderColor:[UIColor redColor]];
}

回答by Abhimanyu Rathore

I made a Swift 4.1 search bar extension:

我做了一个 Swift 4.1 搜索栏扩展:

import Foundation
import UIKit
extension UISearchBar{
    func setTextField(placeHolderColor:UIColor = .gray,placeHolder:String = "Search Something",textColor:UIColor = .white,backgroundColor:UIColor = .black,
                      placeHolderFont:UIFont = UIFont.systemFont(ofSize: 12.0),
                      textFont:UIFont =  UIFont.systemFont(ofSize: 12.0) ){
        for item in self.subviews{
            for mainView in (item as UIView).subviews{
                mainView.backgroundColor = backgroundColor
                if mainView is UITextField{
                    let textField = mainView as? UITextField
                    if let _textF = textField{
                        _textF.text = "success"
                        _textF.textColor = textColor
                        _textF.font      = textFont
                        _textF.attributedPlaceholder = NSMutableAttributedString.init(string: placeHolder, attributes: [NSAttributedStringKey.foregroundColor : placeHolderColor,
                                                                                                                               NSAttributedStringKey.font : placeHolderFont])
                    }
                }
            }
        }
    }
}

You can use this for your searchBarlike this :

您可以searchBar像这样使用它:

controller.searchBar.setTextField(placeHolderColor: .white,
 placeHolder: "Search A Pet",
 textColor: .white,
 backgroundColor: .green,
 placeHolderFont: UIFont.systemFont(ofSize: 14.0),
 textFont: UIFont.systemFont(ofSize: 14.0))

回答by Geva

extension UISearchBar {
    var textField: UITextField? { return value(forKey: "searchField") as? UITextField }
    var placeholderLabel: UILabel? { return textField?.value(forKey: "placeholderLabel") as? UILabel }
    var icon: UIImageView? { return textField?.leftView as? UIImageView }
    var iconColor: UIColor? {
        get {
            return icon?.tintColor
        }
        set {
            icon?.image = icon?.image?.withRenderingMode(.alwaysTemplate)
            icon?.tintColor = newValue
        }
    }
}

回答by Mike Carpenter

Small update to Vasily Bodnarchuk's great answer.

Vasily Bodnarchuk 的精彩答案的小更新。

Swift 4+

斯威夫特 4+

NSForegroundColorAttributeNamehas been changed to NSAttributedStringKey.foregroundColor

NSForegroundColorAttributeName已更改为 NSAttributedStringKey.foregroundColor

回答by Jerome

I found a way to change the textfiled in search bar. It works in swift 3 and Xcode8.

我找到了一种更改搜索栏中文本文件的方法。它适用于 swift 3 和 Xcode8。

Firstly, subclass the UISearchBar class.

首先,继承 UISearchBar 类。

class CustomSearchBar: UISearchBar {

UISearchBar include a view which has the important textfield you wanted. Following function get the index in subviews.

UISearchBar 包含一个视图,其中包含您想要的重要文本字段。以下函数获取子视图中的索引。

func indexOfSearchFieldInSubviews() -> Int! {
    var index: Int!
    let searchBarView = subviews[0]
    for (i, subview) in searchBarView.subviews.enumerated() {
        if subview.isKind(of: UITextField.self) {
            index = i
            break
        }
    }
    return index
}


override func draw(_ rect: CGRect) {
    // Find the index of the search field in the search bar subviews.
    if let index = indexOfSearchFieldInSubviews() {
        // Access the search field
        let searchField: UITextField = subviews[0].subviews[index] as! UITextField
        // Set its frame.
        searchField.frame = CGRect(x: 5, y: 5, width: frame.size.width - 10, height: frame.size.height - 10)
        // Set the font and text color of the search field.
        searchField.font = preferredFont
        searchField.textColor = preferredTextColor

        // Set the placeholder and its color
        let attributesDictionary = [NSForegroundColorAttributeName: preferredPlaceholderColor.cgColor]
        searchField.attributedPlaceholder = NSAttributedString(string: preferredPlaceholder, attributes: attributesDictionary)

        // Set the background color of the search field.
        searchField.backgroundColor = barTintColor
    }

    super.draw(rect)
}

There you go, enjoy for this.

你去吧,享受这个。

回答by skensell

For anybody just trying to change the text and having trouble seeing the updated placeholder, it worked for me by putting it here instead of viewDidLoad.

对于任何试图更改文本并且无法看到更新的占位符的人来说,将它放在这里而不是viewDidLoad.

- (void)viewDidLayoutSubviews {
    [super viewDidLayoutSubviews];
    self.searchBar.placeholder = @"My Custom Text";
}