简体   繁体   English

通过触摸 UITableView 的背景关闭键盘

[英]Dismiss keyboard by touching background of UITableView

I have a UITableView with UITextField s as cells.我有一个UITableViewUITextField作为单元格。 I would like to dismiss the keyboard when the background of the UITableView is touched.当触摸UITableView的背景时,我想关闭键盘。 I'm trying to do this by creating a UIButton the size of the UITableView and placing it behind the UITableView .我试图通过创建一个UIButton大小的UITableView并将其放在UITableView后面来做到这一点。 The only problem is the UIButton is catching all the touches even when the touch is on the UITableView.唯一的问题是UIButton会捕捉所有的触摸,即使触摸是在 UITableView 上。 What am I doing wrong?我究竟做错了什么?

Thanks!谢谢!

This is easily done by creating a UITapGestureRecognizer object (by default this will detect a "gesture" on a single tap so no further customization is required), specifying a target/action for when the gesture is fired, and then attaching the gesture recognizer object to your table view.这很容易通过创建一个UITapGestureRecognizer对象(默认情况下,这将在单击时检测“手势”,因此不需要进一步自定义),指定手势触发时的目标/动作,然后附加手势识别器对象来轻松完成到您的表视图。

Eg Perhaps in your viewDidLoad method:例如,也许在您的viewDidLoad方法中:

UITapGestureRecognizer *gestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(hideKeyboard)];
[self.tableView addGestureRecognizer:gestureRecognizer];

And the hideKeyboard method might look like this: hideKeyboard方法可能如下所示:

- (void) hideKeyboard {
    [textField1 resignFirstResponder];
    [textField2 resignFirstResponder];
    ...
    ...
}

Note that the gesture is not fired when touching inside a UITextField object.请注意,触摸UITextField对象内部时不会触发手势。 It is fired though on the UITableView background, footer view, header view and on UILabels inside cells etc.它在UITableView背景、页脚视图、页眉视图和单元格内的UILabels等上被触发。

如果您设置,则 UITapGestureRecognizer 解决方案适用于表格单元格选择:

gestureRecognizer.cancelsTouchesInView = NO;

Here is a best way to do this.这是执行此操作的最佳方法。 Just do this就这样做

[self.view endEditing:YES];

or或者

[[self.tableView superView] endEditing:YES];

You can also do it from Storyboard:您也可以从 Storyboard 执行此操作: 在此处输入图片说明

As UITableView is a subclass of UIScrollView , implementing one delegate method below provides an extremely easy, quick solution.由于UITableViewUIScrollView的子类,因此在下面实现一个委托方法提供了一种非常简单、快速的解决方案。 No need to even involve resignFirstResponder since view hierarchy introspects and finds the current responder and asks it to resign it's responder status.甚至不需要涉及resignFirstResponder因为视图层次结构会内省并找到当前响应者并要求它resignFirstResponder它的响应者状态。

- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
    [self.view endEditing:YES];
}

And remember to add UIScrollViewDelegate to header file.并记住将UIScrollViewDelegate添加到头文件中。

Firstly, listen for scrollViewWillBeginDragging in your UIViewController by adding the UIScrollViewDelegate :首先,通过添加UIScrollViewDelegateUIViewController监听scrollViewWillBeginDragging

In .h file:在 .h 文件中:

@interface MyViewController : UIViewController <UIScrollViewDelegate> 

In .m file:在 .m 文件中:

- (void)scrollViewWillBeginDragging:(UIScrollView *)activeScrollView {

    [self dismissKeyboard];

}

Then listen for other interactions:然后监听其他交互:

- (void)setupKeyboardDismissTaps {

    UISwipeGestureRecognizer *swipeUpGestureRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboard)];
    swipeUpGestureRecognizer.cancelsTouchesInView = NO;
    swipeUpGestureRecognizer.direction = UISwipeGestureRecognizerDirectionUp;
    [self.tableView addGestureRecognizer:swipeUpGestureRecognizer];

    UISwipeGestureRecognizer *swipeDownGestureRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboard)];
    swipeDownGestureRecognizer.cancelsTouchesInView = NO;
    swipeDownGestureRecognizer.direction = UISwipeGestureRecognizerDirectionDown;
    [self.tableView addGestureRecognizer:swipeDownGestureRecognizer];

    UISwipeGestureRecognizer *swipeLeftGestureRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboard)];
    swipeLeftGestureRecognizer.cancelsTouchesInView = NO;
    swipeLeftGestureRecognizer.direction = UISwipeGestureRecognizerDirectionLeft;
    [self.tableView addGestureRecognizer:swipeLeftGestureRecognizer];

    UISwipeGestureRecognizer *swipeRightGestureRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboard)];
    swipeRightGestureRecognizer.cancelsTouchesInView = NO;
    swipeRightGestureRecognizer.direction = UISwipeGestureRecognizerDirectionRight;
    [self.tableView addGestureRecognizer:swipeRightGestureRecognizer];


    UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboard)];
    tapGestureRecognizer.cancelsTouchesInView = NO;
    [self.tableView addGestureRecognizer:tapGestureRecognizer];

}

Then implement dismissKeyboard :然后实现dismissKeyboard

- (void)dismissKeyboard {

    NSLog(@"dismissKeyboard");

    [yourTextFieldPointer resignFirstResponder];

}

And if, like me, you wanted to dismiss the keyboard for a UITextField inside a custom table cell:如果像我一样,您想关闭自定义表格单元格内 UITextField 的键盘:

- (void)dismissKeyboard {

    NSLog(@"dismissKeyboard");

    CustomCellClass *customCell = [tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]];
    [customCell.textFieldInCell resignFirstResponder]; 

}

Hope that helps anyone searching!!希望对搜索的人有所帮助!!

tableView.keyboardDismissMode = .onDrag

Here's the swift version for your coding pleasure:这是您编码乐趣的快速版本:

It adds a tap gesture recognizer then dismisses the keyboard.它添加了一个点击手势识别器,然后关闭键盘。 No outlet for the TextField is required!不需要 TextField 的出口!

override func viewDidLoad() {
    super.viewDidLoad()
    view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: "handleTap:"))
}

func handleTap(sender: UITapGestureRecognizer) {
    if sender.state == .Ended {
        view.endEditing(true)
    }
    sender.cancelsTouchesInView = false
}

There is Swift 3 version without blocking taps on cells. Swift 3 版本不会阻止点击单元格。

In viewDidLoad() method:viewDidLoad()方法中:

let dismissKeyboardGesture = UITapGestureRecognizer(target: self, action: #selector(hideKeyboard))
dismissKeyboardGesture.cancelsTouchesInView = false
tableView.addGestureRecognizer(dismissKeyboardGesture)

And hideKeyboard looks like this: hideKeyboard看起来像这样:

func hideKeyboard() {
    view.endEditing(true)
}

I did it like this:我是这样做的:

Create a method in your TableViewController to deactivate first responder (which would be your TextBox at that point)在您的 TableViewController 中创建一个方法来停用第一响应者(此时将是您的 TextBox)

- (BOOL)findAndResignFirstResonder:(UIView *)stView {
    if (stView.isFirstResponder) {
        [stView resignFirstResponder];
        return YES;     
    }

    for (UIView *subView in stView.subviews) {
        if ([self findAndResignFirstResonder:subView]) {
            return YES;
        }
    }
    return NO;
}

In tableView:didSelectRowAtIndexPath: call the previous method:tableView:didSelectRowAtIndexPath:调用之前的方法:

- (void)tableView:(UITableView *)tableView
                             didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    ...
    [self findAndResignFirstResonder: self.view];
    ...
}

I had a UITableViewController and implementing touchesBegan:withEvent: didn't work for me.我有一个UITableViewController并且实现touchesBegan:withEvent:对我不起作用。

Here's what worked:这是有效的:

Swift:迅速:

override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    view.endEditing(true)
}

Objective-C:目标-C:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    [self.view endEditing:YES];
}

If you are targeting iOS7 you can use one of the following:如果您的目标是 iOS7,您可以使用以下方法之一:

tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeOnDrag;

tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeInteractive;

The former will animate the keyboard off screen when the table view is scrolled and the later will hide the keyboard like the stock Messages app.前者将在滚动表格视图时在屏幕外设置键盘动画,后者将像股票消息应用程序一样隐藏键盘。

Note that these are from UIScrollView , which UITableView inherits from.请注意,这些来自UIScrollViewUITableView继承自。

@interface DismissableUITableView : UITableView {
}
@end

@implementation DismissableUITableView

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

@end

Then make sure that in your Nib file you set the type of your UITableView to DismissableUITableView .....maybe i could have thought of a better name for this class, but you get the point.然后确保在你的 Nib 文件中你将 UITableView 的类型设置为 DismissableUITableView .....也许我可以为这个类想到一个更好的名字,但你明白了。

Try this:尝试这个:

viewDidLoad(){

    let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(dismissKeyboard))

    tableView.addGestureRecognizer(tap)

}
//Calls this function when the tap is recognized.
@objc func dismissKeyboard() {

    //Causes the view (or one of its embedded text fields) to resign the first responder status.
    view.endEditing(true)

}

I had the same problem and here's my solution, it works perfectly for me:我遇到了同样的问题,这是我的解决方案,它非常适合我:

In the view or view controller that you implemented <UITextFieldDelegate>在您实现<UITextFieldDelegate>的视图或视图控制器中

(In my case I have a custom UITableViewCell called TextFieldCell), (就我而言,我有一个名为 TextFieldCell 的自定义UITableViewCell ),

Declare the UITapGestureRecognizer as a property:UITapGestureRecognizer声明为属性:

@interface TextFieldCell : UITableViewCell <UITextFieldDelegate>
{
    UITextField *theTextField;
    UITapGestureRecognizer *gestureRecognizer;
}
@property (nonatomic,retain) UITextField *theTextField;
@property (nonatomic,retain) UITapGestureRecognizer *gestureRecognizer; 

And initialize it in your view/controller:并在您的视图/控制器中初始化它:

self.gestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(closeKeyboard:)];

In the - (void)textFieldDidBeginEditing:(UITextField *)textField method, use superView to move up to your tableView and call addGestureRecognizer :- (void)textFieldDidBeginEditing:(UITextField *)textField方法中,使用superView向上移动到您的 tableView 并调用addGestureRecognizer

[self.superview.superview addGestureRecognizer:gestureRecognizer];

And in the - (void)textFieldDidEndEditing:(UITextField *)textField , just remove the gesture recognizer:- (void)textFieldDidEndEditing:(UITextField *)textField ,只需删除手势识别器:

[self.superview.superview removeGestureRecognizer:gestureRecognizer];

Hope it helps.希望能帮助到你。

I wanted my cell to open the keyboard when any part of the cell was selected and close it if you clicked anywhere off the cell.我希望我的单元格在单元格的任何部分被选中时打开键盘,并在您单击单元格外的任何位置时关闭它。 To open the keyboard:打开键盘:

- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
    [super setSelected:selected animated:animated];
    if (selected)
    {
        [self.textField becomeFirstResponder];
    }
}

(NOTE: I've subclassed the cell but you can easily achieve this in the tableView:didSelectRowAtIndexPath: delegate method of UITableView ) (注意:我已经对单元格进行了子类化,但您可以在tableView:didSelectRowAtIndexPath:委托方法UITableView轻松实现这一点)

Doing this meant that with the top solutions if you clicking on the cell twice the keyboard would shake as, first the gesture recogniser tried to close the keyboard, and second the cell was reselected and tried open the keyboard.这样做意味着使用顶级解决方案,如果您在单元格上单击两次键盘会抖动,首先手势识别器尝试关闭键盘,然后重新选择单元格并尝试打开键盘。

Solution is to check whether the click occurred inside the currently selected cell:解决方法是检查点击是否发生在当前选中的单元格内:

- (void)viewDidLoad
{
    [super viewDidLoad];
    //gesture recognizer to close the keyboard when user taps away
    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self
                                                                          action:@selector(dismissKeyboard:)];
    tap.cancelsTouchesInView = NO;
    [self.tableView addGestureRecognizer:tap];
}

-(void)dismissKeyboard:(UIGestureRecognizer*)tapGestureRecognizer
{
    if (!CGRectContainsPoint([self.tableView cellForRowAtIndexPath:[self.tableView indexPathForSelectedRow]].frame, [tapGestureRecognizer locationInView:self.tableView]))
    {
        [self.view endEditing:YES];
    }
}

I've found a solution that works great.我找到了一个非常有效的解决方案。

Is needed to use the UIGestureRecognizerDelegate and the method – gestureRecognizer:shouldReceiveTouch: .需要使用UIGestureRecognizerDelegate和方法——gestureRecognizer:shouldReceiveTouch:。

Add the gesture recognizer to the TableView as follows:将手势识别器添加到 TableView,如下所示:

UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(hideKeyboard)];
tapGestureRecognizer.cancelsTouchesInView = NO;
tapGestureRecognizer.delegate = self;
[self.suggestedTableView addGestureRecognizer:tapGestureRecognizer];
[tapGestureRecognizer release];

Then, implement the shouldReceiveTouch delegate method to reject touches that are performed in UITableViewCell class.然后,实现shouldReceiveTouch委托方法以拒绝在 UITableViewCell 类中执行的触摸。 The hideKeyboard method only will be called when the touch has been performed outside UITableViewCell class.只有在 UITableViewCell 类之外执行触摸时才会调用hideKeyboard方法。

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
    if([touch.view isKindOfClass:[UITableViewCell class]]) {
        return NO;
    }
    // UITableViewCellContentView => UITableViewCell
    if([touch.view.superview isKindOfClass:[UITableViewCell class]]) {
        return NO;
    }
    // UITableViewCellContentView => UITableViewCellScrollView => UITableViewCell
    if([touch.view.superview.superview isKindOfClass:[UITableViewCell class]]) {
        return NO;
    }
    return YES; // handle the touch
}

- (void) hideKeyboard{
    [textField resignFirstResponder];
}

UITableView is a subclass of UIScrollView. UITableView 是 UIScrollView 的子类。

The way I did it was to listen for a scroll event by the user and then resignFirstResponder.我这样做的方法是监听用户的滚动事件,然后 resignFirstResponder。 Here's the UIScrollViewDelegate method to implement in your code;这是要在您的代码中实现的 UIScrollViewDelegate 方法;

- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView

When approaching these sorts of problems I've found the best way is to research the delegate protocols for each object and those of the parent classes (in this case UITableViewDelegate, UIScrollViewDelegate. The number of events NS objects fires is quite large and comprehensive. It's also easier implementing a protocol then subclassing anything.在解决这类问题时,我发现最好的方法是研究每个对象和父类的委托协议(在这种情况下为 UITableViewDelegate、UIScrollViewDelegate。NS 对象触发的事件数量非常大且全面。它是也更容易实现协议然后子类化任何东西。

UITableView has a handy backgroundView property, with which I achieved this behavior without messing with cell selection, as shown below in Swift: UITableView有一个方便的backgroundView属性,我用它实现了这种行为,而不会干扰单元格选择,如下面的 Swift 所示:

let tableBackTapRecognizer = UITapGestureRecognizer(target: self, action: #selector(hideKeyboard))
tableView.backgroundView = UIView()
tableView.backgroundView?.addGestureRecognizer(tableBackTapRecognizer)

Simply using a UITapGestureRecognizer and cancelsTouchesInView = NO means that taps on cells and UITextViews also trigger the hide.简单地使用 UITapGestureRecognizer 和cancelsTouchesInView = NO意味着点击单元格和 UITextViews 也会触发隐藏。 This is bad if you have multiple UITextViews and you tap on the next one.如果你有多个 UITextViews 并且你点击下一个,这会很糟糕。 The keyboard will start to hide and then the next textView becomes the firstResponder and the keyboard becomes visible again.键盘将开始隐藏,然后下一个 textView 成为 firstResponder 并且键盘再次可见。 To avoid this, check the tap location and only hide the keyboard if the tap isn't on a cell:为避免这种情况,请检查点击位置并仅在点击不在单元格上时隐藏键盘:

// init
UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(didTapTableView:)];
tapRecognizer.cancelsTouchesInView = NO;
[self.tableView addGestureRecognizer:tapRecognizer];


// Hide on tap
- (void)didTapTableView:(UITapGestureRecognizer *)tap
{
    CGPoint point = [tap locationInView:tap.view];
    [self.view endEditing:!CGRectContainsPoint([self.tableView rectForRowAtIndexPath:[self.tableView indexPathForRowAtPoint:point]], point)];
}

In order for scrollViewWillBeginDragging: to be triggered, the tableView's scrollEnabled property must be YES为了使scrollViewWillBeginDragging:被触发,tableView 的scrollEnabled属性必须为YES

// Hide on scroll
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
    [self.view endEditing:YES];
}

Swift 4/4.2/5斯威夫特 4/4.2/5

You can also dismiss the keyboard when a cell is tapped - prior to doing anything else.您还可以在点击单元格时关闭键盘 - 在执行其他任何操作之前。

    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    view.endEditing(true)
    // Do something here
    }

tableView.keyboardDismissMode = .onDrag // .interactive

I was searching for the solution and did not find anything that would fit my code, so I did it like this:我正在寻找解决方案,但没有找到任何适合我的代码的东西,所以我这样做了:

http://82517.tumblr.com/post/13189719252/dismiss-keyboard-on-uitableview-non-cell-tap http://82517.tumblr.com/post/13189719252/dismiss-keyboard-on-uitableview-non-cell-tap

It's basically a combination of before-mentioned approaches but does not require to subclass anything or to create background buttons.它基本上是前面提到的方法的组合,但不需要子类化任何东西或创建背景按钮。

Why do you want to create a table full of textfields?为什么要创建一个充满文本字段的表格? You should be using a detailed view for each row that contains the text fields.您应该为包含文本字段的每一行使用详细视图。 When you push your detailedview, ensure that you call "[myTextField becomeFirstResponder]" so that the user can start editing with just one click away from the table list.当您推送您的详细视图时,请确保您调用了“[myTextField becomeFirstResponder]”,以便用户只需在远离表格列表的地方单击一下即可开始编辑。

Many interesting answers.许多有趣的答案。 I would like to compile different approaches into the solution that i thought best fit a UITableView scenario (it's the one I usually use): What we usually want is basically to hide the keyboard on two scenarios: on tapping outside of the Text UI elements, or on scrolling down/up the UITableView.我想将不同的方法编译成我认为最适合 UITableView 场景的解决方案(这是我通常使用的一个):我们通常想要的是在两种场景下隐藏键盘:在文本 UI 元素之外点击时,或向下/向上滚动 UITableView。 The first scenario we can easily add via a TapGestureRecognizer, and the second via the UIScrollViewDelegate scrollViewWillBeginDragging: method.第一个场景我们可以通过 TapGestureRecognizer 轻松添加,第二个场景通过 UIScrollViewDelegate scrollViewWillBeginDragging: 方法添加。 First order of business, the method to hide the keyboard:先说正事,隐藏键盘的方法:

   /**
     *  Shortcut for resigning all responders and pull-back the keyboard
     */
    -(void)hideKeyboard
    {
        //this convenience method on UITableView sends a nested message to all subviews, and they resign responders if they have hold of the keyboard
        [self.tableView endEditing:YES];

    }

This method resigns any textField UI of the subviews within the UITableView view hierarchy, so it's more practical than resigning every single element independently.此方法会重新签名 UITableView 视图层次结构中子视图的任何 textField UI,因此它比独立重新签名每个元素更实用。

Next we take care of dismissing via an outside Tap gesture, with:接下来,我们通过外部 Tap 手势处理关闭,使用:

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    [self setupKeyboardDismissGestures];

}

- (void)setupKeyboardDismissGestures
{

//    Example for a swipe gesture recognizer. it was not set-up since we use scrollViewDelegate for dissmin-on-swiping, but it could be useful to keep in mind for views that do not inherit from UIScrollView
//    UISwipeGestureRecognizer *swipeUpGestureRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(hideKeyboard)];
//    swipeUpGestureRecognizer.cancelsTouchesInView = NO;
//    swipeUpGestureRecognizer.direction = UISwipeGestureRecognizerDirectionUp;
//    [self.tableView addGestureRecognizer:swipeUpGestureRecognizer];

    UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(hideKeyboard)];
    //this prevents the gestureRecognizer to override other Taps, such as Cell Selection
    tapGestureRecognizer.cancelsTouchesInView = NO;
    [self.tableView addGestureRecognizer:tapGestureRecognizer];

}

Setting tapGestureRecognizer.cancelsTouchesInView to NO is to avoid the gestureRecognizer from overriding the normal inner workings of the UITableView (for example, not to interfere with cell Selection).将 tapGestureRecognizer.cancelsTouchesInView 设置为 NO 是为了避免gestureRecognizer 覆盖UITableView 的正常内部工作(例如,不干扰单元格选择)。

Finally, to handle hiding the keyboard on Scrolling up/down the UITableView, we must implement the UIScrollViewDelegate protocol scrollViewWillBeginDragging: method, as:最后,要处理在 UITableView 上/下滚动时隐藏键盘,我们必须实现 UIScrollViewDelegate 协议 scrollViewWillBeginDragging: 方法,如:

.h file .h 文件

@interface MyViewController : UIViewController <UIScrollViewDelegate>

.m file .m 文件

#pragma mark - UIScrollViewDelegate

-(void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
    [self hideKeyboard];
}

I hope it helps!我希望它有帮助! =) =)

Here's how I finally made works.这是我最终制作作品的方式。 I combined suggestions and codes from different answers.我结合了来自不同答案的建议和代码。 Features: dismissing keyboard, moving text fields above keyboard while editing and setting "Next" and "Done" keyboard return type.REPLACE "..." with more fields功能:关闭键盘,在编辑和设置“下一步”和“完成”键盘返回类型时移动键盘上方的文本字段。用更多字段替换“...”

static const CGFloat ANIMATION_DURATION = 0.4;
static const CGFloat LITTLE_SPACE = 5;
CGFloat animatedDistance;
CGSize keyboardSize;

@interface ViewController () <UITextFieldDelegate>
 @property (weak, nonatomic) IBOutlet UITextField *firstNameTXT;
  .....// some other text fields
 @property (weak, nonatomic) IBOutlet UITextField *emailTXT;
@end

@implementation ViewController
- (void)viewDidLoad{
.....
// add tap gesture to help in dismissing keyboard
UITapGestureRecognizer * tapGesture = [[UITapGestureRecognizer alloc]
                                       initWithTarget:self
                                       action:@selector(tapScreen:)];// outside textfields

[self.view addGestureRecognizer:tapGesture];

// set text fields return key type to Next, last text field to Done
[self.firstNameTXT setReturnKeyType:UIReturnKeyNext];
.....
[self.emailTXT setReturnKeyType:UIReturnKeyDone];

// set text fields tags
[self.firstNameTXT setTag:0];
....// more text fields
[self.emailTXT setTag:5];

// add keyboard notification
[[NSNotificationCenter defaultCenter] addObserver:self     selector:@selector(keyboardDidShow:) name:UIKeyboardDidShowNotification object:nil];
}
[[NSNotificationCenter defaultCenter] addObserver:self      selector:@selector(keyboardDidHide:) name:UIKeyboardDidHideNotification object:nil];
}

// dismiss keyboard when tap outside text fields
- (IBAction)tapScreen:(UITapGestureRecognizer *)sender {
  if([self.firstNameTXT isFirstResponder])[self.firstNameTXT resignFirstResponder];
  ...
  if([self.emailTXT isFirstResponder])[self.emailTXT  resignFirstResponder];

  }
- (BOOL)textFieldShouldReturn:(UITextField *)textField{
   if(textField.returnKeyType==UIReturnKeyNext) {
     // find the text field with next tag
     UIView *next = [[textField superview] viewWithTag:textField.tag+1];
     [next becomeFirstResponder];
   } else if (textField.returnKeyType==UIReturnKeyDone || textField.returnKeyType==UIReturnKeyDefault) {
    [textField resignFirstResponder];
 }
return YES;
}

// Moving current text field above keyboard
-(BOOL) textFieldShouldBeginEditing:(UITextField*)textField{
   CGRect viewFrame = self.view.frame;
   CGRect textFieldRect = [self.view.window convertRect:textField.bounds fromView:textField];
   CGRect viewRect = [self.view.window convertRect:self.view.bounds fromView:self.view];
   CGFloat textFieldBottomLine = textFieldRect.origin.y + textFieldRect.size.height + LITTLE_SPACE;//

   CGFloat keyboardHeight = keyboardSize.height;

   BOOL isTextFieldHidden = textFieldBottomLine > (viewRect.size.height - keyboardHeight)? TRUE :FALSE;
  if (isTextFieldHidden) {
    animatedDistance = textFieldBottomLine - (viewRect.size.height - keyboardHeight) ;
    viewFrame.origin.y -= animatedDistance;
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationBeginsFromCurrentState:YES];
    [UIView setAnimationDuration:ANIMATION_DURATION];
    [self.view setFrame:viewFrame];
    [UIView commitAnimations];
  }
  return YES;
}

-(void) restoreViewFrameOrigionYToZero{
  CGRect viewFrame = self.view.frame;
  if (viewFrame.origin.y != 0) {
    viewFrame.origin.y = 0;
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationBeginsFromCurrentState:YES];
    [UIView setAnimationDuration:ANIMATION_DURATION];
    [self.view setFrame:viewFrame];
    [UIView commitAnimations];
  }
}

-(void)keyboardDidShow:(NSNotification*)aNotification{
   NSDictionary* info = [aNotification userInfo];
   keyboardSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
 }

-(void)keyboardDidHide:(NSNotification*)aNotification{
   [self restoreViewFrameOrigionYToZero];// keyboard is dismissed, restore frame view to its  zero origin
}
@end

@mixca's answer is very useful but what if i've something different from UITextField. @mixca 的回答非常有用,但如果我有与 UITextField 不同的东西怎么办。 I think best way to handle it by searching all subviews of main view with recursive function, check example below我认为通过使用递归函数搜索主视图的所有子视图来处理它的最佳方法,请查看下面的示例

- (BOOL)findAndResignFirstResponder {
if (self.isFirstResponder) {
    [self resignFirstResponder];
    return YES;
}

    for (UIView *subView in self.subviews) {
        if ([subView findAndResignFirstResponder]) {
            return YES;
        }
    }
    return NO;
}

and also you can put this method to your utility class and can use from tap gesture like @mixca's answer..你也可以把这个方法放到你的实用程序类中,并且可以使用像@mixca's answer这样的点击手势..

If you're willing to subclass (ugh!) your table view,something like this might work:如果你愿意子类化(呃!)你的表视图,这样的事情可能会起作用:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {

   BOOL backgroundTouched = YES;

   for (UITouch *touch in touches) {
      CGPoint location = [touch locationInView:self];
      for (UITableViewCell *cell in self.visibleCells) {
         if (CGRectContainsPoint(cell.frame, location)) {
            backgroundTouched = NO;
            break;
         }
      }
   }

   if (backgroundTouched) {
      for (UITableViewCell *cell in self.visibleCells) {
         // This presumes the first subview is the text field you want to resign.
         [[cell.contentView.subviews objectAtIndex:0] resignFirstResponder];
      }
   }

   [super touchesBegan:touches withEvent:event];
}

If you want to dismiss the keyboard while return key is pressed,you can simply add the following code in textField should return method ie:如果您想在按下返回键时关闭键盘,您可以简单地在 textField 应返回方法中添加以下代码,即:

- (BOOL)textFieldShouldReturn:(UITextField *)atextField
{
   [textField resignFirstresponder];
}

Some textfields might have a picker view or some other as a subview,so in that case the above method doesn't work so in that case we need to make use of UITapGestureRecognizer class ie add the following code snippet to viewDidLoad method ie:一些文本字段可能有一个选择器视图或其他一些作为子视图,因此在这种情况下,上述方法不起作用,因此在这种情况下,我们需要使用 UITapGestureRecognizer 类,即将以下代码片段添加到 viewDidLoad 方法,即:

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

    [self.view addGestureRecognizer:tap];

Now simply add the resign responder to the selector method ie:现在只需将辞职响应者添加到选择器方法即:

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

Hope it helps,thanks :)希望有帮助,谢谢:)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM