【问题标题】:UISearchController iOS 11 CustomizationUISearchController iOS 11 自定义
【发布时间】:2017-08-13 17:43:22
【问题描述】:

在 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:

iOS 11:

到目前为止,对这个问题的大部分注意力都集中在搜索栏的文本颜色上。我看到的不止这些 - 背景颜色、色调颜色、搜索指示符、清除按钮颜色等。

【问题讨论】:

  • 问得好,但如果您采用通过导航栏处理搜索字段的概念,运行时会对其进行处理,我不会感到惊讶。您可以通过将自定义延迟到运行时有机会配置搜索栏本身之后来强制执行您的自定义,但这只是一个猜测,如果这也不起作用,我也不会感到惊讶。
  • 您可以使用外观代理实现这种自定义。但是,根据我的经验,它有问题 - 栏一开始看起来和我想要的完全一样,但是当另一个视图控制器隐藏它时,它会失去圆角。
  • 尝试将字体外观应用到搜索字段(白色字体颜色)。
  • 尝试添加searchController.searchBar.tintColor = UIColor.white 应该可以。
  • 你使用的是哪个版本的iOS11?您是否对项目进行了彻底的清理?这可能是操作系统的错误。但是我会尝试复制它并尽快给你反馈......! @NishantBhindi 他已经做到了……

标签: ios swift uisearchcontroller ios11


【解决方案1】:

我刚刚发现了如何设置它们:(在 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])

白色背景:

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
}

取自here

【讨论】:

  • 再一次,这个答案对颜色不太好。它们的导航栏背景颜色总是比您指定的颜色深。
  • 嗨@AlexanderMacLeod,你修好了吗?
  • 应该被告知,就像所有 iOS 开发者一样,使用任何 value:forKey: 都被视为访问私有 api 水域,并且很可能违反 Apple 的 t&c
  • 为什么苹果每次发布都会打破常规
  • 这个答案几乎救了我!谢谢!唯一的问题是,当您在视图控制器之间进行推送时,导航区域的背景中会立即出现黑色动画行。
【解决方案2】:

要将输入到搜索栏中的文本正确设置为白色(使用深色字段颜色时):

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

上面的好像不行。

【讨论】:

    【解决方案3】:

    尝试设置搜索栏的栏样式。

    searchController.searchBar.barStyle = UIBarStyleBlack;
    

    【讨论】:

    • 太棒了!这会将文本颜色从黑色切换为白色。
    【解决方案4】:

    将对setDefaultSearchBar 的调用移至viewDidAppear 应该可以解决此问题。

    【讨论】:

    • 此答案适用于文本颜色等一些属性,但不适用于背景图像。在视图之间推送时也会留下难看的快照变化
    • @AlexanderMacLeod 太糟糕了,但我想你是对的,它不适用于所有道具 :(
    【解决方案5】:

    您需要找到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真的是一个挑战
    【解决方案6】:
        UITextField.appearance(whenContainedInInstancesOf: [UISearchBar.self]).defaultTextAttributes = [NSForegroundColorAttributeName: UIColor.white]
    

    【讨论】:

    • 也许您可以再解释一下您的答案?仅代码的答案通常不是最有用的。
    【解决方案7】:

    试试看: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
        }
    }
    

    【讨论】:

      【解决方案8】:

      如果您需要更改 searchBar 中 textField 的背景颜色,请在此处查看我的答案: https://stackoverflow.com/a/46315974/1109892

      【讨论】:

      • 你的答案在颜色上效果不是特别好——它们看起来总是比你在代码中指定的要暗得多
      • 是的,我知道,但这是我能得到的最好的。如果您找到解决方法,请告诉我。
      【解决方案9】:

      您必须访问 UISearchBar 内的 UITextField。您可以使用

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

      【讨论】:

      • 可能你得到了清晰的色调,这是我可以成像尝试设置“_searchBar.tintColor = [UIColor redColor];”的唯一原因