问题
I'm trying to hide the number pad, but I do not want to implement a button.
Is there a way to dismiss the number pad when the user taps outside the textfield?
回答1:
This is one of those questions where you read it and say "That's easy you just..". And then you go to do it and make it super complicated. And then realize it doesn't have to be that complicated.
The answer I've come up with, and I'm sure it will help someone else, Is to use an invisible UIView
that never interacts but acts on other views and maybe not in the way you'd think.
The typical answer to a question about dismissing the UIKeyboardTypeNumberPad
keyboard is to add a bar that has a button as the inputAccessoryView
to dismiss the keyboard. If a bar and button are undesirable generally you just listen for touch events on the background and your good to go but this question is about a tableview and that makes this much harder.
But this inputAccessoryView
feature is still awesome. It allows you to define a UIView
or UIView
subclass to be displayed when the keyboard is shown. More importantly when the keyboard is shown due to a textfield for which it is the inputAccessoryView
becoming first responder.
I could yammer on but first here is some code for a lightweight class that actually performs very well in testing.
The contents of NJ_KeyboardDismisser.h
are:
#import <UIKit/UIKit.h>
// For some reason neither inputView or inputAccessoryView are IBOutlets, so we cheat.
@interface UITextField (WhyDoIHaveToDoThisApple)
@property (readwrite, retain) IBOutlet UIView *inputAccessoryView;
@end
@interface NJ_KeyboardDismisser : UIView
@property (nonatomic, weak) IBOutlet UIView *mainView;
-(id)initWithMainView:(UIView *)view; // convienience method for code
@end
And the contents of NJ_KeyboardDismisser.m
are:
#import "NJ_KeyboardDismisser.h"
@implementation NJ_KeyboardDismisser {
UITapGestureRecognizer *_tapGR;
}
@synthesize mainView = _mainView;
-(void)setMainView:(UIView *)view{
if (_tapGR) [_tapGR.view removeGestureRecognizer:_tapGR];
_mainView = view;
_tapGR = [[UITapGestureRecognizer alloc] initWithTarget:_mainView action:@selector(endEditing:)];
}
-(id)initWithMainView:(UIView *)view{
if ((self = [super initWithFrame:CGRectMake(0, 0, 0, 0)])){
self.mainView = view;
}
return self;
}
-(void)didMoveToWindow{ // When the accessory view presents this delegate method will be called
[super didMoveToWindow];
if (self.window){ // If there is a window one of the textfields, for which this view is inputAccessoryView, is first responder.
[self.mainView addGestureRecognizer:_tapGR];
}
else { // If there is no window the textfield is no longer first responder
[self.mainView removeGestureRecognizer:_tapGR];
}
}
@end
You may recognize the endEditing:
method, as mentioned by Cosique, it is a UIView extension method that asks a views nested textfield to resign. Sound handy? It is. By calling it on the tableview the textfield it contains resigns first responder. Since this technique works on all UIView
s there is no need to artificially limit this outlet to only UITableView
s so the outlet is just UIView *mainView
.
The final moving part here is the UITapGestureRecognizer
. We don't want to add this recognizer full time for fear of screwing up the tableview's workings. So we take advantage of UIView
's delegate method didMoveToWindow
. We don't really do anything with the window we just check to see if we are in one; If we are then one of our textfields is first responder, if not then it's not. We add and remove our gesture recognizer accordingly.
Okay straightforward enough, but how do you use it? Well if instantiating in code you could do it like this, in tableView:cellForRowAtIndexPath:
:
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"Cell"];
UITextField *field = [[UITextField alloc] initWithFrame:CGRectMake(20, 6, 100, 31)];
[cell.contentView addSubview:field];
field.keyboardType = UIKeyboardTypeNumberPad;
field.inputAccessoryView = [[NJ_KeyboardDismisser alloc] initWithMainView:self.view];
}
If you are using static cells in a storyboard then the technique is different (obviously). First drag out a generic NSObject
and place it in the dark grey strip below the view (where the other objects such as the view controller are). Then change this new object's class to be NJ_KeyboardDismisser
. Then connect the "Keyboard Dismisser"'s mainView
property to that view (generally a tableview). Then connect the inputAccessoryView
property from any each text field in that scene you wish to the "Keyboard Dismisser".

Give it a try! The tableview acts normally. Apple's tap recognizer is smart enough to ignore the swipes on the table, so you can scroll. It also ignores touches in the textfields so you can edit and select other textfields. But tap outside a textfield and the keyboard is gone.
Note: This class's use is not limited to tableviews. If you want to use it on a regular view, just set the mainView
property to be the same as the view controller's view.
回答2:
The easiest way is to do this in your view controller:
[self.view endEditing: YES];
回答3:
You can resign the responder inside the below function for your view:
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
Make sure your view is enabled for user interaction.
回答4:
when creating the text field add a tag to it.
like this Yourtextfield.tag = 1
;
and in you touchesEnded
method
do this :
UITextField *resignTextField = (UITextField *)[self.view viewWithTag:1];
[resignTextField resignFirstResponder];
来源:https://stackoverflow.com/questions/9246509/how-to-dismiss-uikeyboardtypenumberpad