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 UITapGestureRecognisere atribuí-lo à visualização e, em seguida, ligar para o primeiro atendedor de demissão UITextFieldno 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 UITapGestureRecognizermé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 propertyaqui (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 UIViewuma instância de UIControl(no construtor de interface) e conectar o TouchUpInsideevento ao dismissKeyboardmétodo. Este IBActionmétodo será parecido com:
- (IBAction)dismissKeyboard:(id)sender {
[aTextBox resignFirstResponder];
}
UITapGestureRecognizerinterferiu ao tocar nos botões dentro da visualização). touchesEndednão funcionou porque havia uma UIScrollViewmexer com a cadeia de responder).
Swift 4
Configure o seu UIViewControllercom 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 UIButtonou outro UITextField):
override func viewDidLoad() {
super.viewDidLoad()
let tapper = UITapGestureRecognizer(target: self, action:#selector(endEditing))
tapper.cancelsTouchesInView = false
view.addGestureRecognizer(tapper)
}
selfmelhor 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:withEventmé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, touchesBeganporque touchesBegannão é chamado se você clicar em um botão na parte superior da visualização. É melhor do que o UITapGestureRecognizerque 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, textfieldmas você não tem referência ao seu textfield.
Tente isso;
reftextFieldAgora, no textFieldDidBeginEditingcampo 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 UITextFieldo 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 UIButtonsnão respondesse quando tocado, mesmo quando eu definia a cancelsTouchesInViewpropriedade 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 dismissKeyboardmé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 dismissKeyboardSelectorexecução da pilha de execução de manipulação de toque ...
Envie uma mensagem resignFirstResponderpara 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 TextFieldScrollView. Quero tocar em ScrollViewe 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];
}