无法更改搜索栏背景颜色

32

我有一个搜索栏:

let searchBar:UISearchBar = UISearchBar(frame: CGRectMake((searchView.frame.width - UIScreen.mainScreen().bounds.width / 1.6) / 2, 0, UIScreen.mainScreen().bounds.width / 1.6, 24))

我想改变文本输入部分的背景颜色。为此,我尝试过:

searchBar.barTintColor = UIColor(red: 0/255, green: 74/255, blue: 103/255, alpha: 1)

searchBar.backgroundColor = UIColor.redColor()

但是这两个变体都不起作用。我怎样才能更改我的UISearchBar文本输入部分的背景颜色,我做错了什么?


查看演示项目,我在StoryBoard中添加了SearchBar。 - Kirit Modi
我想改变圆形文本框周围的颜色,并尝试了下面所有的解决方案:D,但只有你上面尝试过的barTintColor属性。请确保在代码或故事板中将isTranslucent设置为false - heyfrank
22个回答

22

像 @aliamcami 一样,之前的所有答案都不起作用,要么答案对我没用,要么它能工作但需要太多“虚拟”的代码。因此,我分享了另一个使用简化逻辑编写的Swift 4答案:

for textField in searchController.searchBar.subviews.first!.subviews where textField is UITextField {
    textField.subviews.first?.backgroundColor = .white
    textField.subviews.first?.layer.cornerRadius = 10.5 //I set 10.5 because is approximately the system value
    textField.subviews.first?.layer.masksToBounds = true
    //Continue changing more properties...
}

textField.subviews.first是指“_UISearchBarSearchFieldBackgroundView”子视图,它在UIFieldEditor后面添加了视觉效果。


已编辑

经过一些开发和许多错误,我得出了这个优雅的解决方案(我相信苹果不会乐意批准,但我不确定),它适用于iOS 10 - iOS 12

if let textField = searchBar.value(forKey: "searchField") as? UITextField {
    textField.backgroundColor = myColor
    //textField.font = myFont
    //textField.textColor = myTextColor
    //textField.tintColor = myTintColor
    // And so on...
    
    let backgroundView = textField.subviews.first
    if #available(iOS 11.0, *) { // If `searchController` is in `navigationItem`
        backgroundView?.backgroundColor = UIColor.white.withAlphaComponent(0.3) //Or any transparent color that matches with the `navigationBar color`
        backgroundView?.subviews.forEach({ $0.removeFromSuperview() }) // Fixes an UI bug when searchBar appears or hides when scrolling
    }
    backgroundView?.layer.cornerRadius = 10.5
    backgroundView?.layer.masksToBounds = true
    //Continue changing more properties...
}

searchBartableHeaderView 中时,上述代码可以在 viewWillAppear 中调用,但如果它在 iOS 11 及以上版本的 navigationItem 中,则应在 viewDidAppear 中调用。


@Ángel Téllez 提供的解决方案对我也起作用了!谢谢Angel!不确定它是否也适用于IOS 10,但它适用于11。此外,还有一个小的UI故障,在导航标题和搜索栏控制器之间会出现一个白线(不到一秒钟)。不知道为什么会发生这种情况,但很高兴这个解决方案有效! - sudhama
欢迎,@sudhama。我很高兴至少有人能用它:D。在3个月后的一些修复后,我更新了我的答案。这段代码在iOS 10及以上版本的iPhone 5到XS上都可以正常工作。关于故障,也许你需要在viewWillAppear中更改searchBar的属性?或者你正在尝试使用searchBarshadowImage属性,导致其下方的线条重新加载?希望你能解决它 :) - Ángel Téllez
为了避免搜索栏在navigationItem中时短暂闪现旧颜色,我发现可以将其放在viewDidLayoutSubviews中,在调用super之后,而不是viewDidAppear - Chris Vasselli

16
如果您只想在您的 ViewController 中更改它而不希望影响其他地方,请使用。
for view in searchBar.subviews {
            for subview in view.subviews {
                if subview .isKindOfClass(UITextField) {
                    let textField: UITextField = subview as! UITextField
                    textField.backgroundColor = UIColor.redColor()
                }
            }
        }

但如果你希望全局更改并且针对iOS 9.0或更高版本,则应使用appearanceWhenContainedInInstancesOfClasses

UITextField.appearanceWhenContainedInInstancesOfClasses([UISearchBar.self]).backgroundColor = UIColor.redColor()

3
我不知道为什么,但它仍然没有改变颜色。 - Orkhan Alizade

16

我为UISearchBar做了一个扩展和类别,用于自定义搜索栏中的文本字段。

兼容iOS 9到iOS 13。

Swift 4+

import UIKit

extension UISearchBar {

    // Due to searchTextField property who available iOS 13 only, extend this property for iOS 13 previous version compatibility
    var compatibleSearchTextField: UITextField {
        guard #available(iOS 13.0, *) else { return legacySearchField }
        return self.searchTextField
    }

    private var legacySearchField: UITextField {
        if let textField = self.subviews.first?.subviews.last as? UITextField {
            // Xcode 11 previous environment
            return textField
        } else if let textField = self.value(forKey: "searchField") as? UITextField {
            // Xcode 11 run in iOS 13 previous devices
            return textField
        } else {
            // exception condition or error handler in here
            return UITextField()
        }
    }
}

使用示例:

var searchController: UISearchController?
searchController?.searchBar.compatibleSearchTextField.textColor = UIColor.XXX
searchController?.searchBar.compatibleSearchTextField.backgroundColor = UIColor.XXX

Objective-C

UISearchBar+SearchTextField.h

#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

@interface UISearchBar (SearchTextField)

// Due to searchTextField property who available iOS 13 only, extend this property for iOS 13 previous version compatibility
@property (nonatomic, readonly) UITextField *compatibleSearchTextField;

@end

NS_ASSUME_NONNULL_END

UISearchBar+SearchTextField.m

#import "UISearchBar+SearchTextField.h"

@implementation UISearchBar (SearchTextField)

- (UITextField *)compatibleSearchTextField {
    if (@available(iOS 13.0, *)) {
#ifdef __IPHONE_13_0
        return self.searchTextField;
#else
        // Xcode 11 run in iOS 13 previous devices
        return (UITextField *)[self valueForKey:@"searchField"];
#endif
    } else {
        // Xcode 11 previous environment
        return [[[self.subviews firstObject] subviews] lastObject];
    }
}

@end

使用示例:

- (UISearchBar *)searchBar {
    if (!_searchBar) {
        _searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(X, X, X, X)];
        _searchBar.compatibleSearchTextField.textColor = [UIColor XXX];
        _searchBar.compatibleSearchTextField.backgroundColor = [UIColor XXX];
    }
    return _searchBar
}


13

Swift 5:

    searchController.searchBar.searchTextField.backgroundColor = .white

2
这应该是被采纳的答案。1行代码完美地按预期工作,没有花哨的东西和变通方法。这是本帖中最好的答案。 - Julian Silvestri
3
这段代码在 iOS 12.x 上会崩溃,因此其他答案更为适合。 - C6Silver
2
在iOS 16上使用此功能,无崩溃。 - Jevon718

12

只使用苹果的API实现这个功能的方法是创建一张图片并使用 setSearchFieldBackgroundImage

self.searchBar.setSearchFieldBackgroundImage(UIImage(named: "SearchFieldBackground"), for: UIControlState.normal)

如果你创建了一个圆角矩形并动态地显示和隐藏按钮,它甚至会适当地动画化角落。

以下是使用此图像的示例:输入图像描述

输入图像描述


这与在 searchBar 上设置 backgroundColor 是相同的。只是不必要地复杂,并且不能解决色调问题,因为您无法正确更改文本色调或文本字段背景以匹配背景。 - user187676
2
backgroundColor 对我没有任何改变。 - Yaroslav Dukal
1
这并不是过度复杂,而是使用正确的API。 - Raphael Oliveira
我无法在iOS 12中更改navigationItem的背景颜色,它一直显示为白色。在iOS 13中正常工作。在我的情况下,我想将其设置为粉色。 - Hitarth

11

您正在将下面的代码添加到ViewDidLoad中,并更改文本字段的背景颜色为红色,

for subView in searchBar.subviews
{
    for subView1 in subView.subviews
    {

        if subView1.isKindOfClass(UITextField)
        {
            subView1.backgroundColor = UIColor.redColor()
        }
    }

}

搜索栏中TextField的红色。

enter image description here


我不知道为什么,但我尝试了许多解决方案,但都没有起作用 =/ - Orkhan Alizade
以上示例项目下载并在您的项目中实现与演示相同的功能。 - Kirit Modi
在搜索栏属性中取消“半透明”选项,然后上面的代码就可以正常工作了。 - Saqib Omer

10

对于 Swift 3+,请使用以下代码:

for subView in searchController.searchBar.subviews {

    for subViewOne in subView.subviews {

        if let textField = subViewOne as? UITextField {

           subViewOne.backgroundColor = UIColor.red

           //use the code below if you want to change the color of placeholder
           let textFieldInsideUISearchBarLabel = textField.value(forKey: "placeholderLabel") as? UILabel
                textFieldInsideUISearchBarLabel?.textColor = UIColor.blue
        }
     }
}

9
我用以下方法实现(Swift 3+解决方案):
let textFieldInsideSearchBar = searchBar.value(forKey: "searchField") as? UITextField
textFieldInsideSearchBar?.backgroundColor = UIColor.red

这是唯一在Xcode 11中有效的。谢谢! - Mikiko Jane

9

遇到了同样的问题,对于iOS 13+,可以按照以下方式获取textField

var searchText : UITextField?
if #available(iOS 13.0, *) {
   searchText  = searchBar.searchTextField
}
else {
    searchText = searchBar.value(forKey: "_searchField") as? UITextField
}
searchText?.backgroundColor = .red                                                              

不错的回答。简单明了。 - Umair_UAS

9

Swift 5扩展:

在所有iOS版本上都完美运行。

import UIKit

extension UISearchBar {

    func setupSearchBar(background: UIColor = .white, inputText: UIColor = .black, placeholderText: UIColor = .gray, image: UIColor = .black) {

        self.searchBarStyle = .minimal

        self.barStyle = .default

        // IOS 12 and lower:
        for view in self.subviews {

            for subview in view.subviews {
                if subview is UITextField {
                    if let textField: UITextField = subview as? UITextField {

                        // Background Color
                        textField.backgroundColor = background

                        //   Text Color
                        textField.textColor = inputText

                        //  Placeholder Color
                        textField.attributedPlaceholder = NSAttributedString(string: textField.placeholder ?? "", attributes: [NSAttributedString.Key.foregroundColor : placeholderText])

                        //  Default Image Color
                        if let leftView = textField.leftView as? UIImageView {
                            leftView.image = leftView.image?.withRenderingMode(.alwaysTemplate)
                            leftView.tintColor = image
                        }

                        let backgroundView = textField.subviews.first
                        backgroundView?.backgroundColor = background
                        backgroundView?.layer.cornerRadius = 10.5
                        backgroundView?.layer.masksToBounds = true

                    }
                }
            }

        }

        // IOS 13 only:
        if let textField = self.value(forKey: "searchField") as? UITextField {

            // Background Color
            textField.backgroundColor = background

            //   Text Color
            textField.textColor = inputText

            //  Placeholder Color
            textField.attributedPlaceholder = NSAttributedString(string: textField.placeholder ?? "", attributes: [NSAttributedString.Key.foregroundColor : placeholderText])

            //  Default Image Color
            if let leftView = textField.leftView as? UIImageView {
                leftView.image = leftView.image?.withRenderingMode(.alwaysTemplate)
                leftView.tintColor = image
            }

        }

    }

}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接