【问题标题】:How to change UISearchBar Placeholder and image tint color?如何更改 UISearchBar 占位符和图像色调颜色?
【发布时间】:2015-06-05 05:00:57
【问题描述】:

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

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

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

【问题讨论】:

  • seachControl.searchBar.placeholder = ""

标签: ios iphone xcode swift uikit


【解决方案1】:

详情

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

解决方案

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 }
}

完整样本

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)
    }
}

结果

【讨论】:

  • 当 SearchBar 在 NavigationBar 中但没有成功时,我一直试图让它在 iOS 11 上运行。有什么想法吗?
  • 你好雷纳托。我无法理解你的问题。不能将 SearchBar 添加到 NavigationBar?
  • 非常感谢!
  • 这个解决方案看起来不错,但对于UISearchController,您需要继承UISearchControllerUISearchBar。即使那样,清除按钮着色仍然不起作用。任何想法为什么?
  • 很好的解决方案!一个问题是 ClearButtonColor 在 iOS 12.0 中不起作用。
【解决方案2】:

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

[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}]];
}

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

编辑:我刚刚意识到你正在用swift写它......呃。快速输入,所以我没有在 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

    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)
    }

【讨论】:

  • 这太完美了,非常感谢您。我以前没见过searchBar.valueForKey("searchField") as? UITextField,这太棒了。您是否也知道如何更改清除按钮(小圆 x)?
  • 我想这将与 setImage 的方式相同,但不是使用 UISearchBarIcon.Search,而是使用 .Clear???我实际上并没有尝试过。除此之外,我知道实际单词“取消”受 searchBar.tintColor...
  • 访问私有属性或 API 肯定会导致您的应用被拒绝。
  • 不要使用私有 API
【解决方案3】:

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

【讨论】:

  • self.searcBar.setTextFieldColor(color: .white) 不起作用,为什么?仍然显示浅浅灰色,但其他颜色正在工作,但白色没有任何想法? ....
【解决方案4】:

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

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

【讨论】:

  • appearanceWhenContainedInInstancesOfClasses 仅适用于 ios9+
【解决方案5】:

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

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

UISearchBar+PlaceholderColor.h

#import <UIKit/UIKit.h>

@interface UISearchBar (PlaceholderColor)

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

@end

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

用法

[mySearchBar setPlaceholderColor:[UIColor redColor]];

重要提示:

确保调用 setPlaceholderColor:AFTER 您的 UISearchBar 已添加到视图并创建了其视图层次结构。

如果您以编程方式打开搜索栏,请将其称为 AFTER 您的 becomeFirstResponder 调用,如下所示:

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

否则,如果您使用 UISearchBarDelegate

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

【讨论】:

    【解决方案6】:
    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
            }
        }
    }
    

    【讨论】:

    • 不错的解决方案!图标工作正常,但占位符文本对我来说并没有改变。
    【解决方案7】:

    我做了一个 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])
                        }
                    }
                }
            }
        }
    }
    

    您可以将其用于您的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))
    

    【讨论】:

      【解决方案8】:

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

      首先,继承 UISearchBar 类。

      class CustomSearchBar: UISearchBar {
      

      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)
      }
      

      你去吧,享受这个。

      【讨论】:

      【解决方案9】:

      对 Vasily Bodnarchuk 出色答案的小幅更新。

      斯威夫特 4+

      NSForegroundColorAttributeName 已更改为NSAttributedStringKey.foregroundColor

      【讨论】:

        【解决方案10】:

        对于任何试图更改文本但无法看到更新的占位符的人,将其放在此处而不是 viewDidLoad 对我有用。

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

        【讨论】:

          【解决方案11】:

          刚刚找到这个帖子,对不起,考虑到年龄的问题。然而,它帮助我尝试解决我的问题,并添加到@m_katsifarakis 的答案中,我在他现有的类别中添加了更多内容。

          为占位符和输入文本添加额外的颜色和字体支持。

          仅在 iOS 13 上进行了测试,因为这就是我所支持的全部。

          @interface UISearchBar (ColorandFont)
          - (void)setPlaceholderColor:(UIColor *)placeholderColor setPlaceholderFont:(UIFont *)placeholderFont;
          - (void)setTextColor:(UIColor *)textColor setTextFont:(UIFont *)textFont;
          @end
          @implementation UISearchBar (ColorandFont)
          
          //Placeholder Color
          - (void)setPlaceholderColor:(UIColor *)placeholderColor setPlaceholderFont:(UIFont *)placeholderFont{
              UILabel *labelView = [self placeholderText:self];
              [labelView setTextColor:placeholderColor];
              [labelView setFont:placeholderFont];
          }
          - (UILabel *)placeholderText:(UIView *)view {
              for (UIView *v in [view subviews]) {
                  if ([v isKindOfClass:[UILabel class]]) {
                      return (UILabel *)v;
                  }
          
                  UIView *labelView = [self placeholderText:v];
                  if (labelView) {
                      return (UILabel *)labelView;
                  }
              }
              return nil;
          }
          
          //Text Color
          - (void)setTextColor:(UIColor *)textColor setTextFont:(UIFont *)textFont{
              UITextField *textView = [self searchBarText:self];
              [textView setTextColor:textColor];
              [textView setFont:textFont];
          }
          - (UITextField *)searchBarText:(UIView *)view {
              for (UIView *v in [view subviews]) {
                  if ([v isKindOfClass:[UITextField class]]) {
                      return (UITextField *)v;
                  }
          
                  UIView *textView = [self searchBarText:v];
                  if (textView) {
                      return (UITextField *)textView;
                  }
              }
              return nil;
          }
          @end
          

          使用(我在 viewDidLoad 和 Appear 中使用)给定我当前的设置,结果可能会有所不同:

          [self.searchBar setPlaceholderColor:[UIColor lightTextColor] setPlaceholderFont:[UIFont italicSystemFontOfSize:13]];
          [self.searchBar setTextColor:[UIColor whiteColor] setTextFont:[UIFont systemFontOfSize:16]];
          

          【讨论】:

            【解决方案12】:

            在 Swift 4 中,假设您的搜索控制器设置如下:

            let searchController = UISearchController(searchResultsController: nil)
            

            然后设置占位符文本如下:

            searchController.searchBar.placeholder = "Here is my custom text"
            

            【讨论】:

            • 问题是如何改变颜色,而不是如何设置文字
            猜你喜欢
            • 2012-08-03
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2019-10-09
            • 2012-04-01
            • 2016-08-03
            • 2012-04-12
            • 1970-01-01
            相关资源
            最近更新 更多