3

当您点击搜索文本框下方和键盘上方时,有谁知道如何从 UISearchBar 中取消(退出 First Responder)?任何人都可以帮助发布一些代码来处理这个问题吗?

谢谢

4

6 回答 6

12

在(UISearchbar 的)父视图中添加点击手势

[self addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:searchBar action:@selector(resignFirstResponder)]];
于 2012-09-15T02:08:16.770 回答
3

我通过使用 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 覆盖了视图的暴露区域,因此我将手势识别器而不是视图控制器的主视图附加到它,从而隔离了手势将响应的区域。

于 2011-04-06T21:22:20.467 回答
2

我从iphonedevbook获得的另一个想法,示例代码项目 04,是使用一个位于所有其他控件后面的大透明按钮,如果被点击,它只会让所有第一响应者辞职。即,如果用户在没有更重要的控制的地方点击——这是直观的行为——搜索栏和键盘就会消失。

于 2009-08-18T12:58:59.833 回答
2

我最终使用了 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;
    }
}
于 2011-06-29T18:09:55.453 回答
0

首先,您需要对搜索栏的引用。假设您的控制器对象有一个对象引用 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 定义视图和控制器?如果是这样,我建议你学习如何不使用它——一旦你掌握了我们在这里讨论的那种技巧,它就变成了障碍而不是帮助——我根本不使用它,永远。

于 2009-08-17T16:10:11.267 回答
0

@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进行垃圾收集,总会有性能损失,这些事情会减慢您的主线程。根据您在主线程上所做的事情,它可能会对性能产生重大影响。

于 2016-03-06T05:48:10.747 回答