iOS -当触摸到UITextField之外时,键盘消失

我想知道如何使键盘消失时,用户触摸UITextField之外。

276401 次浏览

发送消息resignFirstResponder的文本文件,把它放在那里。请请看这篇文章获取更多信息。

你需要添加一个UITapGestureRecogniser并将其分配给视图,然后在它的选择器上调用UITextField上的resign first responder。

代码:

在viewDidLoad

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


[self.view addGestureRecognizer:tap];

在dismissKeyboard:

-(void)dismissKeyboard
{
[aTextField resignFirstResponder];
}

(其中aTextField是负责键盘的文本字段)

斯威夫特3版本看起来像这样

let tapGesture = UITapGestureRecognizer(target: self, action: #selector(self.dismissKeyboard (_:)))
self.view.addGestureRecognizer(tapGesture)

对于dismissKeyboard

@objc func dismissKeyboard (_ sender: UITapGestureRecognizer) {
aTextField.resignFirstResponder()
}

最好让你的UIView成为UIControl的一个实例(在接口构建器中),然后将它们的TouchUpInside事件连接到dismissKeyboard方法。这个IBAction方法看起来像:

- (IBAction)dismissKeyboard:(id)sender {
[aTextBox resignFirstResponder];
}

这个怎么样:我知道这是一个老帖子。它可能会帮助某些人:)

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
NSArray *subviews = [self.view subviews];
for (id objects in subviews) {
if ([objects isKindOfClass:[UITextField class]]) {
UITextField *theTextField = objects;
if ([objects isFirstResponder]) {
[theTextField resignFirstResponder];
}
}
}
}

我认为最简单(最好)的方法是子类化你的全局视图,并使用hitTest:withEvent方法来监听任何触摸。键盘上的触摸没有被注册,所以只有当你在其他地方触摸滚动/刷卡/捏……,然后调用[self endEditing:YES]时,才会调用hitTest:withEvent。

这比使用touchesBegan更好,因为如果单击视图顶部的按钮,touchesBegan不会被调用。它比不能识别滚动手势的UITapGestureRecognizer更好。它也比使用暗屏更好,因为在复杂和动态的用户界面中,你不能到处都放暗屏。此外,它不会阻止其他操作,你不需要点击两次来选择外面的按钮(就像在UIPopover的情况下)。

此外,它比调用[textField resignFirstResponder]更好,因为屏幕上可能有许多文本字段,所以这对所有文本字段都有效。

我发现有些人在使用UITapGestureRecognizer方法时遇到了问题。我在保持现有按钮点击行为不变的情况下完成这一功能的最简单方法是只添加一行到@Jensen2k的答案:

[tap setCancelsTouchesInView:NO];

这使得我现有的按钮仍然可以工作,而不需要使用@Dmitry Sitnikov的方法。

在这里阅读有关property的信息(搜索CancelsTouchesInView): UIGestureRecognizer类引用

我不确定它将如何与滚动条一起工作,因为我看到有些人有问题,但希望其他人可能会遇到与我相同的情况。

看看这个,这是最简单的方法,

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
[self.view endEditing:YES];// this will do the trick
}

这个库将处理包括滚动条自动滚动,点击空间隐藏键盘等…

https://github.com/michaeltyson/TPKeyboardAvoiding

只是在这里添加我的版本如何在外部触摸时取消键盘。

viewDidLoad:

UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleSingleTap:)];
[self.view addGestureRecognizer:singleTap];

在任何地方:

-(void)handleSingleTap:(UITapGestureRecognizer *)sender{
[textFieldName resignFirstResponder];
puts("Dismissed the keyboard");
}

我拼凑了几个答案。

使用在viewDidLoad:期间初始化的ivar

UIGestureRecognizer *tapper;


- (void)viewDidLoad
{
[super viewDidLoad];
tapper = [[UITapGestureRecognizer alloc]
initWithTarget:self action:@selector(handleSingleTap:)];
tapper.cancelsTouchesInView = NO;
[self.view addGestureRecognizer:tapper];
}

删除当前正在编辑的内容:

- (void)handleSingleTap:(UITapGestureRecognizer *) sender
{
[self.view endEditing:YES];
}

如果我没猜错的话,你想要辞职键盘,在textfield之外点击,但你没有你的textfield的引用。

试试这个;

  • 取全局textField,让我们称之为reftextField
  • 现在在textFieldDidBeginEditing中设置引用文本字段为

    - (void) textFieldDidBeginEditing:(UITextField *)textField{
    reftextField = textField;
    }
    
  • Now you can happily use on any button clock, (adding a transparent button on begin editing recomended)

    - (void)dismissKeyboard {
    [reftextField resignFirstResponder];
    }
    
  • Or for resigning done button try this.

    //for resigning on done button
    - (BOOL) textFieldShouldReturn:(UITextField *)textField{
    [textField resignFirstResponder];
    return YES;
    }
    

这是

在本例中,aTextField是唯一的UITextField....如果有其他的uitextview,还有一点点事情要做。

// YourViewController.h
// ...
@interface YourViewController : UIViewController /* some subclass of UIViewController */ <UITextFieldDelegate> // <-- add this protocol
// ...
@end


// YourViewController.m


@interface YourViewController ()
@property (nonatomic, strong, readonly) UITapGestureRecognizer *singleTapRecognizer;
@end
// ...


@implementation
@synthesize singleTapRecognizer = _singleTapRecognizer;
// ...


- (void)viewDidLoad
{
[super viewDidLoad];
// your other init code here
[self.view addGestureRecognizer:self.singleTapRecognizer];


{


- (UITapGestureRecognizer *)singleTapRecognizer
{
if (nil == _singleTapRecognizer) {
_singleTapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(singleTapToDismissKeyboard:)];
_singleTapRecognizer.cancelsTouchesInView = NO; // absolutely required, otherwise "tap" eats events.
}
return _singleTapRecognizer;
}


// Something inside this VC's view was tapped (except the navbar/toolbar)
- (void)singleTapToDismissKeyboard:(UITapGestureRecognizer *)sender
{
NSLog(@"singleTap");
[self hideKeyboard:sender];
}


// When the "Return" key is pressed on the on-screen keyboard, hide the keyboard.
// for protocol UITextFieldDelegate
- (BOOL)textFieldShouldReturn:(UITextField*)textField
{
NSLog(@"Return pressed");
[self hideKeyboard:textField];
return YES;
}


- (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.
[aTextField resignFirstResponder];
NSLog(@"keyboard hidden");
}

我试了这里的很多回答,都不太走运。我的点击手势识别器总是导致我的UIButtons在点击时不响应,即使我将手势识别器的cancelsTouchesInView属性设置为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执行的事情…

在我的新发展中,我以巴里为例。它工作得很好!但我不得不包括一个轻微的变化,要求解散键盘,只有文本字段被编辑。

所以,我在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];
}

这里有很多关于使用UITapGestureRecognizer的很好的答案——所有这些答案都破坏了UITextField的clear (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);
}

这不是最可靠的解决方案,但对我来说很管用。

- (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];


}

如果视图完全嵌入在UIScrollView中,那么你可以使用以下方法:

tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeOnDrag;
tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeInteractive;

前者会在表格视图滚动时将键盘动画化,后者会像股票消息应用程序一样隐藏键盘。

注意,这些都可以在iOS 7.0或更高版本上使用。

这是一个很好的通用解决方案:

objective - c:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[self.view endEditing:YES];
}

迅速:

override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
self.view.endEditing(true)
}

基于@icodebuster解决方案:https://stackoverflow.com/a/18756253/417652

Swift版本,它与其他元素(如UIButton或另一个UITextField)组合使用:

override func viewDidLoad() {
super.viewDidLoad()


let tapper = UITapGestureRecognizer(target: self, action:#selector(endEditing))
tapper.cancelsTouchesInView = false
view.addGestureRecognizer(tapper)
}

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

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

只是使用这段代码在您的.m文件,它将辞职的文本字段,当用户点击文本字段之外。

 -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
[textfield resignFirstResponder];
}
override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
super.view.endEditing(true)
super.touchesBegan(touches, withEvent: event)
}

objective - c:

在你的ViewController.m文件中添加以下代码:

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[self.view endEditing:YES];
}

迅速:

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
view.endEditing(true)
}

你可以使用UITapGestureRecongnizer方法通过点击UITextField之外的按钮来取消键盘。通过使用这个方法,每当用户在UITextField之外点击时,键盘就会被驳回。下面是使用它的代码片段。

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


[self.view addGestureRecognizer:tap];




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


}

你可以在XCode 6及以上版本中使用Storyboard:


创建隐藏键盘的动作

将这个添加到ViewController使用的类的头文件中:

@interface TimeDelayViewController : UIViewController <UITextFieldDelegate>


- (IBAction)dissmissKeyboardOnTap:(id)sender;


@end

然后将这个添加到同一个ViewController的实现文件中:

- (IBAction)dissmissKeyboardOnTap:(id)sender{
[[self view]endEditing:YES];
}

这将是你的故事板场景(即ViewController)的“Received Actions”之一:

enter image description here


将操作连接到用户事件

现在,您需要将这个动作与触碰键盘的用户手势连接起来。

重要-你需要将包含在故事板中的“UIView”转换为UIControl,所以它可以接收事件。从视图控制器场景层次结构中选择视图:

enter image description here

...并更改其类:

enter image description here

现在从你的场景的“received action”旁边的小圆圈拖到你的场景的“空”部分(实际上你是在把“received action”拖到UIControl上)。你会看到一个事件的选择,你可以连接你的行动:

enter image description here

选择“touch up inside”选项。现在,您已经将创建的IBAction连接到触碰键盘的用户操作。当用户点击键盘时,它将被隐藏。

(注意:要将动作与事件挂钩,你也可以从接收到的动作直接拖到视图控制器层次结构中的UIControl上。它在层次结构中显示为“Control”。)

你可以为UiView创建类别并重写touchesBegan方法,如下所示。

这对我来说很好。这是一种集中解决这一问题的方法。

#import "UIView+Keyboard.h"
@implementation UIView(Keyboard)


- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[self.window endEditing:true];
[super touchesBegan:touches withEvent:event];
}
@end

所以我只需要解决这个问题,之前的答案都不适用。我的情况:一个UISearchBar,加上屏幕上的一些其他控件。我想在搜索栏外点击一下以解除键盘,但传播到任何其他控件。当键盘被隐藏时,我希望所有的控制都能工作。

我做了什么:

1)在我的视图控制器中实现一个自定义触摸处理程序。

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?)
{
if searchBar.isFirstResponder()
{
// This causes the first responder, whoever it is, to resign first responder, and hide the keyboard.
// We also "eat" the touch here and not allow it to propagate further.
view.endEditing(true)
}
else
{
// OK to propagate the touch
super.touchesBegan(touches, withEvent: event)
}
}

2)添加了一对委托方法(我的是UISearchBar,但也有类似的UITextField)。下面代码中的controlContainerView是一个UIView,其中有一堆按钮。记住,在父视图上设置userInteractionEnabled会禁用它的所有子视图。

 func searchBarTextDidBeginEditing(searchBar: UISearchBar)
{
controlContainerView.userInteractionEnabled = false
someButton.userInteractionEnabled = false
}


func searchBarTextDidEndEditing(searchBar: UISearchBar)
{
searchBar.resignFirstResponder()


// Done editing: enable the other controls again.


controlContainerView.userInteractionEnabled = false
someButton.userInteractionEnabled = false
}

这一定是通过触摸外部隐藏键盘的最简单方法:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[self.view endEditing:YES];
}

(从当用户点击文本框外的其他区域时,如何解除键盘?)

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


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


}
}

@Jensen2k回答的Swift版本:

let gestureRecognizer : UITapGestureRecognizer = UITapGestureRecognizer.init(target: self, action: "dismissKeyboard")
self.view.addGestureRecognizer(gestureRecognizer)


func dismissKeyboard() {
aTextField.resignFirstResponder()
}

一个衬套

self.view.addTapGesture(UITapGestureRecognizer.init(target: self, action: "endEditing:"))

在这种情况下,可以使用滚动视图并添加到ScrollView中的TextField,我想点击ScrollView和视图,然后解散键盘。为了以防万一,我尝试创建了示例代码。像这样,

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.
}
}

你的故事板看,就像。

enter image description here

  • 在视图中设置文本字段委托

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

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

对于那些在Swift中挣扎的人。这是Jensen2k在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()
}

斯威夫特4

使用这个扩展方法设置你的UIViewController,例如在viewDidLoad中:

override func viewDidLoad() {
super.viewDidLoad()
self.setupHideKeyboardOnTap()
}

键盘将被解散,即使点击NavigationBar

import UIKit
extension UIViewController {
/// Call this once to dismiss open keyboards by tapping anywhere in the view controller
func setupHideKeyboardOnTap() {
self.view.addGestureRecognizer(self.endEditingRecognizer())
self.navigationController?.navigationBar.addGestureRecognizer(self.endEditingRecognizer())
}


/// Dismisses the keyboard from self.view
private func endEditingRecognizer() -> UIGestureRecognizer {
let tap = UITapGestureRecognizer(target: self.view, action: #selector(self.view.endEditing(_:)))
tap.cancelsTouchesInView = false
return tap
}
}

Swift在线软件

view.addGestureRecognizer(UITapGestureRecognizer(target: view, action: #selector(UIView.endEditing(_:))))
在viewDidLoad < p > 斯威夫特4.2 代码如下:

let viewTap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action:#selector(dismissKeyboard))
view.addGestureRecognizer(viewTap)
@objc func dismissKeyboard() {
view.endEditing(true)
}

在swift 5中,你可以使用以下代码来解除文本域外的键盘

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


let tapGesture = UITapGestureRecognizer(target: self, action: #selector(self.dismissKeyboard(_:)))
self.view.addGestureRecognizer(tapGesture)
}


@objc func dismissKeyboard(_ sender: UITapGestureRecognizer) {
self.view.endEditing(true)
}

有一件事很重要……

添加手势识别到视图可以子视图覆盖它。 所以只执行一个动作。 如果你想通过父视图和子视图执行多重识别操作… 你必须使用

 tap.cancelsTouchesInView = false

完整代码如下:

 let tap = UITapGestureRecognizer(target: self, action: #selector(self.superViewClicked))
tap.numberOfTapsRequired = 1
tap.delegate = self
tap.cancelsTouchesInView = false
self.view.addGestureRecognizer(tap)








@objc func superViewClicked(){
        

self.searchTF.resignFirstResponder()
}

在外面点击关闭软键盘的最佳解决方案是什么?

我将解释一个条件:

想想看:你在顶部有UISearchBar, 然后添加头表视图!< / p >

解决方法很简单:

  1. 跟踪软键盘打开或关闭
  2. 添加手势识别头视图
  3. 实现表视图didSelectRowAt的委托

完整的代码:

   var isSoftKeyboardActive = false


override func viewDidLoad() {
    

    

var tap = UITapGestureRecognizer(target: self, action: #selector(self.tableHeaderClick))
tap.numberOfTapsRequired = 1
tap.delegate = self
tap.cancelsTouchesInView = false
self.headerOfTableView.addGestureRecognizer(tap)
    

}
    

override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillDisappear), name: UIResponder.keyboardWillHideNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillAppear), name: UIResponder.keyboardWillShowNotification, object: nil)
}
              

override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
NotificationCenter.default.removeObserver(self)
}
        





func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if isSoftKeyboardActive == true{
               

self.searchTF.resignFirstResponder()
}else{
           

selectedRow = indexPath.row
performSegue(withIdentifier: "segueWebview", sender: self)
               

}
}
    





 

@objc func tableHeaderClick(){
         

self.searchTF.resignFirstResponder()
    

}
    

    

    

@objc func keyboardWillAppear() {


        

isSoftKeyboardActive = true
}


@objc func keyboardWillDisappear() {
        

isSoftKeyboardActive = false
        

}
 

它是如何工作的:

  1. 如果软键盘是打开的,用户点击头软键盘关闭
  2. 如果软键盘打开,用户点击单元格,键盘关闭,不执行单元格点击

藏品视图:

// the keyboard follows the dragging touch off screen, and may be pulled upward again to cancel the dismiss
collectionView.keyboardDismissMode = .interactive
// dismisses the keyboard when a drag begins
collectionView.keyboardDismissMode = .onDrag