iOS - 点击UITextField外部时收起键盘

492
我想知道如何让用户点击UITextField之外的区域时,键盘自动消失。

8
Dmitry给出了正确的答案。这不是一个手势问题,而是将第一响应者放弃的问题。Dmitry的答案也是Mark、Nutting和LeMarche在《Beginning iOS 4 Development》(http://www.amazon.com/dp/143023024X)第4章第83页中推荐的解决方案。 - jww
38个回答

3

这里有很多关于使用UITapGestureRecognizer的好答案,但所有这些答案都会破坏UITextField的清除(X)按钮。解决方法是通过其代理来禁止手势识别器:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
    BOOL touchViewIsButton = [touch.view isKindOfClass:[UIButton class]];
    BOOL touchSuperviewIsTextField = [[touch.view superview] isKindOfClass:[UITextField class]];
    return !(touchViewIsButton && touchSuperviewIsTextField);
}

虽然这不是最完美的解决方案,但对我而言是有效的。


如果我在同一文本框中点击,所有上述操作都会失败。 即使该文本框是我的响应者,它也会被取消响应。并且在单击文本框内的清除按钮时,它还会关闭键盘。 - Mrug
我会简化它,只需对按钮进行测试:return !touchViewIsButton。我猜其他需要关闭键盘的按钮应该在它们的操作中执行此操作。此外,在键盘消失时布局更改可能不会调用TouchUpInside。 - Marián Černý

2

最简单、最短的方法之一是将此代码添加到viewDidLoad中。

[self.view addGestureRecognizer:[[UITapGestureRecognizer alloc]
                                     initWithTarget:self.view
                                     action:@selector(endEditing:)]];

2
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {

    if let touch = touches.first{
     view.endEditing(true)

     }
}

2

我试过这里的很多回复,但都没成功。即使我将手势识别器的属性设置为NO,我的轻拍手势识别器仍然会导致我的无法响应点击。

最终解决方案如下:

创建一个ivar:

UITapGestureRecognizer *_keyboardDismissGestureRecognizer;

当文本字段开始编辑时,设置手势识别器:

- (void) textFieldDidBeginEditing:(UITextField *)textField
{
    if(_keyboardDismissGestureRecognizer == nil)
    {
        _keyboardDismissGestureRecognizer = [[[UITapGestureRecognizer alloc]
                                       initWithTarget:self
                                       action:@selector(dismissKeyboard)] autorelease];
        _keyboardDismissGestureRecognizer.cancelsTouchesInView = NO;

        [self.view addGestureRecognizer:_keyboardDismissGestureRecognizer];
    }
}

那么关键在于如何设置dismissKeyboard方法:

- (void) dismissKeyboard
{
    [self performSelector:@selector(dismissKeyboardSelector) withObject:nil afterDelay:0.01];
}

- (void) dismissKeyboardSelector
{
    [self.view endEditing:YES];

    [self.view removeGestureRecognizer:_keyboardDismissGestureRecognizer];
    _keyboardDismissGestureRecognizer = nil;
}

我想这只是关于将dismissKeyboardSelector的执行从触摸处理的执行堆栈中移除的某种方法...


2

我在我的新开发中使用了Barry的例子。它非常好用!但是我必须包含一个稍微的更改,仅为正在编辑的文本字段取消键盘。

所以,我添加了以下内容到Barry的例子中:

- (void) textFieldDidBeginEditing:(UITextField *)textField
{
    _textBeingEdited = textField;
}
-(void) textFieldDidEndEditing:(UITextField *)textField
{
    _textBeingEdited = nil;
}

另外,我将hideKeyboard方法更改如下:

- (IBAction)hideKeyboard:(id)sender
{
    // Just call resignFirstResponder on all UITextFields and UITextViews in this VC
    // Why? Because it works and checking which one was last active gets messy.
    //UITextField * tf = (UITextField *) sender;
    [_textBeingEdited resignFirstResponder];
}

1
  • Set text fields delegate in view did load:

    override func viewDidLoad() 
    {
      super.viewDidLoad()
      self.userText.delegate = self
    }
    
  • Add this Function:

    func textFieldShouldReturn(userText: UITextField!) -> Bool 
    {
     userText.resignFirstResponder()
     return true;
    }
    

1

对于那些在Swift中遇到困难的人。这是Jensen2k在Swift中的被接受的答案。

Swift 2.3

    override func viewDidLoad() {
        //.....

        let viewTapGestureRec = UITapGestureRecognizer(target: self, action: #selector(handleViewTap(_:)))
        //this line is important
        viewTapGestureRec.cancelsTouchesInView = false
        self.view.addGestureRecognizer(viewTapGestureRec)

         //.....
    }

    func handleViewTap(recognizer: UIGestureRecognizer) {
        myTextField.resignFirstResponder()
    }

1
在这种情况下,可以使用 ScrollView 并将其添加到 ScrollView 中的 TextField,我想要点击 ScrollView 和 View,然后隐藏键盘。我尝试创建示例代码以防万一。像这样,
import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var scrollView: UIScrollView!
    @IBOutlet weak var textField: UITextField!

    override func viewDidLoad() {
        super.viewDidLoad()

        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(ViewController.tap(_:)))
        view.addGestureRecognizer(tapGesture)
        // Do any additional setup after loading the view, typically from a nib.
    }
    func tap(gesture: UITapGestureRecognizer) {
        textField.resignFirstResponder()
    }
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}

你的Storyboard看起来就像这样。

enter image description here


1
- (void)viewDidLoad
{
    [super viewDidLoad]; 

UITapGestureRecognizer *singleTapGestureRecognizer = [[UITapGestureRecognizer alloc]
                                                          initWithTarget:self
                                                          action:@selector(handleSingleTap:)];
    [singleTapGestureRecognizer setNumberOfTapsRequired:1];
    [singleTapGestureRecognizer requireGestureRecognizerToFail:singleTapGestureRecognizer];

    [self.view addGestureRecognizer:singleTapGestureRecognizer];
}

- (void)handleSingleTap:(UITapGestureRecognizer *)recognizer
{
    [self.view endEditing:YES];
    [textField resignFirstResponder];
    [scrollView setContentOffset:CGPointMake(0, -40) animated:YES];

}

1

您可以使用UITapGestureRecongnizer方法,在UITextField外部单击以关闭键盘。通过使用此方法,每当用户单击UITextField外部时,键盘都会关闭。以下是使用它的代码片段。

 UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]
                                   initWithTarget:self
                                   action:@selector(dismissk)];

    [self.view addGestureRecognizer:tap];


//Method
- (void) dismissk
{
    [abctextfield resignFirstResponder];
    [deftextfield resignFirstResponder];

}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接