Простой способ уволить клавиатуру?
У меня довольно много элементов управления, разбросанных по многим ячейкам таблицы в моей таблице, и мне было интересно, есть ли более простой способ уволить клавиатуру без необходимости циклически перебирать все мои элементы управления и отказываться от них всех в качестве первого респондента. Я предполагаю, что вопрос.. Как бы я получить текущий первый ответчик на клавиатуре?
31 ответ
Вы можете принудительно изменить вид, редактируемый в настоящее время, чтобы изменить статус первого респондента с [view endEditing:YES]
, Это скрывает клавиатуру.
В отличие от -[UIResponder resignFirstResponder]
, -[UIView endEditing:]
будет искать в подпредставлениях, чтобы найти текущего первого респондента. Таким образом, вы можете отправить его на верхнем уровне просмотра (например, self.view
в UIViewController
) и это будет правильно делать.
(Этот ответ ранее включал несколько других решений, которые также работали, но были более сложными, чем необходимо. Я удалил их, чтобы избежать путаницы.)
Вы можете отправить нулевое целевое действие в приложение, оно в любой момент подаст в отставку первому респонденту, не беспокоясь о том, какое представление в настоящее время имеет статус первого респондента.
Objective-C:
[[UIApplication sharedApplication] sendAction:@selector(resignFirstResponder) to:nil from:nil forEvent:nil];
Swift 3.0:
UIApplication.shared.sendAction(#selector(resignFirstResponder), to: nil, from: nil, for: nil)
Действия с нулевым таргетингом распространены в Mac OS X для команд меню, и вот их использование в iOS.
Честно говоря, я не в восторге от любого решения, предложенного здесь. Я нашел хороший способ использовать TapGestureRecognizer, который, я думаю, доходит до сути вашей проблемы: когда вы нажимаете на что-либо, кроме клавиатуры, отклоняйте клавиатуру.
В viewDidLoad зарегистрируйтесь для получения уведомлений клавиатуры и создайте UITapGestureRecognizer:
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; [nc addObserver:self selector:@selector(keyboardWillShow:) name: UIKeyboardWillShowNotification object:nil]; [nc addObserver:self selector:@selector(keyboardWillHide:) name: UIKeyboardWillHideNotification object:nil]; tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(didTapAnywhere:)];
Добавить клавиатуру показать / скрыть респондентов. Там вы добавляете и удаляете TapGestureRecognizer в UIView, который должен отклонять клавиатуру при нажатии. Примечание. Нет необходимости добавлять его во все вложенные представления или элементы управления.
-(void) keyboardWillShow:(NSNotification *) note { [self.view addGestureRecognizer:tapRecognizer]; } -(void) keyboardWillHide:(NSNotification *) note { [self.view removeGestureRecognizer:tapRecognizer]; }
TapGestureRecognizer будет вызывать вашу функцию, когда он получает нажатие, и вы можете отклонить клавиатуру следующим образом:
-(void)didTapAnywhere: (UITapGestureRecognizer*) recognizer { [textField resignFirstResponder]; }
Хорошая особенность этого решения состоит в том, что оно фильтрует только по нажатию, а не по считыванию. Поэтому, если у вас есть прокрутка контента над клавиатурой, пролистывание все равно будет прокручиваться и клавиатура будет отображаться. Удалив распознаватель жестов после того, как клавиатура исчезнет, будущие касания на вашем экране обрабатываются как обычно.
Это решение, чтобы заставить клавиатуру уйти при нажатии return
в любом текстовом поле, добавив код в одном месте (поэтому не нужно добавлять обработчик для каждого текстового поля):
рассмотрим этот сценарий:
у меня есть viewcontroller
с двумя текстовыми полями (имя пользователя и пароль). и viewcontroller
инвентарь UITextFieldDelegate
протокол
я делаю это в viewDidLoad
- (void)viewDidLoad
{
[super viewDidLoad];
username.delegate = self;
password.delegate = self;
}
и viewcontroller реализует необязательный метод как
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
[textField resignFirstResponder];
return YES;
}
и независимо от того, в каком текстовом поле вы находитесь, как только я нажму return
в клавиатуре это уволено!
В вашем случае то же самое будет работать, если вы установите для всех делегатов текстового поля значение self и реализуете textFieldShouldReturn
Лучше подходить, чтобы что-то "украло" статус первого респондента.
Поскольку UIApplication является подклассом UIResponder, вы можете попробовать:
[[UIApplication sharedApplication] becomeFirstResponder]
[[UIApplication sharedApplication] resignFirstResponder]
В противном случае создайте новый UITextField с фреймом нулевого размера, добавьте его где-нибудь в представление и сделайте что-то подобное (переходите в отставку).
Убери это в каком-нибудь служебном классе.
+ (void)dismissKeyboard {
[self globalResignFirstResponder];
}
+ (void) globalResignFirstResponder {
UIWindow * window = [[UIApplication sharedApplication] keyWindow];
for (UIView * view in [window subviews]){
[self globalResignFirstResponderRec:view];
}
}
+ (void) globalResignFirstResponderRec:(UIView*) view {
if ([view respondsToSelector:@selector(resignFirstResponder)]){
[view resignFirstResponder];
}
for (UIView * subview in [view subviews]){
[self globalResignFirstResponderRec:subview];
}
}
@ Николас Райли & @Kendall Helmstetter Geln & @cannyboy:
Абсолютно блестящий!
Спасибо.
Учитывая ваши советы и советы других в этой теме, вот что я сделал:
Как это выглядит при использовании:
[[self appDelegate] dismissKeyboard];
(примечание: я добавил appDelegate как дополнение к NSObject, чтобы я мог использовать где угодно и что угодно)
Как это выглядит под капотом:
- (void)dismissKeyboard
{
UITextField *tempTextField = [[[UITextField alloc] initWithFrame:CGRectZero] autorelease];
tempTextField.enabled = NO;
[myRootViewController.view addSubview:tempTextField];
[tempTextField becomeFirstResponder];
[tempTextField resignFirstResponder];
[tempTextField removeFromSuperview];
}
РЕДАКТИРОВАТЬ
Поправка к моему ответу включена tempTextField.enabled = NO;
, Отключение текстового поля предотвратит UIKeyboardWillShowNotification
а также UIKeyboardWillHideNotification
уведомления от клавиатуры от отправки, если вы полагаетесь на эти уведомления во всем приложении.
Вот что я использую в своем коде. Отлично работает!
В yourviewcontroller.h добавьте:
@property (nonatomic) UITapGestureRecognizer *tapRecognizer;
Теперь в.m файле добавьте это к вашей функции ViewDidLoad:
- (void)viewDidLoad {
//Keyboard stuff
tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(didTapAnywhere:)];
tapRecognizer.cancelsTouchesInView = NO;
[self.view addGestureRecognizer:tapRecognizer];
}
Также добавьте эту функцию в файл.m:
- (void)handleSingleTap:(UITapGestureRecognizer *) sender
{
[self.view endEditing:YES];
}
Здесь много слишком сложных ответов, возможно, потому, что это не так легко найти в документации по iOS. Иосиф-Х имел это прямо выше:
[[view window] endEditing:YES];
Даже проще, чем ответ Мигар
затирать touchesBegan:withEvent:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[textField resignFirstResponder];`
}
Это будет dismiss the keyboard
когда вы касаетесь где-либо в background
,
Быстрый совет о том, как отключить клавиатуру в iOS, когда пользователь касается любого места на экране за пределами UITextField или клавиатуры. Учитывая, сколько недвижимости может занять клавиатура iOS, имеет смысл предложить пользователям простой и интуитивно понятный способ отклонить клавиатуру.
Вот ссылка
Вы должны отправить endEditing:
чтобы рабочее окно являлось подклассом UIView
[[UIApplication sharedApplication].windows.firstObject endEditing:NO];
Лучший способ отклонить клавиатуру из UITableView и UIScrollView:
tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeOnDrag
В заголовочный файл вашего контроллера добавить <UITextFieldDelegate>
к определению интерфейса вашего контроллера, чтобы он соответствовал протоколу делегата UITextField...
@interface someViewController : UIViewController <UITextFieldDelegate>
... В файле реализации контроллера (.m) добавьте следующий метод или код внутри него, если у вас уже есть метод viewDidLoad...
- (void)viewDidLoad
{
// Do any additional setup after loading the view, typically from a nib.
self.yourTextBox.delegate = self;
}
... Затем свяжите yourTextBox с вашим фактическим текстовым полем
- (BOOL)textFieldShouldReturn:(UITextField *)theTextField
{
if (theTextField == yourTextBox) {
[theTextField resignFirstResponder];
}
return YES;
}
В Swift 3 вы можете сделать следующее
UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
Подкласс ваши текстовые поля... а также текстовые представления
В подклассе положить этот код..
-(void)conformsToKeyboardDismissNotification{
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(dismissKeyBoard) name:KEYBOARD_DISMISS object:nil];
}
-(void)deConformsToKeyboardDismissNotification{
[[NSNotificationCenter defaultCenter] removeObserver:self name:KEYBOARD_DISMISS object:nil];
}
- (void)dealloc{
[[NSNotificationCenter defaultCenter] removeObserver:self];
[self resignFirstResponder];
}
В текстовом поле делегаты (аналогично для делегатов textview)
-(void)textFieldDidBeginEditing:(JCPTextField *)textField{
[textField conformsToKeyboardDismissNotification];
}
- (void)textFieldDidEndEditing:(JCPTextField *)textField{
[textField deConformsToKeyboardDismissNotification];
}
Все готово.. Теперь просто отправьте уведомление из любого места в вашем коде. Он подаст в отставку любую клавиатуру.
И в кратчайшие сроки мы можем сделать
UIApplication.sharedApplication().sendAction("resignFirstResponder", to: nil, from: nil, forEvent: nil)
Я думаю, что ответ Джереми не работал для меня, потому что у меня был стек навигации в виде вкладок с модальным диалогом поверх него. Я использую следующее прямо сейчас, и оно работает для меня, но ваш пробег может отличаться.
// dismiss keyboard (mostly macro)
[[UIApplication sharedApplication].delegate dismissKeyboard]; // call this in your to app dismiss the keybaord
// --- dismiss keyboard (in indexAppDelegate.h) (mostly macro)
- (void)dismissKeyboard;
// --- dismiss keyboard (in indexAppDelegate.m) (mostly macro)
// do this from anywhere to dismiss the keybard
- (void)dismissKeyboard { // from: http://stackru.com/questions/741185/easy-way-to-dismiss-keyboard
UITextField *tempTextField = [[UITextField alloc] initWithFrame:CGRectZero];
UIViewController *myRootViewController = <#viewController#>; // for simple apps (INPUT: viewController is whatever your root controller is called. Probably is a way to determine this progragrammatically)
UIViewController *uivc;
if (myRootViewController.navigationController != nil) { // for when there is a nav stack
uivc = myRootViewController.navigationController;
} else {
uivc = myRootViewController;
}
if (uivc.modalViewController != nil) { // for when there is something modal
uivc = uivc.modalViewController;
}
[uivc.view addSubview:tempTextField];
[tempTextField becomeFirstResponder];
[tempTextField resignFirstResponder];
[tempTextField removeFromSuperview];
[tempTextField release];
}
Чтобы закрыть клавиатуру после ее появления, есть 2 случая:
когда UITextField находится внутри UIScrollView
когда UITextField находится вне UIScrollView
2. когда UITextField находится вне UIScrollView, переопределите метод в вашем подклассе UIViewController
Вы также должны добавить делегат для всех UITextView
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[self.view endEditing:YES];
}
- В режиме прокрутки касание снаружи не вызовет никакого события, поэтому в этом случае используйте Распознаватель жестов касания, перетащите UITapGesture для представления прокрутки и создайте для него IBAction.
чтобы создать IBAction, нажмите Ctrl+ щелкните UITapGesture и перетащите его в.h файл viewcontroller.
Здесь я назвал tappedEvent в качестве имени моего действия
- (IBAction)tappedEvent:(id)sender {
[self.view endEditing:YES]; }
приведенная выше информация была получена по следующей ссылке, пожалуйста, обратитесь за дополнительной информацией или свяжитесь со мной, если вы не понимаете данные выше.
http://samwize.com/2014/03/27/dismiss-keyboard-when-tap-outside-a-uitextfield-slash-uitextview/
Вам также может понадобиться переопределить UIViewController disablesAutomaticKeyboardDismissal, чтобы в некоторых случаях это работало. Это, возможно, должно быть сделано на UINavigationController, если у вас есть.
Вы должны использовать один из этих методов,
[self.view endEditing:YES];
или же
[self.textField resignFirstResponder];
Вы можете рекурсивно перебирать подпредставления, сохранять массив всех UITextFields, а затем перебирать их и оставлять их все.
Не очень хорошее решение, особенно если у вас много подпредставлений, но для простых приложений это должно сработать.
Я решил это гораздо более сложным, но гораздо более производительным способом, но с использованием синглтона / менеджера для механизма анимации моего приложения, и каждый раз, когда текстовое поле становилось отвечающим, я назначал его статическому элементу, который получал бы подметил (подал в отставку) на основе некоторых других событий... это почти невозможно для меня объяснить в параграфе.
Будьте изобретательны, мне понадобилось всего 10 минут, чтобы обдумать это для моего приложения после того, как я нашел этот вопрос.
Самый простой способ - вызвать метод
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
if(![txtfld resignFirstResponder])
{
[txtfld resignFirstResponder];
}
else
{
}
[super touchesBegan:touches withEvent:event];
}
Это не красиво, но то, как я оставляю firstResponder, когда я не знаю, что это за ответчик:
Создайте UITextField, либо в IB, либо программно. Сделать это скрытым Свяжите это с вашим кодом, если вы сделали это в IB. Затем, когда вы хотите убрать клавиатуру, вы переключаете респондент в невидимое текстовое поле и немедленно отмените его:
[self.invisibleField becomeFirstResponder];
[self.invisibleField resignFirstResponder];
Немного более надежный метод, который мне нужно было использовать недавно:
- (void) dismissKeyboard {
NSArray *windows = [UIApplication sharedApplication].windows;
for(UIWindow *window in windows) [window endEditing:true];
// Or if you're only working with one UIWindow:
[[UIApplication sharedApplication].keyWindow endEditing:true];
}
Я обнаружил, что некоторые другие "глобальные" методы не работают (например, UIWebView
& WKWebView
отказался уйти в отставку).
Я ненавижу, что не существует "глобального" способа программно отключить клавиатуру без использования частных вызовов API. Часто мне нужно программно отмахиваться от клавиатуры, не зная, какой объект является первым респондентом. Я прибег к проверке self
используя API-интерфейс Objective-C, перечисляя все его свойства, извлекая те, которые имеют тип UITextField
и отправив им resignFirstResponder
сообщение.
Это не должно быть так сложно сделать это...
Добавьте распознаватель жестов касанием к своему виду. И определите его ibaction
ваш.m файл будет похож
- (IBAction)hideKeyboardGesture:(id)sender {
NSArray *windows = [UIApplication sharedApplication].windows;
for(UIWindow *window in windows) [window endEditing:true];
[[UIApplication sharedApplication].keyWindow endEditing:true];
}
Это работает для меня
Да, endEditing - лучший вариант. И из iOW 7.0, UIScrollView
имеет классную функцию, чтобы отклонить клавиатуру при взаимодействии с видом прокрутки. Для достижения этого вы можете установить keyboardDismissMode
собственностью UIScrollView
,
Установите режим отклонения клавиатуры как:
tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeOnDrag
У него есть несколько других типов. Посмотрите на этот яблочный документ.