当用户点击视图时,取消UISearchBar

时间:2009-08-17 14:38:48

标签: iphone objective-c uisearchbar

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

由于

6 个答案:

答案 0 :(得分:12)

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

[self addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:searchBar action:@selector(resignFirstResponder)]];

答案 1 :(得分: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,取消,范围或结果按钮,他们将无法正确回应。

在我的特定场景中,我有一个UITableView覆盖了视图的暴露区域,因此我将手势识别器连接到它而不是视图控制器主视图,隔离了手势将响应的区域。

答案 2 :(得分:2)

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

答案 3 :(得分: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;
    }
}

答案 4 :(得分:0)

首先,您需要对搜索栏的引用。假设您的控制器对象具有对象引用UISearchBar * theSearchBar,并在创建UISearchBar对象时分配它。

接下来,您需要检测是否已触摸包含视图。触摸的视图“知道”,但您需要将该信息提供给控制器。可悲的是,Apple没有提供一种简单的方法来做到这一点,但也不是那么难。

我的解决方案是替换UIViewController对象通常使用UIControl创建的标准UIView,然后让UIViewController响应触摸事件。

<强> MainController.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];
    }
}

<强> MainController.h

@interface MainController : UIViewController
{
    UISearchBar *theSearchBar;
}

澄清:

只有一个对象 - 让我们调用类MainController - 它是UIViewController的子类。上面列出的所有方法都在MainController中实现。 theSearchBar在.h文件中声明为UISearchBar *。

您是否使用Interface Builder定义视图和控制器?如果是这样的话,我建议你学习如何不使用它 - 一旦你进入我们在这里讨论的那种技巧,它就会成为一种障碍而不是一种帮助 - 我根本就不使用它。 / p>

答案 5 :(得分:0)

@Gia Dang的答案是最简单的,但我不是UIView的子类,只是UIViewController,所以我的调用略有不同。此外,由于我不知道实际调用resignFirstResponder的开销,我更愿意先检查。这是更多的代码,但由于所有这些都是在主线程上完成的(这可能会减慢用户界面),我宁愿先检查一下。

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