Удалить кнопку Очистить (серый x) справа от UISearchBar при нажатии кнопки Отмена

правильно, чтобы начать мой вопрос, вот некоторые экранные проблемы, уже решенные приложением Spotify:

Шаг 1 Spotify: стандартный UISearchBar не в режиме редактирования.

Шаг 1 http://i49.tinypic.com/wbtpwi.png

Шаг 2 Spotify: UISearchBar теперь в режиме редактирования. Введен поисковый запрос. Кнопка "Отмена" скользит справа, и появляется кнопка "Очистить" (серый x).

Шаг 2 http://i45.tinypic.com/161kbvp.png

Шаг 3 Spotify: кнопка отмены нажата; клавиатура выскальзывает, и панель поиска больше не находится в режиме редактирования. Срок поиска остается и серая кнопка x теперь скрыта.

Шаг 3 http://i46.tinypic.com/20utv9v.png

В настоящее время следующий код срабатывает, когда мой кнопка отмены нажата:

- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar {
    [searchBar resignFirstResponder];
    [searchBar setShowsCancelButton:NO animated:YES];
}

какие результаты в:

Шаг 3: панель поиска теперь не в режиме редактирования. Кнопка "Отмена" и клавиатура выскользнули. Поисковый запрос остается, но и серый x.

проблема http://i46.tinypic.com/rlm4w5.png

Итак, мой вопрос таков: учитывая это -resignFirstResponder-endEditing:, FYI) делает не скрыть серую кнопку x, когда в строке поиска был введен текст, как его скрыть?

еще раз спасибо, друзья.

11 ответов


проблема в том, что UISearchBar не предоставляет текстовое поле и управляет свойствами самого текстового поля. Иногда, значения свойств не то, что вы хотите.

например, в моем собственном приложении я хотел, чтобы стиль клавиатуры для моей панели поиска использовал прозрачный стиль оповещения.

мое решение состояло в том, чтобы пройти через подвиды панели поиска, пока вы не найдете текстовое поле. Затем вы сможете установить clearButtonMode собственность, используя что-то как UITextFieldViewModeWhileEditing в качестве параметра.

это должно сделать так, чтобы кнопка clear отображалась только во время редактирования текстового поля.

вы хотите сделать это viewDidLoad или что-то раннее, поэтому оно установлено до того, как вы начнете его использовать (но после инициализации строки поиска.

for (UIView *subview in searchBar.subviews)
{
    if ([subview conformsToProtocol:@protocol(UITextInputTraits)])
    {
        [(UITextField *)subview setClearButtonMode:UITextFieldViewModeWhileEditing];
    }
}

похоже, что iOS 7 изменила иерархию представлений UISearchBar, и текстовое поле находится глубже в представлении (вышеупомянутое решение не сработало для меня). Однако изменение вышеуказанного решения для прохождения всей иерархии работает:

[self configureSearchBarView:[self searchBar]];

- (void)configureSearchBarView:(UIView*)view {
    for (UIView *subview in [view subviews]){
        [self configureSearchBarView:subview];
    }
    if ([view conformsToProtocol:@protocol(UITextInputTraits)]) {
        [(UITextField *)view setClearButtonMode:UITextFieldViewModeWhileEditing];
    }
}

я основываюсь на предыдущих ответах, потому что я начал видеть сбои на iOS 7.1, если я не сделал следующее изменение. Я добавил дополнительный вызов respondsToSelector для каждого представления, чтобы убедиться в том, что setClearButtonMode: можно назвать. Я наблюдал пример UISearchBar получение прошло, что, кажется, соответствует UITextInputTraits протокол еще не имеет setClearButtonMode: селектор, поэтому произошел сбой. Пример UISearchBarTextField также передается и является фактическим объектом для вызова setClearButtonMode:.

- (void)removeClearButtonFromView:(UIView *)view
{
    if (!view)
    {
        return;
    }

    for (UIView *subview in view.subviews)
    {
        [self removeClearButtonFromView:subview];
    }

    if ([view conformsToProtocol:@protocol(UITextInputTraits)])
    {
        UITextField *textView = (UITextField *)view;
        if ([textView respondsToSelector:@selector(setClearButtonMode:)])
        {
            [textView setClearButtonMode:UITextFieldViewModeNever];
        }
    }
}

лучший способ сделать это в iOS7:

[[UITextField appearanceWhenContainedIn:[UISearchBar class], nil] setClearButtonMode:UITextFieldViewModeWhileEditing];


вам нужно получить текстовое поле строки поиска

UITextField *textField = [searchBar valueForKey:@"_searchField"];
textField.clearButtonMode = UITextFieldViewModeNever;

использовать в - (void)searchBarTextDidBeginEditing: (UISearchBar *)метод searchBar.

- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar
 {

UITextField *textField = [searchBar valueForKey:@"_searchField"];
textField.clearButtonMode = UITextFieldViewModeNever;


 }

чтобы развернуть ответ Jadariens, если вы никогда не хотите, чтобы серый x появился, вам нужно использовать следующее

for (UIView *subview in searchBar.subviews)
{
    if ([subview conformsToProtocol:@protocol(UITextInputTraits)])
    {
        [(UITextField *)subview setClearButtonMode:UITextFieldViewModeNever];
    }
}

принятый ответ не работает на iOS7+, вот измененная версия в качестве расширения Swift

extension UIView {
    class func removeClearButton(svs: [UIView]) {
        for sv in svs {
            if let tv = sv as? UITextField where sv.conformsToProtocol(UITextInputTraits) {
                tv.clearButtonMode = .Never
                return
            } else {
                UIView.removeClearButton(sv.subviews)
            }
        }
    }
}

использование

UIView.removeClearButton(searchBar.subviews)

ее категория, которую я написал, делает это

категория

@implementation UISearchBar (Additions)

- (void)setClearButtonMode:(UITextFieldViewMode)viewMode {
    UITextField *textField = [self findTextFieldInView:self];
    [textField setClearButtonMode:viewMode];
}

- (UITextField *)findTextFieldInView:(UIView *)view {

    for (UIView *subview in view.subviews) {

        if ([subview isKindOfClass:[UITextField class]] ||
            [subview.class isSubclassOfClass:[UITextField class]]) {

            return (UITextField *)subview;
        }

        UITextField *textField = [self findTextFieldInView:subview];

        if (textField) {
            return textField;
        }
    }

    return nil;
}

@end

использование

[searchBar setClearButtonMode:UITextFieldViewModeWhileEditing];

есть лучший способ, чем любой из ответов здесь, и вам не нужно использовать частные API или пересекать подвиды для этого.

UISearchBar имеет встроенный API для этого:

[uisearchbar setImage: forSearchBarIcon: state]

ключ значка панели поиска, который вы хотите, - UISearchBarIconClear, и вы хотите состояние UIControlStateNormal. Затем дайте ему четкое изображение для изображения, и вы закончите.

Итак, это должно выглядеть так это:

[searchBar setImage:clearImage forSearchBarIcon:UISearchBarIconClear state:UIControlStateNormal];

для значка (x) в строке поиска. Вы можете использовать метод делегата ниже.

- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar
{
    searchBar.showsCancelButton = YES;
}

for (UIView *subview in _search_bar.subviews)
{
    NSLog(@"%@",subview.subviews);

    for (UIView *subview11 in subview.subviews)
    {
        if ([subview11 conformsToProtocol:@protocol(UITextInputTraits)])
        {
            [(UITextField *)subview11 setClearButtonMode:UITextFieldViewModeNever];
        }
    }

}