当您点击搜索文本框下方和键盘上方时,有谁知道如何从 UISearchBar 中取消(退出 First Responder)?任何人都可以帮助发布一些代码来处理这个问题吗?
谢谢
当您点击搜索文本框下方和键盘上方时,有谁知道如何从 UISearchBar 中取消(退出 First Responder)?任何人都可以帮助发布一些代码来处理这个问题吗?
谢谢
在(UISearchbar 的)父视图中添加点击手势
[self addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:searchBar action:@selector(resignFirstResponder)]];
我通过使用 UITapGestureRecognizer 实现了这一点:
UIGestureRecognizer* cancelGesture;
- (void) backgroundTouched:(id)sender {
[self.view endEditing:YES];
}
#pragma mark - UISearchBarDelegate
-(void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar {
cancelGesture = [UITapGestureRecognizer new];
[cancelGesture addTarget:self action:@selector(backgroundTouched:)];
[self.view addGestureRecognizer:cancelGesture];
}
-(void)searchBarTextDidEndEditing:(UISearchBar *)searchBar {
if (cancelGesture) {
[self.view removeGestureRecognizer:cancelGesture];
[cancelGesture release];
cancelGesture = nil;
}
}
代码是裸露的,但您可以看到意图。当 SearchBar 开始编辑时,您将点击手势识别器附加到视图控制器的视图,并在停止编辑时将其移除。
您可以解决一些注意事项:这样做会导致如果您单击键盘或搜索栏文本字段之外的任何内容,识别器会捕获单击 - 因此,如果您使用 clear、cancel、scope 或 results按钮,他们将无法正确响应。
在我的特定场景中,我有一个 UITableView 覆盖了视图的暴露区域,因此我将手势识别器而不是视图控制器的主视图附加到它,从而隔离了手势将响应的区域。
我从iphonedevbook获得的另一个想法,示例代码项目 04,是使用一个位于所有其他控件后面的大透明按钮,如果被点击,它只会让所有第一响应者辞职。即,如果用户在没有更重要的控制的地方点击——这是直观的行为——搜索栏和键盘就会消失。
我最终使用了 Hauke 和 Beau Scott 的混合方法。我在使用他们的解决方案时遇到了两个问题:
1) 如果屏幕上还有其他内容,点击它不会导致调用 resignFirstResponder。例如,如果用户点击一个按钮而不是按钮周围的空间,则该按钮将吞噬该事件。然而,Beau Scott 的解决方案解决了这个问题。
2)点击搜索栏本身将导致 resignFirstResponder 被调用。显然,当您点击 UISearchBar 时,您不希望键盘消失。下面描述的一个小改动解决了这个问题。
我最终将我的视图设置如下。父视图有两个子视图 - UISearchBar 和一个包含其余 UI 元素的子视图。子视图占据了 UISearchBar 下方的整个屏幕。然后我使用 Beau Scott 的确切代码来添加和删除手势识别器,但我没有将其添加到 self.view 中,而是将其添加到子视图中:
IBOutlet UIView *gestureRecognizer;
...
-(void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar {
cancelGesture = [UITapGestureRecognizer new];
[cancelGesture addTarget:self action:@selector(backgroundTouch:)];
[gestureRecognizer addGestureRecognizer:cancelGesture];
}
-(void)searchBarTextDidEndEditing:(UISearchBar *)searchBar {
if (cancelGesture) {
[gestureRecognizer removeGestureRecognizer:cancelGesture];
[cancelGesture release];
cancelGesture = nil;
}
}
首先,您需要对搜索栏的引用。假设您的控制器对象有一个对象引用 UISearchBar *theSearchBar,并且您在创建 UISearchBar 对象时分配了它。
接下来,您需要检测包含视图是否已被触摸。被触摸的视图“知道”,但您需要将该信息传递给控制器。可悲的是,Apple 没有提供一种简单的方法来做到这一点,但也没有那么难。
我的解决方案是用 UIControl 替换 UIViewController 对象通常创建的标准 UIView,然后让 UIViewController 响应触摸事件。
主控制器.m
- (void) loadView {
UIControl *control = [[UIControl alloc] initWithFrame: <desired frame>];
[control addTarget: self action: @selector(touchUpInside)
forControlEvents: UIControlEventTouchUpInside];
// or touch down events, or whatever you like
self.view = control;
[control release];
}
- (void) viewDidLoad {
[super viewDidLoad];
theSearchBar = [[UISearchBar alloc] initWithFrame: <desired frame>];
// insert code to finish customizing the search bar
[self.view addSubview: theSearchBar];
}
- (void) touchUpInside {
if [theSearchBar isFirstResponder] {
// grab any data you need from the search bar
[theSearchBar resignFirstResponder];
}
}
主控制器.h
@interface MainController : UIViewController
{
UISearchBar *theSearchBar;
}
澄清:
只有一个对象——我们称之为 MainController 类——它是 UIViewController 的子类。上面列出的所有方法都在 MainController 中实现。theSearchBar 在 .h 文件中被声明为 UISearchBar*。
您是否使用 Interface Builder 定义视图和控制器?如果是这样,我建议你学习如何不使用它——一旦你掌握了我们在这里讨论的那种技巧,它就变成了障碍而不是帮助——我根本不使用它,永远。
@Gia Dang 的回答是最简单的,但我没有继承UIView
,只有UIViewController
,所以我的电话略有不同。另外,由于我不知道实际调用的开销resignFirstResponder
,我更喜欢先检查。这是更多的代码,但由于所有这些都是在主线程上完成的(这会减慢 UI 的速度),我宁愿先检查一下。
@implementation MyController : UIViewController {
@private
UISearchController *_uiSearchController;
}
- (void)viewDidLoad {
// add tap on view to resign the responder if we're in the middle of typing in the search
UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(closeKeyboardIfNeeded)];
[self.view addGestureRecognizer:tapGestureRecognizer];
}
- (void)closeKeyboardIfNeeded {
if (![_uiSearchController.searchBar isFirstResponder]) {
return;
}
[_uiSearchController.searchBar resignFirstResponder];
}
@end
至于其他答案,请注意不断重新创建对象。无论是创建本身还是通过ARC进行垃圾收集,总会有性能损失,这些事情会减慢您的主线程。根据您在主线程上所做的事情,它可能会对性能产生重大影响。