【问题标题】:Dismissing keyboard from UISearchBar when the X button is tapped点击 X 按钮时从 UISearchBar 关闭键盘
【发布时间】:2011-05-10 13:55:49
【问题描述】:

我正在使用 UISearchBar(但不是通常结合使用的 SearchDisplayController),我想在您点击“X”按钮时关闭键盘。

我已经关注TomSwift's suggestion,当点击“X”时被调用,效果很好。但是从文本字段中退出第一响应者并在 UISearchBar 实例中调用,两者都使用resignFirstResponder,不会使键盘消失。

当用户点击 X 按钮时,有没有办法摆脱键盘?

这是我为获得“清除”通知所做的工作:

- (void)viewDidLoad:
{
    for (UIView* v in searchBar.subviews)
    {
        if ( [v isKindOfClass: [UITextField class]] )
        {
            UITextField *tf = (UITextField *)v;
            tf.delegate = self;
            break;
        }
    }    
}

然后我有我的类设置来实现 UISearchBarDelegate 和 UITextFieldDelegate。

让该类充当文本字段委托让我可以得到这个调用:

- (BOOL)textFieldShouldClear:(UITextField *)textField
{
     [textField resignFirstResponder];
     [self.searchBar resignFirstResponder];
     return YES;
}

我已经尝试了我能想到的一切。我要尝试的最后一件事是找到一种方法来发出 UISearchDelegate 将在我的 Controller 类上调用的“searchBarCancelButtonClicked”,但我不确定如何做到这一点,因为 UISearchBar 似乎没有任何直接的方法来用这个名字调用。

【问题讨论】:

  • 您能简要解释一下您是如何让 TomSwift 的建议发挥作用的吗?我无法让它在我的实现中工作。
  • 修改了问题以显示我让该类充当 TextField 委托。

标签: iphone uitextfield uisearchbar


【解决方案1】:

汤姆斯的回答让我思考。如果用户点击清除按钮时搜索栏还不是firstResponder,我们可以等到它是,然后让它resignFirstResponder;即沿着:

- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
{
  [self performFilteringBySearchText: searchText]; // or whatever

  // The user clicked the [X] button or otherwise cleared the text.
  if([searchText length] == 0) {
    [searchBar performSelector: @selector(resignFirstResponder) 
                    withObject: nil 
                    afterDelay: 0.1];
  }
}

像一个魅力,比汤姆的恕我直言不那么老套。

【讨论】:

  • 酱汁真棒!一个反直觉的解决方案,但我仍然大声而自豪地使用它。谢谢
  • 使用 GCD:dispatch_async(dispatch_get_main_queue(), ^(void){ [self.searchBar resignFirstResponder]; });
  • 当用户点击删除按钮时会发生什么?在这种情况下,searchText 的长度为 0
  • @RodrigoGonzalez 老实说,我不知道删除时会发生什么。我认为在这种情况下应该清除搜索文本,并且键盘消失。这不是每个人都想要的吗?
  • 虽然 searchBar.endEditing(true) 适用于完成/搜索按钮和取消按钮但不适用于 (X),但我很困惑。为什么 ?任何人
【解决方案2】:

这行得通:

[searchBar performSelector:@selector(resignFirstResponder) withObject:nil afterDelay:0.1];

【讨论】:

    【解决方案3】:

    为 SWIFT 3 更新:

    假设用户在搜索字段中输入了一个字符串并单击 x,以下代码可以在按下 x 时隐藏键盘

    `

    func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) 
    {
                if searchBar.text == nil || searchBar.text == ""
                {
                    searchBar.perform(#selector(self.resignFirstResponder), with: nil, afterDelay: 0.1)
                }
     }
    

    `

    【讨论】:

      【解决方案4】:

      Swift 2 版本:

      func searchBar(searchBar: UISearchBar, textDidChange searchText: String) {
              // The user clicked the [X] button or otherwise cleared the text.
              if (searchText.characters.count == 0) {
                  searchBar.performSelector("resignFirstResponder", withObject: nil, afterDelay: 0.1)
              }
          }
      

      【讨论】:

        【解决方案5】:

        更新:

        嗯,这完全是一个技巧,但我能够让它工作。基本上,代码调用取消按钮的处理程序。为了让它工作,我不得不延迟调用选择器,我不确定为什么会这样。另外,我必须为取消按钮编写一个访问器,就像您为文本字段所做的那样。

        再一次,这完全是一个黑客行为。我不确定自己会在应用程序中执行此操作。

        // this in the context of the search bar
        - (UIButton*) cancelButton
        {
            for (UIView* v in self.subviews)
            {
                if ( [v isKindOfClass: [UIButton class]] )
                    return (UIButton*)v;
            }
        
            return nil;
        }
        
        // this is the textField delegate callback
        - (BOOL)textFieldShouldClear:(UITextField *)textField
        {
            [textField resignFirstResponder];
        
            UIButton* cb = _searchBar.cancelButton;
        
            NSObject* target = [[cb allTargets] anyObject];
        
            NSArray* actions = [cb actionsForTarget: target forControlEvent:UIControlEventTouchUpInside];
        
            NSString* selectorName = [actions  objectAtIndex:0];
        
            SEL selector = NSSelectorFromString( selectorName );
        
            [target performSelector: selector withObject: cb afterDelay: 0.1];
        
            return YES;
        }
        

        原答案:

        如何首先显示清除“X”按钮?在我的测试用例中,我没有看到它显示...

        尝试在 searchBar 而不是 textField 上执行 resignFirstResponder。

        【讨论】:

        • 我用 Interface Builder 添加了 UISearchBar,当我在搜索栏文本字段中输入一个字符后,X 按钮会自动显示。我尝试退出 searchBar(存储在 Controller 类中)和文本字段。没有运气
        • 好吧,是的,我是愚蠢的。我得到了它的工作。不知道为什么它还没有被解雇。
        • 哦,似乎是延迟造成的。通过所有的黑客攻击,我决定尝试使 SDK 短路很痛苦,并添加了取消按钮。我必须按照 SDK 的意图去做。
        【解决方案6】:

        您可以点击取消按钮作为resignFirstResponder。

        - (void)searchBarTextDidEndEditing:(UISearchBar *)searchBar
        
        {
        
            SearchBar.showsCancelButton =NO;
        
        }
        
        
        - (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar
        {
        
            [SearchBar resignFirstResponder];
        
        
        }
        

        【讨论】:

        • 但是如果你想在 x 按钮点击时这样做,那么你必须拿一个按钮并将 x 之类的图像添加到它。然后点击这个按钮你可以退出 FirstResponder跨度>
        • 这不是他想要的。他想在点击明文按钮时移除键盘。
        • 是的 Tozer 我知道他在找什么,所以请看下面我给出的评论。他需要用自己的按钮来代替清除按钮。
        • 根本没有取消按钮 - 只有 X 按钮的清除操作,我不想添加任何其他按钮。
        • 在搜索栏里有可以隐藏或显示的取消按钮和清除按钮。
        【解决方案7】:

        我在上一个问题中发现了这个:

        UISearchbar clearButton forces the keyboard to appear

        它应该做你想做的事。

        【讨论】:

        • 我尝试完全按照建议进行操作,但键盘仍然打开。
        【解决方案8】:

        尽量避免

        - (BOOL)searchBarShouldEndEditing:(UISearchBar *)searchBar
        

        您的代码中的方法我们可以解决这个问题

        【讨论】:

          【解决方案9】:

          我结合了@radiospiel 的答案和@Tozar linked 的答案:

          @interface SearchViewController : UIViewController <UISearchBarDelegate> {
              // all of our ivar declarations go here...
              BOOL shouldBeginEditing;
              ....
          }
          
          ...
          @end
          
          @implementation SearchViewController
          ...
          - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
              if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) {
                  ...
                  shouldBeginEditing = YES;
              }
          }
          ...
          
          - (void) searchBar:(UISearchBar *)theSearchBar textDidChange:(NSString *)searchText {
              // TODO - dynamically update the search results here, if we choose to do that.
          
              if (![searchBar isFirstResponder]) {
                  // The user clicked the [X] button while the keyboard was hidden
                  shouldBeginEditing = NO;
              }
              else if ([searchText length] == 0) {
                  // The user clicked the [X] button or otherwise cleared the text.
                  [theSearchBar performSelector: @selector(resignFirstResponder)
                                  withObject: nil
                                  afterDelay: 0.1];
              }
          }
          
          - (BOOL)searchBarShouldBeginEditing:(UISearchBar *)bar {
              // reset the shouldBeginEditing BOOL ivar to YES, but first take its value and use it to return it from the method call
              BOOL boolToReturn = shouldBeginEditing;
              shouldBeginEditing = YES;
              return boolToReturn;
          }
          @end
          

          【讨论】:

            【解决方案10】:

            不应该在主线程上进行 UI 更改,而不是使用 performselector:WithObject:afterDelay:

            - (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
            {
                if (searchText.length == 0) {
                    [searchBar performSelectorOnMainThread:@selector(resignFirstResponder) withObject:nil waitUntilDone:NO];
                }
            }
            

            【讨论】:

              【解决方案11】:

              编辑: 实际上,下面的代码破坏了连接到 UISearchBar 的委托。只需继承 UISearchBar 并覆盖 UITextField Delegate 方法。

              ============================

              我必须这样做才能访问 UITextView

              for (UIButton* v in [self.searchBar.subviews[0] subviews])
              {
                  if ( [v isKindOfClass: [UITextField class]] )
                  {
                      UITextField *tf = (UITextField *)v;
                      tf.delegate = self;
                      break;
                  }
              }
              

              【讨论】:

                【解决方案12】:

                感谢 Maxhs 的原始答案: 这是 swift 2.2 版本: 对我来说像魅力一样工作

                if searchBar.text == "" {
                                dispatch_async(dispatch_get_main_queue(), { 
                                    self.searchBar.resignFirstResponder()
                                })
                            }
                

                【讨论】:

                  【解决方案13】:

                  明文流的另一种观点(类似于@TomSwift 的答案,但对我来说更清晰且不那么棘手)。另外,我需要在退出搜索栏后隐藏取消按钮,在用户完成搜索之前实现实时搜索(在每个符号之后)和覆盖表格。

                  //self.searchHoverView can cover table view
                  //performSearchWithSearchBar: method for performing search
                  
                  #pragma mark - UISearchBarDelegate
                  
                  - (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar {
                      [searchBar setShowsCancelButton:YES animated:YES];
                      self.searchHoverView.hidden = NO;
                  }
                  
                  - (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText {
                      if (searchText.length) {
                          [self performSearchWithSearchBar:searchBar];
                      } else {
                          UIButton *button;
                          for (UIView *subView in [searchBar subviews]) {
                              for (UIView *view in [subView subviews]) {
                                  if ([view isKindOfClass:[UIButton class]]) {
                                      button = (UIButton *)view;
                                      break;
                                  }
                              }
                          }
                  
                          if (button) {
                              dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                                  [button sendActionsForControlEvents:UIControlEventTouchUpInside];
                              });
                          }
                      }
                  }
                  
                  - (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar {
                      self.searchBar.text = nil;
                  
                      [self.searchBar setShowsCancelButton:NO animated:YES];
                      [self.searchBar resignFirstResponder];
                  
                      self.searchHoverView.hidden = YES;
                  }
                  

                  【讨论】:

                    【解决方案14】:

                    当您单击“x”按钮时,搜索栏文本字段中的字符串将变为空字符集合。

                    检查集合的长度有助于检测“x”按钮何时被点击。

                    我遇到了类似的问题,这个解决方案对我有用:

                    func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
                        //let searchText = searchText.trimmingCharacters(in: .whitespaces)
                        if searchText.isEmpty{
                            DispatchQueue.main.async { [weak self] in
                                guard let self = self else{ return }
                                self.searchBar.resignFirstResponder()
                            }
                        }
                    }
                    

                    【讨论】:

                      猜你喜欢
                      • 1970-01-01
                      • 2014-05-21
                      • 1970-01-01
                      • 2011-09-15
                      • 2014-11-24
                      • 1970-01-01
                      • 2020-07-29
                      • 2018-07-24
                      • 1970-01-01
                      相关资源
                      最近更新 更多