UISearchController iOS 11定制化

59

在iOS 11之前,我一直使用以下代码自定义UISearchController搜索栏的外观:

var searchController = UISearchController(searchResultsController: nil)
searchController.searchBar.setDefaultSearchBar()
searchController.searchResultsUpdater = self

if #available(iOS 11.0, *) {
    navigationItem.searchController = searchController
} else {
    tableView.tableHeaderView = searchController.searchBar
}

extension UISearchBar {
    func setDefaultSearchBar() {
        self.tintColor = UIColor.blue
        self.searchBarStyle = .minimal
        self.backgroundImage = UIImage(color: UIColor.clear)
        let searchBarTextField = self.value(forKey: "searchField") as! UITextField
        searchBarTextField.textColor = UIColor.white
        searchBarTextField.tintColor = UIColor.blue
        searchBarTextField = .dark
    }
}

然而,在iOS 11上运行相同的代码时,搜索栏的外观未能更新。
iOS 10:

enter image description here

iOS 11:

enter image description here

到目前为止,对于这个问题的大部分关注都集中在搜索栏的文本颜色上。但我需要考虑更多——背景颜色、色调颜色、搜索指示器、清除按钮颜色等等。


问得好,但如果你采用搜索字段由导航栏处理的观念,运行时会对其施加自己的外观,我也不会感到惊讶。你可能可以通过延迟自定义操作来强制实现它们,直到运行时有机会配置搜索栏本身,但这只是一个猜测,如果这也行不通,那我也不会感到惊讶。 - matt
您可以使用外观代理来实现这种定制。然而,根据我的经验,它存在一些错误 - 当另一个视图控制器隐藏它时,该工具栏会失去圆角,尽管一开始看起来完全符合我的要求。 - Andy Ibanez
尝试将字体外观应用于搜索字段(白色字体颜色)。 - LLIAJLbHOu
我正在使用最新的iOS 11测试版 @AndreaVultaggio - Alexander MacLeod
尝试设置navigationItem的文本颜色。 - Wayne
显示剩余4条评论
9个回答

79
我刚刚发现如何设置它们:(在Brandon和Krunal的帮助下,谢谢!)
“取消”文本:
“取消”文本:
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]

在此输入图片描述

占位符:

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

enter image description here

白色背景:

if #available(iOS 11.0, *) {
    let sc = UISearchController(searchResultsController: nil)
    sc.delegate = self
    let scb = sc.searchBar
    scb.tintColor = UIColor.white
    scb.barTintColor = UIColor.white

    if let textfield = scb.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 = sc
    navigationItem.hidesSearchBarWhenScrolling = false
}

enter image description here

引用自这里.


4
这个回答在颜色方面表述不够清晰。导航栏的背景颜色似乎总是比你指定的颜色要暗。 - Alexander MacLeod
1
应该注意,与所有的iOS开发一样,使用任何value:forKey:都被认为是访问私有API,并且很可能违反Apple的条款和条件。 - Will Von Ullrich
40
为什么苹果每次推出新版本都会出现问题? - hhanesand
1
这个回答几乎救了我!谢谢!唯一的问题是,在视图控制器之间推送时,导航区域的后台会立即出现一个黑色动画行。 - Konstantinos
最佳答案!尝试了数十种方法,只有这个有效。 - Alexei Mikhailov
显示剩余8条评论

11

为了将搜索栏中输入的文本设置为白色,请使用以下代码(在使用深色背景时):

searchController.searchBar.barStyle = .black

设置文本框的背景颜色

if #available(iOS 11.0, *) {

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

                // Background color
                backgroundview.backgroundColor = UIColor.white

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

然而,使用类似的东西

textfield.textColor = UIColor.blue

以上方法似乎不起作用。


6

尝试设置搜索栏的样式。

searchController.searchBar.barStyle = UIBarStyleBlack;

image 1


太棒了!这将文本颜色从黑色切换到白色。 - Ashley Mills

5
将调用 setDefaultSearchBar 的代码移动到 viewDidAppear 中应该可以解决这个问题。

2
这个答案适用于一些属性,比如文本颜色,但不适用于背景图片。在视图之间切换时,它还会留下一个丑陋的快照变化。 - Alexander MacLeod
@AlexanderMacLeod 真遗憾,但我想你是对的,它不会适用于所有道具 :( - pronebird

4
你需要找到 UISearchBar 底层的 UITextField 并更改其文本颜色。
请注意,这只有在搜索控制器即将呈现 (UISearchControllerDelegate.willPresentSearchController) 或已呈现时才会生效。
class ViewController : UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // setup your search controller...

        // set search controller's delegate
        navigationItem.searchController?.delegate = self
    }
}

extension ViewController : UISearchControllerDelegate {

    func willPresentSearchController(_ searchController: UISearchController) {
        // update text color
        searchController.searchBar.textField?.textColor = .white
    }
}

extension UISearchBar {

    var textField: UITextField? {
        for subview in subviews.first?.subviews ?? [] {
            if let textField = subview as? UITextField {
                return textField
            }
        }
        return nil
    }
}

谢谢,你救了我的一天。在iOS中自定义UISearchBar确实是一个挑战。 - Marina

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

也许您可以更详细地解释一下您的答案?仅有代码的答案通常不是最有用的。 - Antimony

2
尝试使用以下代码:searchController.<YOUR SEARCHBAR>.barStyle = .blackOpaque 替代 self.searchBarStyle = .minimal
因此:
var searchController = UISearchController(searchResultsController: nil)
searchController.searchBar.setDefaultSearchBar()
//Add this line below
searchController.searchBar.barStyle = .blackOpaque
searchController.searchResultsUpdater = self

if #available(iOS 11.0, *) {
    navigationItem.searchController = searchController
} else {
    tableView.tableHeaderView = searchController.searchBar
}

extension UISearchBar {
    func setDefaultSearchBar() {
        self.tintColor = UIColor.blue
        //Delete this line below
        self.searchBarStyle = .minimal
        self.backgroundImage = UIImage(color: UIColor.clear)
        let searchBarTextField = self.value(forKey: "searchField") as! UITextField
        searchBarTextField.textColor = UIColor.white
        searchBarTextField.tintColor = UIColor.blue
        searchBarTextField = .dark
    }
}

1

你的回答在颜色方面并不特别有效 - 它们似乎总是比你在代码中指定的要暗许多。 - Alexander MacLeod
是的,我知道,但这是我能得到的最好的。如果你找到了解决方法,请告诉我。 - Adam Studenic

0

你必须访问 UISearchBar 内的 UITextField。你可以通过以下方式实现

let textFieldInsideSearchBar = yourSearchbar.value(forKey: "searchField") as? UITextField

textFieldInsideSearchBar?.textColor = yourcolor

或者

enter image description here


你可能已经得到了清晰的色彩,这是我能想象的唯一原因尝试设置"_searchBar.tintColor = [UIColor redColor];" - yogesh wadhwa

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