当取消按钮被点击时,将UISearchBar右侧的清除按钮(灰色x)移除。

23

首先,这是我的问题,以下是Spotify应用程序解决此问题的截图:

Spotify的第一步:标准的UISearchBar处于非编辑模式。

Step 1

Spotify的第二步:UISearchBar现在处于编辑模式。输入搜索词。取消按钮从右侧滑入,清除按钮(灰色x)出现。

Step 2

Spotify的第三步:按下取消按钮;键盘滑出,搜索栏不再处于编辑模式。搜索词保留,现在隐藏灰色x按钮

Step 3

目前,当按下我的取消按钮时,以下代码会触发:

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

结果如下:

我的步骤3:搜索栏现在不处于编辑模式。取消按钮和键盘已经滑出。搜索词保留,但灰色的x也保留。

Problem

因此,我的问题是:鉴于-resignFirstResponder(以及-endEditing:,FYI)不能在搜索栏中输入文本时隐藏灰色x按钮,那么如何隐藏它?

再次感谢,朋友们。

11个回答

29
问题在于UISearchBar没有公开其文本字段,并管理文本字段上的属性。有时,属性的值不是您想要的。
例如,在我的应用中,我希望搜索栏的键盘样式使用透明警报样式。
我的解决办法是遍历搜索栏的子视图,直到找到文本字段。然后,您应该能够设置clearButtonMode属性,使用类似UITextFieldViewModeWhileEditing的参数。
这样应该使清除按钮仅在文本字段正在编辑时显示。
您需要在viewDidLoad或某些早期执行此操作,以便在开始使用之前设置它(但在搜索栏初始化之后)。
for (UIView *subview in searchBar.subviews)
{
    if ([subview conformsToProtocol:@protocol(UITextInputTraits)])
    {
        [(UITextField *)subview setClearButtonMode:UITextFieldViewModeWhileEditing];
    }
}

1
谢谢 Jasarien,这似乎正是我所需要的。不幸的是,在[subview conformsToProtocol:UITextInputTraits] 这一行中出现了一个错误,错误信息为:expected expression before 'UITextInputTraits'。我需要导入或遵循任何协议吗? - David Foster
2
我的错!抱歉。你需要执行 [subview conformsToProtocol:@protocol(UITextInputTraits)] - Jasarien
1
顺便问一下,你是用应用程序在截图上做了那个小注释吗?如果是的话,用的是什么应用程序?看起来很有用 :) - Jasarien
1
不幸的是,那只是Photoshop的画笔工具。不过注释应用程序是个好主意! - David Foster

6

看起来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];
    }
}

这个功能可以很容易地被转换为UISearchBar的分类,以便复用。 - ABeanSits
3
似乎会导致崩溃,显然有不止一个符合UITextInputTraits的视图,而且该视图无法响应setClearButtonMode。 - Mackey18
为了避免闪退,我将代码更改如下:for (UIView *subview in [self.searchDisplayController.searchBar subviews]){[self configureSearchBarView:subview];} 并添加 configureSearchBarView:(UIView *)view 方法。看起来在我的情况下是 searchBar 本身导致的崩溃。 - Mackey18

6

我想在之前的答案基础上补充一些内容,因为我发现在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]; } } }

最佳解决方案!谢谢。 - Simone Lai

5
您需要获取搜索栏的文本字段。
UITextField *textField = [searchBar valueForKey:@"_searchField"];
textField.clearButtonMode = UITextFieldViewModeNever;

在使用中,需要调用 - (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar 方法。

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

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


 }

4
在iOS7中更好的方法是: [[UITextField appearanceWhenContainedIn:[UISearchBar class], nil] setClearButtonMode:UITextFieldViewModeWhileEditing];

3

如果你希望灰色的“X”永远不出现,你需要使用以下方法:

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

1

被接受的答案在 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)

0

这里有比任何答案都更好的方法,而且您不必使用私有API或遍历子视图来完成。

UISearchBar具有内置的API可用于执行此操作:

[UISearchBar setImage:forSearchBarIcon:state]

您想要的SearchBar图标键是UISearchBarIconClear,并且您想要UIControlStateNormal状态。然后为图像提供一个清晰的图像,就完成了。

所以,它应该看起来像这样:

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

0
这是我写的一个类别,可以实现这个功能。
类别。
@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];

0
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];
        }
    }

}

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