iOS 11如何在导航栏中自定义搜索栏

52

当iOS 11搜索栏嵌入到导航栏中时,我想改变文本和图标的颜色,包括占位文本、搜索文本和搜索图标。

输入图片描述

if #available(iOS 11.0, *) {
    navigationController?.navigationBar.prefersLargeTitles = false
    let searchController = UISearchController(searchResultsController: nil)
    navigationItem.searchController = searchController
    navigationItem.hidesSearchBarWhenScrolling = false

    searchController.searchBar.placeholder = "Suchen"
    searchController.searchBar.tintColor = .white
}

如图所示,文本是灰色的,背景是深蓝色的,看起来很丑。我希望文本和图标至少是白色的。(改变蓝色背景颜色也不太好用,请参见我的其他问题

唯一有效的方法是更改闪烁光标和“取消”按钮的颜色,这可以使用.tintColor属性完成。

在iOS 10及以下版本中似乎有效的解决方案在iOS 11中不再起作用,因此请仅发布您知道在iOS 11中有效的解决方案。谢谢。

也许我没有理解iOS 11中的“自动样式”。感谢任何帮助。


你尝试过 UITextField.appearance(whenContainedInInstancesOf: [UISearchBar.self]).tintColor = .white 吗? - MwcsMac
3
好的,不起作用。 - Darko
8个回答

122

我刚刚发现了如何设置剩余部分:(在Brandon的帮助下,谢谢!)

“取消”文本:

searchController.searchBar.tintColor = .white

搜索图标:

searchController.searchBar.setImage(UIImage(named: "my_search_icon"), for: UISearchBarIcon.search, state: .normal)

清除图标:

searchController.searchBar.setImage(UIImage(named: "my_search_icon"), for: UISearchBarIcon.clear, state: .normal)

搜索文本:

UITextField.appearance(whenContainedInInstancesOf: [UISearchBar.self]).defaultTextAttributes = [NSAttributedStringKey.foregroundColor.rawValue: UIColor.white]

感谢 @Brandon 的帮助!

输入图像描述

占位符:

UITextField.appearance(whenContainedInInstancesOf: [UISearchBar.self]).attributedPlaceholder = NSAttributedString(string: "placeholder", attributes: [NSAttributedStringKey.foregroundColor: UIColor.white])

这里输入图片描述

白色背景:

let searchController = UISearchController(searchResultsController: nil)
searchController.delegate = self

let searchBar = searchController.searchBar
searchBar.tintColor = UIColor.white
searchBar.barTintColor = UIColor.white

if let textfield = searchBar.value(forKey: "searchField") as? UITextField {
    textfield.textColor = UIColor.blue
    if let backgroundview = textfield.subviews.first {

        // Background color
        backgroundview.backgroundColor = UIColor.white

        // Rounded corner
        backgroundview.layer.cornerRadius = 10;
        backgroundview.clipsToBounds = true;
    }
}

if let navigationbar = self.navigationController?.navigationBar {
    navigationbar.barTintColor = UIColor.blue
}

navigationItem.searchController = searchController
navigationItem.hidesSearchBarWhenScrolling = false

这里输入图片描述

来源:这里


7
很棒的东西,非常有帮助。但是,我遇到了一个问题,即文本框的背景颜色,白色背景。如果取样它,它实际上不是白色,而是rgb(.95,.95,.95)。事实证明,textField.subviews.first 视图有自己的子视图,它们应用了透明度着色。我尝试了除交换方法外的所有方法来消除这些着色器,但没有成功。如果有人找到了解决方法,请告诉我。 - beebcon
1
关于 ^^ 我终于找到了解决方法。在搜索栏 didMoveToSuperview 之后,如果你遍历 textField.subviews.first.subviews 并执行 subview.removeFromSuperview(),似乎可以消除着色器,并获得纯白背景 rgb(1,1,1)。 - beebcon
1
所以我有一个自定义颜色(是灰色的一种色调),但它一直显示为黑色。我本来要使用上面的解决方案,但它完全删除了我的自定义颜色(尽管如果我将背景设置为白色,它就不会这样...这毫无意义)。因此,我开始设置底部边框(像材料设计搜索栏),因为我的搜索栏与导航栏混合在一起,突然间,BOOM,我的正确的自定义灰色出现了。发现如果我设置 tf.borderStyle = .none,它就神奇地工作了。哇。 - Michael McKenna
1
要更改背景颜色,无需访问子视图,只需执行以下操作即可:if let textfield = scb.value(forKey: "searchField") as? UITextField { textfield.backgroundColor = UIColor.blue } - rs7
1
@BrunoMuniz 不,这不是私有API。但它涉及到导航栏内部工作的知识。这意味着 - 它在未来的iOS版本中可能会停止工作。因此,您需要在iOS更新上进行测试。 - Darko
显示剩余4条评论

3
将以下代码放入`AppDelegate`中:
``` UITextField.appearance(whenContainedInInstancesOf: [UISearchBar.self]).defaultTextAttributes = [NSForegroundColorAttributeName: UIColor.white] UISearchBar.appearance().tintColor = UIColor.white ```
或者将它们都放在`[UIViewController viewDidLoad:]`中。

这确实改变了搜索文本的颜色,很棒!但占位符文本颜色和图标仍然缺失。 - Darko
1
Objective-C 语法: [UISearchBar appearance].tintColor = [UIColor whiteColor]; [[UITextField appearanceWhenContainedInInstancesOfClasses:@[[UISearchBar class]]] setDefaultTextAttributes:@{NSForegroundColorAttributeName: [UIColor whiteColor]}]; - Wayne

3
除了Darko的答案之外, 在我的情况下,我需要获得纯白色搜索文本框颜色。 此外,我需要自定义borderLine和cornerRadius。 因此,如果我只将背景颜色设置为白色,设置自定义圆角半径和自定义边框线,我会得到这样的东西。 当您点击文本字段时,请查看这个丑陋的灰色高亮显示 问题在于搜索栏具有一些子视图,而我刚刚删除了它们。 以下是我的代码:
@interface YourViewController () <UISearchBarDelegate, UISearchControllerDelegate>
// your properties
@property (nonatomic,strong) UISearchController *searchController;
@property (nonatomic,strong) UISearchBar *searchBar;
@end

- (void)viewDidLoad {
[super viewDidLoad];

_searchController = [[UISearchController alloc] initWithSearchResultsController:self.resultsTableController];
_searchController.delegate = self;
_searchController.searchBar.delegate = self;
_searchBar = self.searchController.searchBar;

if (@available(iOS 11.0, *)) {

    UITextField *searchTextField = [_searchBar valueForKey:@"searchField"];
if (searchTextField != nil) {
        searchTextField.layer.cornerRadius = 4.f;
        searchTextField.layer.borderWidth = 1.f;
        searchTextField.clipsToBounds = YES;

        for (UIView *subView in searchTextField.subviews) {
            [subView removeFromSuperview];
        }
}

// Color for "Cancel" button
    _searchBar.tintColor = [UIColor blackColor];
// Add searchController to navgationBar
    _navigationItem.searchController = _searchController;
// Hide searchBar when scroll
    _navigationItem.hidesSearchBarWhenScrolling = YES;
}
}

现在我有一个搜索栏,它具有纯白色背景、自定义的圆角和边框宽度。当点击时,我已经禁用了灰色的高亮显示。 编辑搜索框 取消第一响应者

你是如何在点击时禁用灰色高亮显示的? - Andrew Morris
1
@AndrewMorris 请查看上面的代码。有一个循环,在其中我删除了'searchTextField.subviews'的子视图。 - Alex Kolovatov

2

设置搜索文本颜色

(UITextField.appearance(whenContainedInInstancesOf: [UISearchBar.self]) ).defaultTextAttributes = [NSForegroundColorAttributeName: UIColor.white]

设置搜索框占位符颜色

(UITextField.appearance(whenContainedInInstancesOf: [UISearchBar.self]) ).attributedPlaceholder = [NSForegroundColorAttributeName: UIColor.white]

这个很适合搜索文本颜色。为什么更改背景的解决方案对我无效? - jlstr

1

我对Swift 4.x的建议,简单整理如下。

在控制器或应用程序委托中添加:

appearance.backgroundColor = .green
let myFont = UIFont.italicSystemFont(ofSize: 12)
let attribs = [
    NSAttributedString.Key(rawValue: NSAttributedString.Key.font.rawValue): myFont,
    NSAttributedString.Key(rawValue: NSAttributedString.Key.foregroundColor.rawValue): UIColor.red
]

appearance.defaultTextAttributes =  attribs

在控制器中:
self.searchBar.barTintColor = .blue

你将会得到蓝色背景、绿色搜索栏背景和红色斜体字体。

enter image description here


你忘了提到appearance是如何声明的。 - gklka
正确!//搜索栏: let appearance = UITextField.appearance(whenContainedInInstancesOf: [UISearchBar.self]) - ingconti

0
如果有人卡在 Darkos solution 为什么不起作用的问题上,请尝试将 UINavigationBar 的样式更改为 default 而不是 black。我花了半天时间才弄清楚 ¯\_(ツ)_/¯。

0

我尝试了Daroko的解决方案,但是当我将背景更改为纯白色时出现了问题(它是灰色的)。 我的解决方案是使用setSearchFieldBackgroundImage。此外,我不想依赖于苹果结构来获取UITextField。

  if #available(iOS 11.0, *) {
     let whiteImage = UIImage(color: UIColor.white, size: CGSize(width: searchController.searchBar.layer.frame.width, height: searchController.searchBar.layer.frame.height))
     searchController.searchBar.setSearchFieldBackgroundImage(whiteImage, for: .normal)
     self.navigationItem.searchController = searchController
     self.navigationItem.hidesSearchBarWhenScrolling = true
 }


public extension UIImage {
  public convenience init?(color: UIColor, size: CGSize = CGSize(width: 1, height: 1)) {
    let rect = CGRect(origin: .zero, size: size)
     UIGraphicsBeginImageContextWithOptions(rect.size, false, 0.0)
     color.setFill()
     UIRectFill(rect)
     let image = UIGraphicsGetImageFromCurrentImageContext()
     UIGraphicsEndImageContext()
     guard let cgImage = image?.cgImage else { return nil }
     self.init(cgImage: cgImage)
} }

我使用了UIImage扩展自: 在Swift中创建纯色UIImage


-4

这段代码可以改变文本框的背景颜色

Swift 4

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {

        //background color of text field
         UITextField.appearance(whenContainedInInstancesOf: [UISearchBar.self]).backgroundColor = .cyan

        }

编辑:一个青色的UISearchBar示例

sample


4
不能工作。或者我可能漏掉了什么东西? - jlstr
4
不适用于 UISearchController,也许适用于 UISearchBar。 - HJo
我再次尝试,这行代码仍然对我有效,我在回复中编辑了一张截图。这是iOS 11。 - Maruta

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