隐藏UISearchBar的清除文本按钮

16
我想知道如何隐藏或不显示出现在UISearchBar textField中的交叉按钮。
我尝试过使用以下代码:
filterSearchBar.showsCancelButton = NO;

然而,这是一个真正的取消按钮,而不是小灰色的交叉按钮,所以我想知道在UISearchBar中是否有与小灰色按钮相当的替代按钮。

15个回答

37

您需要获取搜索栏的textField:

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

希望这能有所帮助!=)


你在哪里找到键"_searchField",它是否在文档中? - Sébastien REMY
1
你可以在运行时头文件中找到它。例如:https://github.com/nst/iOS-Runtime-Headers。 - Saren Inden

10

有一种更好的方法可以做到这一点,而且您不必使用私有API或遍历子视图来完成,因此此解决方案是App Store安全的。

UISearchBar内置了用于执行此操作的API:

[UISearchBar setImage:forSearchBarIcon:state]

您要使用的SearchBar图标关键字是UISearchBarIconClear,状态是UIControlStateNormal。 然后为其提供一个清晰的图片,就完成了。

因此,它应该看起来像这样:

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

3
尽管这个技术上可以使按钮不可见,但您仍然可以轻触它。但是因为使用了官方的API而得到了一个加分。 - zliw
有人找到了一个非黑客解决方案来防止与按钮的交互吗? - Charlton Provatas

8

Swift 4

在Alexander的回答基础上,针对清除按钮进行用户交互屏蔽的操作:

隐藏按钮:

searchBar.setImage(UIImage(), for: .clear, state: .normal)

要禁用清除按钮上的用户交互,只需对UISearchBar进行子类化。

class CustomSearchBar: UISearchBar {

    override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
        let view = super.hitTest(point, with: event)
        if view is UIButton {
            return view?.superview // this will pass-through all touches that would've been sent to the button
        }
        return view
    }
}

这是一个适用于Swift 4+的好解决方案,我一直在使用以上以"_searchField"为键的方法,但在iOS 13.2.2上应用程序崩溃了。这个解决方案已经修复了我的问题,无论是较低版本的iOS还是最新版本的iOS都可以使用。 - Muhammad Adil

8

参考@Gines的答案,这里是Swift版本:

func searchBarTextDidBeginEditing(searchBar: UISearchBar) {
    guard let firstSubview = searchBar.subviews.first else { return }

    firstSubview.subviews.forEach {
        ($0 as? UITextField)?.clearButtonMode = .never
    }
}

@Tom 谢谢你的编辑。看起来完美。这是正确的方法吗? - kishorer747
1
我认为Soto_iGhost的方法是解决这个特定问题的最佳方法。但当我看到你的代码时,我忍不住想要编辑它☺️ 当然,编写这个相同逻辑的方法有很多种,但我最喜欢这种方法。 - Tom van Zummeren

7

Swift 5

测试于 iOS 13

对我有效的一行代码:

searchBar.searchTextField.clearButtonMode = .never

您还可以将其设置为 .whileEditing,这样当用户在输入时它将显示出来,然后在搜索栏失去焦点时被移除。

5
您可以为所有的 UISearchBar 实例移除清除文本按钮:
[UITextField appearanceWhenContainedInInstancesOfClasses:@[[UISearchBar class]]].clearButtonMode = UITextFieldViewModeNever;

这是唯一有效的非黑客式答案。干得好! - Jan
这个答案看起来不错 - 我们还能将其设置为特定视图控制器类的搜索栏吗?我在多个地方都有搜索栏,只需要为一个类更新它。 - Hemang

5

根据@Alexsander的回答,Swift 3如下:

searchBar.setImage(UIImage(), for: .clear, state: .normal)

4

Swift 5

只需在下面添加一行代码即可:

searchBar.searchTextField.clearButtonMode = .never

3

Swift 3解决方案:

extension UISearchBar{
    var textField : UITextField{
        return self.value(forKey: "_searchField") as! UITextField
    }
}

使用方法:

searchBar.textField.clearButtonMode = .never

1
这个程序崩溃了。 - Denis Kakačka

2

我尝试了几种解决方案,包括这篇文章中提到的方法,但它们都没有奏效。

以下是我找到的解决方法:

UIView *subview = [[searchBar subviews] firstObject]; //SearchBar only have one subview (UIView)

//There are three sub subviews (UISearchBarBackground, UINavigationButton, UISearchBarTextField)
for (UIView *subsubview in subview.subviews)
{
    //The UISearchBarTextField class is a UITextField. We can't use UISearchBarTextField directly here.
    if ([subsubview isKindOfClass: [UITextField class]])
    {
            [(UITextField *)subsubview setClearButtonMode:UITextFieldViewModeNever];
    }
}

谢谢,它起作用了!关键是要搜索Searchbar的第一个子视图的子视图。请查看我的Swift版本答案。 - kishorer747

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