如何使用UISearchBar启用取消button?
在iPhone上的联系人应用程序中,如果您inputsearch词,然后点击“search”button,键盘被隐藏,但取消button仍处于启用状态。 在我的应用程序中,当我呼叫resignFirstResponder时取消button被禁用。
任何人都知道如何隐藏键盘,同时保持取消button处于启用状态?
我使用下面的代码:
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar { [searchBar resignFirstResponder]; }
键盘滑出视图,但search文本字段右侧的“取消”button被禁用,因此我无法取消search。 联系人应用程序将取消button保持在启用状态。
我想也许有一个解决scheme是潜入searchBar对象,并在实际文本字段上调用resignFirstResponder,而不是search栏本身。
任何input赞赏。
尝试这个
for(id subview in [yourSearchBar subviews]) { if ([subview isKindOfClass:[UIButton class]]) { [subview setEnabled:YES]; } }
这个方法在iOS7中工作。
- (void)enableCancelButton:(UISearchBar *)searchBar { for (UIView *view in searchBar.subviews) { for (id subview in view.subviews) { if ( [subview isKindOfClass:[UIButton class]] ) { [subview setEnabled:YES]; NSLog(@"enableCancelButton"); return; } } } }
(也请务必在使用[_searchBar resignFirstResponder]之后的任何地方调用它。)
当您开始滚动表格而不是点击“search”button时,接受的解决scheme将不起作用。 在这种情况下,“取消”button将被禁用。
这是我的解决scheme,每次使用KVO禁用时,都会重新启用“取消”button。
- (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; // Search for Cancel button in searchbar, enable it and add key-value observer. for (id subview in [self.searchBar subviews]) { if ([subview isKindOfClass:[UIButton class]]) { [subview setEnabled:YES]; [subview addObserver:self forKeyPath:@"enabled" options:NSKeyValueObservingOptionNew context:nil]; } } } - (void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; // Remove observer for the Cancel button in searchBar. for (id subview in [self.searchBar subviews]) { if ([subview isKindOfClass:[UIButton class]]) [subview removeObserver:self forKeyPath:@"enabled"]; } } - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { // Re-enable the Cancel button in searchBar. if ([object isKindOfClass:[UIButton class]] && [keyPath isEqualToString:@"enabled"]) { UIButton *button = object; if (!button.enabled) button.enabled = YES; } }
从iOS 6开始,button看起来像UINavigationButton(私有类),而不是UIButton。
我已经调整了上面的例子看起来像这样。
for (UIView *v in searchBar.subviews) { if ([v isKindOfClass:[UIControl class]]) { ((UIControl *)v).enabled = YES; } }
但是,这显然是脆弱的,因为我们正在与内部打交道。 它也可以启用更多的button,但它为我工作,直到find一个更好的解决scheme。
我们应该问苹果揭露这一点。
这似乎适用于我(在viewDidLoad):
__unused UISearchDisplayController* searchDisplayController = [[UISearchDisplayController alloc] initWithSearchBar:self.searchBar contentsController:self];
我意识到我应该正确使用UISearchDisplayController,但是这对我当前的实现来说是一个简单的修复。
您可以使用运行时API访问取消button。
UIButton *btnCancel = [self.searchBar valueForKey:@"_cancelButton"]; [btnCancel setEnabled:YES];
通过在UISearchBar上实现这个简单类别,我扩展了已经发布的其他人。
的UISearchBar + alwaysEnableCancelButton.h
#import <UIKit/UIKit.h> @interface UISearchBar (alwaysEnableCancelButton) @end
的UISearchBar + alwaysEnableCancelButton.m
#import "UISearchBar+alwaysEnableCancelButton.h" @implementation UISearchBar (alwaysEnableCancelButton) - (BOOL)resignFirstResponder { for (UIView *v in self.subviews) { // Force the cancel button to stay enabled if ([v isKindOfClass:[UIControl class]]) { ((UIControl *)v).enabled = YES; } // Dismiss the keyboard if ([v isKindOfClass:[UITextField class]]) { [(UITextField *)v resignFirstResponder]; } } return YES; } @end
这是一个稍微强大的解决scheme,适用于iOS 7.它将recursion遍历search栏的所有子视图,以确保它启用所有UIControl
(包括“取消”button)。
- (void)enableControlsInView:(UIView *)view { for (id subview in view.subviews) { if ([subview isKindOfClass:[UIControl class]]) { [subview setEnabled:YES]; } [self enableControlsInView:subview]; } }
在调用[self.searchBar resignFirstResponder]
之后,请立即调用此方法:
[self enableControlsInView:self.searchBar];
瞧! 取消button保持启用。
for (UIView *firstView in searchBar.subviews) { for(UIView* view in firstView.subviews) { if([view isKindOfClass:[UIButton class]]) { UIButton* button = (UIButton*) view; [button setEnabled:YES]; } } }
我发现一个不同的方法,使其在iOS 7中的工作。
我正在尝试的东西就像Twitter的iOS应用程序。 如果您单击“时间轴”选项卡中的放大镜,则显示UISearchBar
,同时激活“取消”button,显示键盘和最近的search屏幕。 滚动最近的search屏幕,它隐藏键盘,但它保持取消button激活。
这是我的工作代码:
UIView *searchBarSubview = self.searchBar.subviews[0]; NSArray *subviewCache = [searchBarSubview valueForKeyPath:@"subviewCache"]; if ([subviewCache[2] respondsToSelector:@selector(setEnabled:)]) { [subviewCache[2] setValue:@YES forKeyPath:@"enabled"]; }
我通过在我的表视图的scrollViewWillBeginDragging:
设置一个断点来解决这个问题。 我看着我的UISearchBar
,露出它的子视图。 它总是只有一个,这是UIView
types(我的variablessearchBarSubview
)。
然后,该UIView
拥有一个名为subviewCache
NSArray
,我注意到最后一个元素,这是第三个,是UINavigationButton
types,不在公共API中。 所以我开始使用键值编码。 我检查了UINavigationButton
是否响应了setEnabled:
,幸运的是,它的确如此。 所以我把属性设置为@YES
。 原来那个UINavigationButton
是取消button。
如果苹果决定改变一个UISearchBar
的内部的实现,这肯定会打破,但是到底是什么。 它现在工作。
David Douglas答复的SWIFT版本(在iOS9上testing)
func enableSearchCancelButton(searchBar: UISearchBar){ for view in searchBar.subviews { for subview in view.subviews { if let button = subview as? UIButton { button.enabled = true } } } }
build立在smileyborg的答案 ,只需将其放置在您的searchBar代表:
- (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); }); }
此解决scheme在iOS 7及更高版本上运行良好。
你可以创build从UISearchBarinheritance的CustomSearchBar并实现这个方法:
- (void)layoutSubviews { [super layoutSubviews]; @try { UIView *baseView = self.subviews[0]; for (UIView *possibleButton in baseView.subviews) { if ([possibleButton respondsToSelector:@selector(setEnabled:)]) { [(UIControl *)possibleButton setEnabled:YES]; } } } @catch (NSException *exception) { NSLog(@"ERROR%@",exception); } }
更好的解决scheme是
[UIBarButtonItem appearanceWhenContainedIn:[UISearchBar class], nil].enabled = YES;
对于iOS 10,Swift 3:
for subView in self.movieSearchBar.subviews { for view in subView.subviews { if view.isKind(of:NSClassFromString("UIButton")!) { let cancelButton = view as! UIButton cancelButton.isEnabled = true } } }
更好和简单的方法:
[(UIButton *)[self.searchBar valueForKey:@"_cancelButton"] setEnabled:YES];
对于iOS 9/10(testing),Swift 3(更短):
searchBar.subviews.flatMap({$0.subviews}).forEach({ ($0 as? UIButton)?.isEnabled = true })