Ios4 UI搜索栏禁用自动禁用取消按钮
我在表视图中实现了一个UISearchBar,除了一件小事之外,几乎所有的东西都在工作:当我输入文本,然后按下键盘上的搜索按钮时,键盘消失,搜索结果是表中显示的唯一项目,文本保留在UISearchBar中,但取消按钮被禁用 我一直试图让我的列表尽可能接近Apple contacts应用程序的功能,当你在该应用程序中按search时,它不会禁用cancel按钮 当我查看UISearchBar头文件时,我注意到在_searchBarFlags结构下有一个autoDisableCancelButton标志,但它是私有的Ios4 UI搜索栏禁用自动禁用取消按钮,ios4,uisearchbar,cancel-button,Ios4,Uisearchbar,Cancel Button,我在表视图中实现了一个UISearchBar,除了一件小事之外,几乎所有的东西都在工作:当我输入文本,然后按下键盘上的搜索按钮时,键盘消失,搜索结果是表中显示的唯一项目,文本保留在UISearchBar中,但取消按钮被禁用 我一直试图让我的列表尽可能接近Apple contacts应用程序的功能,当你在该应用程序中按search时,它不会禁用cancel按钮 当我查看UISearchBar头文件时,我注意到在_searchBarFlags结构下有一个autoDisableCancelButton
当我设置UISearchBar时,是否有遗漏的内容?我找到了解决方案。您可以使用此for循环在搜索栏的子视图上循环,并在按下键盘上的搜索按钮时启用它
for(UIView*搜索栏中的可能按钮。子视图)
{
if([possibleButton IsKindof类:[UIButton类]])
{
UIButton*cancelButton=(UIButton*)可能的按钮;
cancelButton.enabled=是;
打破
}
}
这就是我在iOS 6上工作的原因:
searchBar.showsCancelButton = YES;
searchBar.showsScopeBar = YES;
[searchBar sizeToFit];
[searchBar setShowsCancelButton:YES animated:YES];
为了让它在iOS7中为我工作,我不得不对它进行一些调整
-(void)enableCancelButton:(UISearchBar*)搜索栏
{
用于(UIView*搜索栏中的视图。子视图)
{
用于(视图中的id子视图。子视图)
{
if([subview iskindof类:[UIButton类]])
{
[子视图设置启用:是];
NSLog(@“启用取消按钮”);
返回;
}
}
}
}
这是我的解决方案,它适用于所有版本的iOS中的所有情况
也就是说,由于用户拖动了一个滚动视图,所以当键盘被关闭时,其他解决方案无法处理
- (void)enableCancelButton:(UIView *)view {
if ([view isKindOfClass:[UIButton class]]) {
[(UIButton *)view setEnabled:YES];
} else {
for (UIView *subview in view.subviews) {
[self enableCancelButton:subview];
}
}
}
// This will handle whenever the text field is resigned non-programatically
// (IE, because it's set to resign when the scroll view is dragged in your storyboard.)
- (void)searchBarTextDidEndEditing:(UISearchBar *)searchBar {
[self performSelector:@selector(enableCancelButton:) withObject:searchBar afterDelay:0.001];
}
// Also follow up every [searchBar resignFirstResponder];
// with [self enableCancelButton:searchBar];
没有一个答案对我有用。我的目标是iOS 7。但我找到了答案 我正在尝试的是类似于Twitter iOS应用程序的东西。如果单击“时间线”选项卡中的放大镜,则会出现
ui搜索栏
,并激活“取消”按钮,显示键盘和“最近搜索”屏幕。滚动最近的搜索屏幕,它隐藏键盘,但它保持取消按钮激活
这是我的工作代码:
UIView *searchBarSubview = self.searchBar.subviews[0];
NSArray *subviewCache = [searchBarSubview valueForKeyPath:@"subviewCache"];
if ([subviewCache[2] respondsToSelector:@selector(setEnabled:)]) {
[subviewCache[2] setValue:@YES forKeyPath:@"enabled"];
}
我通过在表视图的ScrollViewWillBeginDraging:
上设置断点来实现此解决方案。我查看了我的ui搜索栏
,并显示了它的子视图。它总是只有一个,类型为UIView
(我的变量searchBarSubview
)
然后,UIView
保存一个名为subviewCache
的NSArray
,我注意到最后一个元素,即第三个元素,是UINavigationButton
类型,不在公共API中。所以我开始使用键值编码来代替。我检查了UINavigationButton
是否响应setEnabled:
,幸运的是,它响应了。因此,我将属性设置为@YES
。原来,UINavigationButton
是取消按钮
如果苹果决定改变UISearchBar
的内部实现,这一点肯定会被打破,但这到底是怎么回事。现在可以使用了。根据,将其放置在搜索栏代理中:
- (void)searchBarTextDidEndEditing:(UISearchBar *)searchBar
{
dispatch_async(dispatch_get_main_queue(), ^{
__block __weak void (^weakEnsureCancelButtonRemainsEnabled)(UIView *);
void (^ensureCancelButtonRemainsEnabled)(UIView *);
weakEnsureCancelButtonRemainsEnabled = ensureCancelButtonRemainsEnabled = ^(UIView *view) {
for (UIView *subview in view.subviews) {
if ([subview isKindOfClass:[UIControl class]]) {
[(UIControl *)subview setEnabled:YES];
}
weakEnsureCancelButtonRemainsEnabled(subview);
}
};
ensureCancelButtonRemainsEnabled(searchBar);
});
}
对于Monotouch或Xamarin iOS,我有以下适用于iOS 7和iOS 8的C#解决方案:
foreach(UIView view in searchBar.Subviews)
{
foreach(var subview in view.Subviews)
{
//Console.WriteLine(subview.GetType());
if(subview.GetType() == typeof(UIButton))
{
if(subview.RespondsToSelector(new Selector("setEnabled:")))
{
UIButton cancelButton = (UIButton)subview;
cancelButton.Enabled = true;
Console.WriteLine("enabledCancelButton");
return;
}
}
}
}
这个答案基于解决方案。有两种方法可以轻松实现这一点
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar{
// The small and dirty
[(UIButton*)[searchBar valueForKey:@"_cancelButton"] setEnabled:YES];
// The long and safe
UIButton *cancelButton = [searchBar valueForKey:@"_cancelButton"];
if ([cancelButton respondsToSelector:@selector(setEnabled:)]) {
cancelButton.enabled = YES;
}
}
你应该使用第二个,如果苹果在后台更改它,它不会使你的应用程序崩溃
顺便说一句,我从iOS 4.0到8.2对它进行了测试,没有任何更改,而且我在商店认可的应用程序中使用了它,没有任何问题。更完整的答案:
- 自iOS 7以来,在搜索栏下增加了一级子视图
- 启用“取消”按钮的最佳位置是
searchbartextdidediting
下面是一个Swift 3解决方案,它利用扩展功能轻松获取“取消”按钮:
extension UISearchBar {
var cancelButton: UIButton? {
for subView1 in subviews {
for subView2 in subView1.subviews {
if let cancelButton = subView2 as? UIButton {
return cancelButton
}
}
}
return nil
}
}
现在了解用法:
class MyTableViewController : UITableViewController, UISearchBarDelegate {
var searchBar = UISearchBar()
func viewDidLoad() {
super.viewDidLoad()
searchBar.delegate = self
tableView.tableHeaderView = searchBar
}
func searchBarTextDidEndEditing(_ searchBar: UISearchBar) {
DispatchQueue.main.async {
if let cancelButton = searchBar.cancelButton {
cancelButton.isEnabled = true
cancelButton.isUserInteractionEnabled = true
}
}
}
}
时间流逝,但问题仍然存在 优雅的Swift 5/iOS 13解决方案:
func searchBarTextDidEndEditing(_ searchBar: UISearchBar) {
for case let cancelButton as UIButton in searchBar.subviews {
cancelButton.isEnabled = true
}
}
这对我在iOS 6上不起作用,因为唯一存在的按钮是一个UINavigationButton,它似乎是一个私有类。您是否尝试在UISearchBar上设置showsCancelButton属性?UINavigationButton是UIButton的子类,因此此代码有效,并且没有私有类用法。在搜索栏失去焦点(辞职FirstResponder)后,你只需要在适当的时候使用它。对我来说很有用!我做了
((UIButton*)可能的按钮)。enabled=YES
我发现使用了太多的cancelButton
。这并不能解决问题:op想要禁用自动禁用功能,即不允许UISearchBar禁用它。您应该返回内部if语句,而不是中断。该break语句只会将您从内部for循环中分离出来,并将继续在searchBar.subview上循环,即使在找到“取消”按钮后也是如此。这是可行的,但您的应用可能会被拒绝,因为它使用的是私有方法。小心。@PedroJoséCardoso不,这并不算是私有api的使用,而且我从来没有见过任何因为这一点而被拒绝的情况。这是我见过的最干净的解决方案。谢谢。在iOS 13+上不起作用,因为在iOS 13UISearchBar中,subview 2
不是UIButton
。subview
只返回一个元素,而不是UIButton
func searchBarTextDidEndEditing(_ searchBar: UISearchBar) {
for case let cancelButton as UIButton in searchBar.subviews {
cancelButton.isEnabled = true
}
}