Eu estou querendo saber como fazer o teclado desaparecer quando o usuário toca fora de um UITextField
.
Eu estou querendo saber como fazer o teclado desaparecer quando o usuário toca fora de um UITextField
.
Respostas:
Você precisará adicionar um UITapGestureRecogniser
e atribuí-lo à visualização e, em seguida, ligar para o primeiro atendedor de demissão UITextField
no seletor.
O código:
In viewDidLoad
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboard)];
[self.view addGestureRecognizer:tap];
Em dispensKeyboard:
-(void)dismissKeyboard
{
[aTextField resignFirstResponder];
}
(Onde aTextField
é o campo de texto responsável pelo teclado)
A versão Swift 3 se parece com isso
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(self.dismissKeyboard (_:)))
self.view.addGestureRecognizer(tapGesture)
FormissKeyboard
@objc func dismissKeyboard (_ sender: UITapGestureRecognizer) {
aTextField.resignFirstResponder()
}
[aTextField resignFirstResponder]
seria [self.view endEditing:YES];
ele não precisa de uma referência ao campo de texto e vai trabalhar para vários campos de texto
[self.view addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self.view action:@selector(endEditing:)]];
[tap setCancelsTouchesInView:NO];
pela resposta de @qiaoyi; Eu tive um problema com uma tabela que não respondeu às seleções de linha. 5 anos depois, espero que isso ajude outra pessoa.
self.view.addGestureRecognizer(UITapGestureRecognizer(target: self.view, action: #selector(UIView.endEditing(_:))))
Eu amassei algumas respostas.
Use um ivar que seja inicializado durante viewDidLoad:
UIGestureRecognizer *tapper;
- (void)viewDidLoad
{
[super viewDidLoad];
tapper = [[UITapGestureRecognizer alloc]
initWithTarget:self action:@selector(handleSingleTap:)];
tapper.cancelsTouchesInView = NO;
[self.view addGestureRecognizer:tapper];
}
Ignore o que está sendo editado no momento:
- (void)handleSingleTap:(UITapGestureRecognizer *) sender
{
[self.view endEditing:YES];
}
Verifique isso, seria a maneira mais fácil de fazer isso,
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
[self.view endEditing:YES];// this will do the trick
}
Ou
Esta biblioteca irá lidar com a rolagem automática da barra de rolagem, toque no espaço para ocultar o teclado, etc.
Vejo que algumas pessoas estão tendo problemas ao usar o UITapGestureRecognizer
método. A maneira mais fácil de obter essa funcionalidade, mantendo o comportamento de toque do botão existente intacto, é adicionar apenas uma linha à resposta de @ Jensen2k:
[tap setCancelsTouchesInView:NO];
Isso permitiu que meus botões existentes ainda funcionassem sem usar o método do @Dmitry Sitnikov.
Leia sobre isso property
aqui (pesquise CancelsTouchesInView
): Referência da classe UIGestureRecognizer
Não sei ao certo como isso funcionaria com as barras de rolagem, pois vejo que alguns deles tiveram problemas, mas espero que outra pessoa possa ter o mesmo cenário que eu.
UIImageView
, adicione [imageView setUserInteractionEnabled:NO];
e você "clicará" nela, o que faz esse método funcionar.
É melhor criar UIView
uma instância de UIControl
(no construtor de interface) e conectar o TouchUpInside
evento ao dismissKeyboard
método. Este IBAction
método será parecido com:
- (IBAction)dismissKeyboard:(id)sender {
[aTextBox resignFirstResponder];
}
UITapGestureRecognizer
interferiu ao tocar nos botões dentro da visualização). touchesEnded
não funcionou porque havia uma UIScrollView
mexer com a cadeia de responder).
Swift 4
Configure o seu UIViewController
com este método de extensão uma vez, por exemplo viewDidLoad
:
override func viewDidLoad() {
super.viewDidLoad()
self.setupHideKeyboardOnTap()
}
e o teclado será descartado mesmo tocando no 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
}
}
Versão Swift, isso funciona em combinação com outros elementos (como um UIButton
ou outro UITextField
):
override func viewDidLoad() {
super.viewDidLoad()
let tapper = UITapGestureRecognizer(target: self, action:#selector(endEditing))
tapper.cancelsTouchesInView = false
view.addGestureRecognizer(tapper)
}
self
melhor do queself.view
canclesTouchesInView
é uma propriedade útil para usar. Obrigado.
c#
. FYI Esse ponto-e-vírgula é permitido pela sintaxe, simplesmente não é necessário.
Que tal isso: eu sei que este é um post antigo. Pode ajudar alguém :)
- (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];
}
}
}
}
Esta é uma boa solução genérica:
Objetivo-C:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[self.view endEditing:YES];
}
Rápido:
override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
self.view.endEditing(true)
}
Baseado na solução @icodebuster: https://stackoverflow.com/a/18756253/417652
Swift 4 oneliner
view.addGestureRecognizer(UITapGestureRecognizer(target: view, action: #selector(UIView.endEditing(_:))))
Acho que a maneira mais fácil (e melhor) de fazer isso é subclassificar sua visão global e usar o hitTest:withEvent
método para ouvir qualquer toque. Os toques no teclado não são registrados, então hitTest: withEvent é chamado apenas quando você toca / rola / desliza / pitada ... em outro lugar e, em seguida, chama [self endEditing:YES]
.
É melhor do que usar, touchesBegan
porque touchesBegan
não é chamado se você clicar em um botão na parte superior da visualização. É melhor do que o UITapGestureRecognizer
que não pode reconhecer um gesto de rolagem, por exemplo. Também é melhor do que usar uma tela escura, porque em uma interface complexa e dinâmica do usuário, você não pode colocar a tela escura em qualquer lugar. Além disso, ele não bloqueia outras ações, você não precisa tocar duas vezes para selecionar um botão externo (como no caso de UIPopover
).
Além disso, é melhor do que ligar [textField resignFirstResponder]
, porque você pode ter muitos campos de texto na tela, portanto, isso funciona para todos eles.
Essa deve ser a maneira mais fácil de ocultar o teclado tocando fora:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[self.view endEditing:YES];
}
(em Como descartar o teclado quando o usuário toca em outra área fora do campo de texto? )
Se a visualização estiver totalmente incorporada a UIScrollView
, você poderá usar o seguinte:
tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeOnDrag;
tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeInteractive;
O primeiro anima o teclado fora da tela quando a exibição da tabela é rolada e o posterior oculta o teclado como o aplicativo de mensagens padrão.
Observe que eles estão disponíveis no iOS 7.0 ou superior.
Você pode fazer isso usando o Storyboard no XCode 6 e acima:
Adicione isso ao arquivo de cabeçalho da classe usada pelo seu ViewController:
@interface TimeDelayViewController : UIViewController <UITextFieldDelegate>
- (IBAction)dissmissKeyboardOnTap:(id)sender;
@end
Em seguida, adicione isso ao arquivo de implementação do mesmo ViewController:
- (IBAction)dissmissKeyboardOnTap:(id)sender{
[[self view]endEditing:YES];
}
Agora, essa será uma das 'Ações recebidas' da cena do storyboard (por exemplo, ViewController):
Agora você precisa conectar esta ação ao gesto do usuário de tocar no teclado.
Importante - Você precisa converter o 'UIView' contido no seu storyboard em um UIControl , para que ele possa receber eventos. Selecione a visualização da hierarquia da cena do View Controller:
... e mude de classe:
Agora arraste do pequeno círculo ao lado da 'ação recebida' para a sua cena para uma parte 'vazia' da sua cena (na verdade você está arrastando a 'Ação recebida' para o UIControl). Você verá uma seleção de eventos aos quais você pode conectar sua ação:
Selecione a opção 'retocar por dentro'. Agora você conectou o IBAction que você criou a uma ação do usuário de tocar no teclado. Quando o usuário toca no teclado, ele fica oculto.
(OBSERVAÇÃO: para conectar a ação ao evento, você também pode arrastar a ação recebida diretamente para o UIControl na sua hierarquia dos Controladores de exibição. Ela é exibida como 'Controle' na hierarquia.)
Se eu entendi direito, você deseja renunciar ao teclado enquanto toca fora, textfield
mas você não tem referência ao seu textfield
.
Tente isso;
reftextField
Agora, no textFieldDidBeginEditing
campo de texto referenciado definido como
- (void) textFieldDidBeginEditing:(UITextField *)textField{
reftextField = textField;
}
Agora você pode usá-lo com facilidade em qualquer relógio de botão (adicionar um botão transparente para começar a editar é recomendado)
- (void)dismissKeyboard {
[reftextField resignFirstResponder];
}
Ou, para renunciar ao botão Concluído, tente isso.
//for resigning on done button
- (BOOL) textFieldShouldReturn:(UITextField *)textField{
[textField resignFirstResponder];
return YES;
}
Apenas para adicionar à lista aqui minha versão de como descartar um teclado em um toque externo.
viewDidLoad:
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleSingleTap:)];
[self.view addGestureRecognizer:singleTap];
Qualquer lugar:
-(void)handleSingleTap:(UITapGestureRecognizer *)sender{
[textFieldName resignFirstResponder];
puts("Dismissed the keyboard");
}
Muitas ótimas respostas aqui sobre o uso de UITapGestureRecognizer
- todas as quais quebram UITextField
o botão (X) claro. A solução é suprimir o reconhecedor de gestos por meio de seu representante:
- (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);
}
Não é a solução mais robusta, mas funciona para mim.
return !touchViewIsButton
. Eu acho que quaisquer outros botões que precisam descartar o teclado devem fazê-lo em suas ações. Além disso, o TouchUpInside pode não ser chamado quando o layout é alterado na dispensa do teclado.
Você pode criar uma categoria para o UiView e substituir os toquesBegan meathod da seguinte maneira.
Ele está funcionando bem para mim e é uma solução centralizada para esse problema.
#import "UIView+Keyboard.h"
@implementation UIView(Keyboard)
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[self.window endEditing:true];
[super touchesBegan:touches withEvent:event];
}
@end
Versão rápida da resposta de @ Jensen2k:
let gestureRecognizer : UITapGestureRecognizer = UITapGestureRecognizer.init(target: self, action: "dismissKeyboard")
self.view.addGestureRecognizer(gestureRecognizer)
func dismissKeyboard() {
aTextField.resignFirstResponder()
}
Um forro
self.view.addTapGesture(UITapGestureRecognizer.init(target: self, action: "endEditing:"))
Usei o exemplo de Barry para o meu novo desenvolvimento. Funcionou muito bem! mas tive que incluir uma pequena alteração, necessária para descartar o teclado apenas para o campo de texto que está sendo editado.
Então, adicionei ao exemplo de Barry o seguinte:
- (void) textFieldDidBeginEditing:(UITextField *)textField
{
_textBeingEdited = textField;
}
-(void) textFieldDidEndEditing:(UITextField *)textField
{
_textBeingEdited = nil;
}
Além disso, mudei o método hideKeyboard da seguinte maneira:
- (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];
}
Uma das maneiras mais fáceis e curtas é adicionar esse código ao seu viewDidLoad
[self.view addGestureRecognizer:[[UITapGestureRecognizer alloc]
initWithTarget:self.view
action:@selector(endEditing:)]];
Tentei muitas das respostas aqui e não tive sorte. Meu reconhecedor de gestos de toque sempre fazia com que eu UIButtons
não respondesse quando tocado, mesmo quando eu definia a cancelsTouchesInView
propriedade do reconhecedor de gestos como NÃO.
Isto é o que acabou resolvendo o problema:
Tenha um ivar:
UITapGestureRecognizer *_keyboardDismissGestureRecognizer;
Quando um campo de texto começar a editar, defina o reconhecedor de gestos:
- (void) textFieldDidBeginEditing:(UITextField *)textField
{
if(_keyboardDismissGestureRecognizer == nil)
{
_keyboardDismissGestureRecognizer = [[[UITapGestureRecognizer alloc]
initWithTarget:self
action:@selector(dismissKeyboard)] autorelease];
_keyboardDismissGestureRecognizer.cancelsTouchesInView = NO;
[self.view addGestureRecognizer:_keyboardDismissGestureRecognizer];
}
}
O truque está em como você configura o dismissKeyboard
método:
- (void) dismissKeyboard
{
[self performSelector:@selector(dismissKeyboardSelector) withObject:nil afterDelay:0.01];
}
- (void) dismissKeyboardSelector
{
[self.view endEditing:YES];
[self.view removeGestureRecognizer:_keyboardDismissGestureRecognizer];
_keyboardDismissGestureRecognizer = nil;
}
Eu acho que há algo sobre tirar a dismissKeyboardSelector
execução da pilha de execução de manipulação de toque ...
Envie uma mensagem resignFirstResponder
para o arquivo de texto que o colocou lá. Por favor, consulte este post para mais informações.
Neste exemplo, aTextField é o único UITextField .... Se houver outros ou UITextViews, há um pouco mais a fazer.
// 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");
}
- (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];
}
Adicione este código ao seu arquivo ViewController.m :
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[self.view endEditing:YES];
}
Nesse caso, pode-se usar o ScrollView e adicioná-lo ao TextField
ScrollView. Quero tocar em ScrollView
e em Exibir e depois em Ignorar o teclado. Eu tentei criar código de exemplo por precaução. Como isso,
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.
}
}
Seu Storyboard Veja isso exatamente como.
Você pode usar o método UITapGestureRecongnizer para descartar o teclado clicando fora do UITextField. Ao usar esse método sempre que o usuário clicar fora do UITextField, o teclado será descartado. Abaixo está o trecho de código para usá-lo.
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]
initWithTarget:self
action:@selector(dismissk)];
[self.view addGestureRecognizer:tap];
//Method
- (void) dismissk
{
[abctextfield resignFirstResponder];
[deftextfield resignFirstResponder];
}