UISearchBar отменить цвет кнопки?

Когда я помещаю UISearchBar в представление в Интерфейсном Разработчике и меняю его стиль на Черный Непрозрачный, кнопка отмены остается не совсем подходящей сине-серой и не становится черной.

Как сделать кнопку отмены черной?

РЕДАКТИРОВАТЬ: Это работает так:

// Assume a UISearchBar searchBar.
NSArray *subviews = [searchBar subviews];

// The index depends on how you configure the searchBar.
UIButton *cancelButton = [subviews objectAtIndex:3];

// Set the style to "normal" style.
[cancelButton setStyle:0];

Но setStyle: Метод из частной структуры, поэтому это может быть проблемой при отправке приложения в Apple.

10 ответов

Я использовал что-то вроде этого и работал со мной:

[[UIBarButtonItem appearanceWhenContainedIn: [UISearchBar class], nil] setTintColor:[UIColor blackColor]];

он изменил цвет кнопки отмены на черный.

Обновление для iOS 9.0, метод appearanceWhenContainedIn устарела, использовать appearanceWhenContainedInInstancesOfClasses вместо:

[[UIBarButtonItem appearanceWhenContainedInInstancesOfClasses:@[[UISearchBar class]]] setTintColor:[UIColor blackColor]];

И в Свифте 3:

UIBarButtonItem.appearance(whenContainedInInstancesOf:[UISearchBar.self]).tintColor = UIColor.black

Проблема с вашим решением состоит в том, что код предполагает, что objectAtIndex:3 является кнопкой отмены. Это не только генерирует предупреждение компилятора, но также, если вы отображаете кнопку "Отмена" программно (например, используя [searchBar setShowsCancelButton:YES], вы рискуете сбой приложения.

Более простое решение - установить стиль всей панели поиска в ViewDidLoad(), используя:

searchBar.tintColor = [UIColor colorWithWhite:0.3 alpha:1.0];

это переопределяет стиль, установленный в Интерфейсном Разработчике, НО также меняет цвет кнопки "Отмена" на тот же цвет, что и вся панель (хотя, к сожалению, не позволяет независимо устанавливать стиль кнопки "Отмена").

Попробуйте это и посмотрите: (Я тестировал код ниже со Swift 4.1 - Xcode 9.3-beta4)

@IBOutlet weak var sbSearchBar: UISearchBar!

sbSearchBar.tintColor = UIColor.red
sbSearchBar.showsCancelButton = true
sbSearchBar.barTintColor = UIColor.blue
sbSearchBar.tintColor = UIColor.red

if let buttonItem = sbSearchBar.subviews.first?.subviews.last as? UIButton {
    buttonItem.setTitleColor(UIColor.yellow, for: .normal)
}

Для iOS 10:

UISearchBar.appearance().tintColor = UIColor.red //cancel button color
UISearchBar.appearance().barTintColor = UIColor.blue //background button color

В Swift 4.2

let appearance = UIBarButtonItem.appearance(whenContainedInInstancesOf: [UISearchBar.self])
appearance.setTitleTextAttributes([NSAttributedString.Key.foregroundColor: UIColor(named: "goldColor")!], for: .normal)

Это работает для меня. Спасибо @Tim Semple

Это обновленная версия ответа Хоссама Гариба выше для Swift 3:

UIBarButtonItem.appearance(whenContainedInInstancesOf: [UISearchBar.self] ).tintColor = UIColor.red

Но это не отменит внешний вид, если он уже был установлен в другом месте для UIBarButtonItem.

Например, в моем контроллере navbar мне пришлось изменить это:

UIBarButtonItem.appearance().setTitleTextAttributes([NSForegroundColorAttributeName:UIColor.white], for: UIControlState.normal)

Для этого для решения выше, чтобы работать:

UIBarButtonItem.appearance(whenContainedInInstancesOf: [UINavigationBar.self] ).setTitleTextAttributes([NSForegroundColorAttributeName:UIColor.white], for: UIControlState.normal)

Придумал следующее решение, которое также работает с iOS 13.0 и iOS 12.4, должно работать и над предыдущими версиями до iOS 9.0. Следующее решение предназначено для:

  1. Цвет кнопки отмены (нормальное состояние).
  2. Цвет кнопки отмены (отключенное состояние).
  3. Цвет фона текстового поля панели поиска (нормальное состояние).

Для цели C:

[[UIBarButtonItem appearanceWhenContainedInInstancesOfClasses:@[[UISearchBar class]]] setTintColor:[UIColor whiteColor]]; 

[[UIBarButtonItem appearanceWhenContainedInInstancesOfClasses:@[[UISearchBar class]]] setTitleTextAttributes:@{NSForegroundColorAttributeName: [UIColor whiteColor]} forState:UIControlStateNormal];

[[UIBarButtonItem appearanceWhenContainedInInstancesOfClasses:@[[UISearchBar class]]] setTitleTextAttributes:@{NSForegroundColorAttributeName: [UIColor whiteColor]} forState:UIControlStateDisabled];

[[UIBarButtonItem appearanceWhenContainedInInstancesOfClasses:@[[UISearchBar class]]] setTitleTextAttributes:@{NSBackgroundColorAttributeName: [UIColor whiteColor]} forState:UIControlStateNormal];

Приведенный выше код также фиксированный мои проблемы пользовательского интерфейса для прошивки 13 и iPhone X. Я включил этот код в моем AppDelegate.m классе в didFinishLaunchingWithOptions функции, так что изменения можно были бы сделать в целом приложение.

let view: UIView = self.searchBar.subviews[0] as UIView
let subViewsArray = view.subviews

for subView: UIView in subViewsArray {
    if let cancelButt = subView as? UIButton{
        cancelButt.setTitleColor(UIColor.white, for: .normal)         
    }
}

Это сработало для меня

Нажмите на строку поиска и установите цвет оттенка под представлением из Интерфейсного Разработчика.

Я взял ответ Бенджамина и соединил его с безопасным Array поиск для создания короткой, но безопасной функциональной версии:

searchController.searchBar.tintColor = UIColor.whiteColor()
(searchController.searchBar.subviews[safe: 0]?.subviews as? [UIView])?
    .filter({$0.isKindOfClass(UITextField)})
    .map({$0.tintColor = .lightGrayColor()})

Это приводит к окрашиванию кнопки Отмена в белый цвет и курсора при наборе серого. В противном случае он будет белым и, следовательно, не виден. searchController является объектом типа UISearchController, Если кто-то хочет использовать его в контроллере результатов, замените его на self,

Реализация safe: подстрочный ответ нкукушкина:

extension Array {
    subscript(safe index: Int) -> T? {
        return indices(self) ~= index ? self[index] : nil
    }
}

Для тех, кто хочет воспроизвести такое же поведение в Swift:

override func viewWillAppear(animated: Bool) {
    self.searchBar.tintColor = UIColor.whiteColor()

    let view: UIView = self.searchBar.subviews[0] as! UIView
    let subViewsArray = view.subviews

    for (subView: UIView) in subViewsArray as! [UIView] {
        println(subView)
        if subView.isKindOfClass(UITextField){
            subView.tintColor = UIColor.blueColor()
        }
    }

}
Другие вопросы по тегам