Как изменить серый фон по умолчанию в текстовом поле поиска UISearchController?

@wings что происходит, когда Apple решает изменить иерархию представлений?
Пожалуйста, посмотрите этот ответ: stackoverflow.com/questions/52870677/…
@RakeshaShastri ... Я не понимаю: D
@SagarChauhan, что происходит, когда Apple решает сменить ключ?
@RakeshaShastri, он не изменит ключ сейчас, и если есть какие-либо изменения, это не повлияет на живое приложение. В новой версии вы можете изменить этот ключ в соответствии с решением Apple.
@SagarChauhan, да, но они не скажут вам новый ключ. То, что вы знаете это сейчас, не означает, что вы узнаете новый. Кроме того, если Apple меняет ключ, это будет влияет на живое приложение. Вы не можете кодировать ОС, которая еще не была выпущена.
@RakeshaShastri, Ооо, Предположим, старое приложение имеет функцию flatMap, и теперь оно работает. Итак, Apple обновила название функции как compactMap, поэтому она работает в реальном приложении. Правильно ?
@SagarChauhan Wat ?! нет, это не так. почему это повлияет на живые приложения ?! Либо вы неправильно объясняете свою точку зрения (что может случиться, ничего страшного), либо вы сильно ошибаетесь в том, как все это работает (что было бы довольно большим делом) ...
поделиться исходным кодом SearchController





Вы пробовали что-то вроде
searchController.searchBar.backgroundColor = UIColor.blue
Хорошо! Может быть, вы можете попробовать с subviews внутри searchBar, и если вы найдете subview, который является UITextField, измените его backgroundColor
Вот пример того, как установить фон textField.
class ViewController: UIViewController {
let searchController = UISearchController(searchResultsController: nil)
private lazy var searchTextField: UITextField? = { [unowned self] in
var textField: UITextField?
self.searchController.searchBar.subviews.forEach({ view in
view.subviews.forEach({ view in
if let view = view as? UITextField {
textField = view
}
})
})
return textField
}()
override func viewDidLoad() {
super.viewDidLoad()
searchController.obscuresBackgroundDuringPresentation = false
searchController.searchBar.placeholder = "Search Candies"
navigationItem.searchController = searchController
definesPresentationContext = true
if let bg = self.searchTextField?.subviews.first {
bg.backgroundColor = .green
bg.layer.cornerRadius = 10
bg.clipsToBounds = true
}
}
}
Результат
Не лучший способ найти UITextField. Сделайте это хотя бы рекурсивным. :(
Чтобы обновить фон UISearchController, нужно изменить фоновое изображение.
Если вы видите UISearchController в визуальном отладчике, вы можете узнать, что его фоном является UIImageView:
Итак, вы должны сделать маленькое изображение своей панели поиска и установить его на seachBar следующим образом:
lazy var searchController: UISearchController = {
let searchController = UISearchController(searchResultsController: nil)
searchController.searchBar.placeholder = "Search"
searchController.searchBar.tintColor = UIColor.black
searchController.searchBar.searchBarStyle = .minimal
// Set background image to searchBar so it will resize
searchController.searchBar.setSearchFieldBackgroundImage(UIImage(named: "oval_static"), for: .normal)
definesPresentationContext = true
return searchController
}()
Изображение searchBar (в проекте я рекомендую использовать формат изображения .pdf или .png, здесь только скриншот):
UISearchBar изменит его размер по мере необходимости, и результат будет:
Более того, мы можем сделать что-то вроде этого, чтобы создать собственный фон только в коде:
/// Just random extension to make image from UIView, you can use your own
extension UIView {
func asImage() -> UIImage {
let renderer = UIGraphicsImageRenderer(bounds: bounds)
return renderer.image { rendererContext in
layer.render(in: rendererContext.cgContext)
}
}}
lazy var searchController: UISearchController = {
let searchController = UISearchController(searchResultsController: nil)
searchController.searchBar.placeholder = "Search"
searchController.searchBar.tintColor = UIColor.black
searchController.searchBar.searchBarStyle = .minimal
// Create own view with custom properties
// Default height is 36 points
let differentColorSearchBar = UIView(frame: CGRect(x: 0, y: 0, width: 10, height: 36))
differentColorSearchBar.layer.cornerRadius = 8
differentColorSearchBar.clipsToBounds = true
differentColorSearchBar.backgroundColor = UIColor.blue
searchController.searchBar.setSearchFieldBackgroundImage(differentColorSearchBar.asImage(), for: .normal)
definesPresentationContext = true
return searchController
}
Результат (конечно, вы можете изменить другие свойства searchBar, чтобы сделать его лучше, но я просто покажу вам, как правильно изменить фон):
Я рекомендую избегать частных свойств, просто используйте open! Надеюсь, это поможет.
Я делаю это так, код Objective-C:
UITextField *searchField = [_navigationSearchBar valueForKey:@"searchField"];
searchField.backgroundColor = [UIColor defaultSeacrhBarColor];
searchField.textColor = [UIColor defaultWhiteColor];
searchField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:searchTitle];
UILabel *placeholderLabel = [searchField valueForKey:@"placeholderLabel"];
placeholderLabel.textColor = [UIColor lightTextColor];
UIButton *clearButton = [searchField valueForKey:@"clearButton"];
[clearButton setImage:[clearButton.imageView.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] forState:UIControlStateNormal];
clearButton.tintColor = [UIColor defaultWhiteColor];
_navigationSearchBar.delegate = self;
[_navigationSearchBar setTranslucent:NO];
[_navigationSearchBar setBackgroundImage:nil];
[_navigationSearchBar setBarTintColor:[UIColor defaultNavigationBarColor]];
[_navigationSearchBar setBackgroundColor:[UIColor defaultNavigationBarColor]];
[_navigationSearchBar setImage:[UIImage imageNamed:@"Search_Icon"] forSearchBarIcon:UISearchBarIconSearch state:UIControlStateNormal];
_navigationSearchBar.clipsToBounds = YES;
[_navigationBar addSubview:_navigationSearchBar];
У Apple есть ключ searchField для обнаружения текстового поля в searchBar. Итак, сначала безопасно получите это текстовое поле и сделайте все, что хотите, с помощью текстового поля.
let searchController = UISearchController(searchResultsController: nil)
searchController.searchResultsUpdater = self
searchController.searchBar.placeholder = "Search here..."
searchController.searchBar.delegate = self
searchController.searchBar.tintColor = .white
searchController.searchBar.barTintColor = .white
searchController.hidesNavigationBarDuringPresentation = false
searchController.obscuresBackgroundDuringPresentation = false
if let textfield = searchController.searchBar.value(forKey: "searchField") as? UITextField {
// Set text colour of text field
textfield.textColor = UIColor.blue
if let backgroundview = textfield.subviews.first {
// Get background view and change background color
backgroundview.backgroundColor = UIColor.white
// Set rounded corner
backgroundview.layer.cornerRadius = 10
backgroundview.clipsToBounds = true
}
}
if #available(iOS 11.0, *) {
self.navigationItem.searchController = searchController
} else {
self.tblCustomers.tableHeaderView = searchController.searchBar
}
Это рабочий код, который я реализовал в своем текущем проекте. Тем не менее, если у вас есть какие-либо вопросы, дайте мне знать.
Я надеюсь, что это поможет вам.
Когда вы пишете .value(forKey: "searchField"), вы звоните в Apple, чтобы отклонить ваше приложение в любое время, когда они это заметят. Кроме того, ваше приложение выйдет из строя, если они просто переименуют атрибут searchField в любой новой версии.
@Kamran, Во-первых, у меня есть безопасное получение textField путем необязательного развертывания if let, так что это не приведет к сбою приложения. Во-вторых, если приложение работает, то как оно вылетит. Кроме того, одно из моих приложений уже работает, где доступен этот код.
Да, дополнительная распаковка будет работать, если .value(forKey: "searchField") не выйдет из строя. Если внутри этого метода произошел сбой, дополнительная распаковка не спасет. Если приложение работает и они переименовали атрибут в новой операционной системе, оно начнет вылетать, так как этот ключ будет недоступен. Наконец, ваше приложение и многие другие приложения работают, потому что Apple не заметила, что вы обращаетесь к API private. Заметив это, они могут отклонить приложение.
Макс используйте эту функцию ниже для изменения цвета.
extension UISearchBar {
func setBackgroundColor(){
if let view:UIView = self.subviews.first {
for curr in view.subviews {
guard let searchBarBackgroundClass = NSClassFromString("UISearchBarBackground") else {
return
}
if curr.isKind(of:searchBarBackgroundClass){
if let imageView = curr as? UIImageView{
imageView.backgroundColor = .red
break
}
}
}
}
}
}
Используйте эту функцию с панель поиска.
searchBarController.searchBar.setBackgroundColor()
Нет никакого надлежащего / общедоступного способа изменить цвет фона этой панели поиска. Есть несколько способов использования частного API, например answer @sanjayshah, но в этом случае есть вероятность, что Apple отклонит ваше приложение. Я думаю, вам следует перейти к использованию цвета фона по умолчанию. Большинство приложений используют то же самое.
Рекурсивная версия ответа @Kamran с лучшим лучшим случаем и средним временем работы. Принятая версия у меня не работает на iOS 13+.
private lazy var searchTextField: UITextField? = { [unowned self] in
guard let searchBar = self.searchController?.searchBar else { return nil }
var views = searchBar.subviews
while !views.isEmpty {
guard let view = views.popLast() else { break }
if let textfield = view as? UITextField {
return textfield
}
views += view.subviews
}
return nil
}()
В iOS13 и более поздних версиях searchTextField является членом UISearchBar. Итак, вы можете использовать что-то вроде этого:
searchController.searchBar.searchTextField.backgroundColor = UIColor.blue
Будьте осторожны, у Apple нет надлежащей записи в SDK, показывающей, что это свойство появилось в iOS 13, поэтому, если вы поддерживаете iOS 12 или более раннюю версию, оно не показывает вам никаких предупреждений. Обязательно заверните его только для iOS 13.
Сначала проверьте платформу,
чем вносить изменения, потому что iOS 13 не принимает много трюков, сделанных для iOS 12
if #available(iOS 13, *) {
searchController.searchBar.searchTextField.backgroundColor = .white
} else {
for textField in searchController.searchBar.subviews.first.subviews where textField is UITextField {
textField.subviews.first.backgroundColor = .white
textField.subviews.first.layer.cornerRadius = 10
textField.subviews.first.layer.masksToBounds = true
}
}
В iOS 12 и ниже необходимо закрыть изображение внутри текстового поля, это изображение дает цвет фона, который мы хотим изменить. Вы можете добавить собственное представление в индекс 1 сразу после просмотра изображения, чтобы добиться желаемого.
if #available(iOS 13.0, *)
{
searchBar.searchTextField.textColor = .black
searchBar.searchTextField.backgroundColor = .red
}
else if let textFieldInsideSearchBar = searchBar.value(forKey: "searchField") as? UITextField
{
textFieldInsideSearchBar.textColor = .black
let backgroundView = UIView(frame: textFieldInsideSearchBar.bounds)
backgroundView.backgroundColor = .red
backgroundView.layer.cornerRadius = 10
backgroundView.clipsToBounds = true
textFieldInsideSearchBar.insertSubview(backgroundView, at: 1)
}
увидеть это stackoverflow.com/questions/52905371/…