iphone - appears - hide keyboard swift 4
¿Cómo descartar el teclado para UITextView con tecla de retorno? (30)
// Puedes usar esto ...
Paso 1. El primer paso es asegurarse de que declara soporte para el protocolo UITextViewDelegate
. Esto se hace en su archivo de encabezado, como ejemplo aquí está el encabezado llamado
EditorController.h:
@interface EditorController : UIViewController {
UITextView *messageTextView;
}
@property (nonatomic, retain) UITextView *messageTextView;
@end
Paso 2. A continuación, deberá registrar el controlador como delegado de UITextView. Continuando con el ejemplo anterior, aquí es cómo he inicializado el UITextView
con EditorController
como delegado ...
- (id) init {
if (self = [super init]) {
// define the area and location for the UITextView
CGRect tfFrame = CGRectMake(10, 10, 300, 100);
messageTextView = [[UITextView alloc] initWithFrame:tfFrame];
// make sure that it is editable
messageTextView.editable = YES;
// add the controller as the delegate
messageTextView.delegate = self;
}
Paso 3. Y ahora, la última pieza del rompecabezas es tomar acción en respuesta al mensaje shouldCahngeTextInRange
siguiente manera:
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range
replacementText:(NSString *)text
{
// Any new character added is passed in as the "text" parameter
if ([text isEqualToString:@"/n"]) {
// Be sure to test for equality using the "isEqualToString" message
[textView resignFirstResponder];
// Return FALSE so that the final ''/n'' character doesn''t get added
return FALSE;
}
// For any other character return TRUE so that the text gets added to the view
return TRUE;
}
En la biblioteca de IB, la introducción nos dice que cuando se presiona la tecla de retorno, el teclado para UITextView
desaparecerá. Pero en realidad la clave de retorno solo puede actuar como ''/ n''.
Puedo agregar un botón y usar [txtView resignFirstResponder]
para ocultar el teclado.
¿Pero hay una manera de agregar la acción para la tecla de retorno en el teclado para que no tenga que agregar UIButton
?
Agregar un observador en viewDidLoad
[[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(textViewKeyPressed:) name: UITextViewTextDidChangeNotification object: nil];
y luego use el selector para verificar "/ n"
-(void) textViewKeyPressed: (NSNotification*) notification {
if ([[[notification object] text] hasSuffix:@"/n"])
{
[[notification object] resignFirstResponder];
}
}
Utiliza "/ n" y no busca específicamente una clave de retorno, pero creo que esto está bien.
ACTUALIZAR
Vea la respuesta de ribto a continuación, que usa [NSCharacterSet newlineCharacterSet]
en lugar de /n
Agregue este método en su controlador de vista.
Swift :
func textView(textView: UITextView, shouldChangeTextInRange range: NSRange, replacementText text: String) -> Bool {
if text == "/n" {
textView.resignFirstResponder()
return false
}
return true
}
Este método también puede ser útil para usted:
/**
Dismiss keyboard when tapped outside the keyboard or textView
:param: touches the touches
:param: event the related event
*/
override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
if let touch = touches.anyObject() as? UITouch {
if touch.phase == UITouchPhase.Began {
textField?.resignFirstResponder()
}
}
}
Al igual que Matt comentó a Samvermette, tampoco me gusta la idea de detectar "/ n". La tecla "retorno" está ahí por una razón en UITextView, que es ir a la siguiente línea, por supuesto.
En mi opinión, la mejor solución es imitar la aplicación de mensajes del iPhone, que consiste en agregar la barra de herramientas (y el botón) en el teclado.
Obtuve el código de la siguiente publicación del blog:
http://www.iosdevnotes.com/2011/02/iphone-keyboard-toolbar/
Pasos:
-Agregue la barra de herramientas a su archivo XIB - establezca la altura en 460
-Agregar elemento de botón de la barra de herramientas (si no está ya agregado). Si necesita alinearlo a la derecha, también agregue un elemento de botón de barra flexible a XIB y mueva el elemento de botón de la barra de herramientas
-Crear una acción que vincule el elemento de su botón con resignFirstResponder como sigue:
- (IBAction)hideKeyboard:(id)sender {
[yourUITextView resignFirstResponder];
}
-Entonces:
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil];
}
- (void)keyboardWillShow:(NSNotification *)notification {
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.3];
CGRect frame = self.keyboardToolbar.frame;
frame.origin.y = self.view.frame.size.height - 260.0;
self.keyboardToolbar.frame = frame;
[UIView commitAnimations];
}
- (void)keyboardWillHide:(NSNotification *)notification {
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.3];
CGRect frame = self.keyboardToolbar.frame;
frame.origin.y = self.view.frame.size.height;
self.keyboardToolbar.frame = frame;
[UIView commitAnimations];
}
De acuerdo. Todos han dado respuestas con trucos, pero creo que la forma correcta de lograrlo es mediante
Conectando la siguiente acción al evento " Did End On Exit " en Interface Builder
. (Haga clic con el botón derecho en el TextField
y cntrl-arrastre de ''Finalizó al salir '' al método siguiente.
-(IBAction)hideTheKeyboard:(id)sender
{
[self.view endEditing:TRUE];
}
Encontré que la respuesta de josebama es la respuesta más completa y limpia disponible en este hilo.
A continuación se muestra la sintaxis de Swift 4 para ello:
func textView(_ textView: UITextView, shouldChangeTextIn _: NSRange, replacementText text: String) -> Bool {
let resultRange = text.rangeOfCharacter(from: CharacterSet.newlines, options: .backwards)
if text.characters.count == 1 && resultRange != nil {
textView.resignFirstResponder()
// Do any additional stuff here
return false
}
return true
}
Hay otra solución mientras se usa con uitextview. Puede agregar la barra de herramientas como InputAccessoryView en "textViewShouldBeginEditing", y desde este botón de barra de herramientas puede descartar el teclado, el código para esto es el siguiente:
En viewDidLoad
toolBar = [[UIToolbar alloc]initWithFrame:CGRectMake(0, 0, 320, 44)]; //toolbar is uitoolbar object
toolBar.barStyle = UIBarStyleBlackOpaque;
UIBarButtonItem *btnDone = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(btnClickedDone:)];
[toolBar setItems:[NSArray arrayWithObject:btnDone]];
En el método textviewdelegate
- (BOOL)textViewShouldBeginEditing:(UITextView *)textView
{
[textView setInputAccessoryView:toolBar];
return YES;
}
En la acción de Button Done que se encuentra en la barra de herramientas está siguiendo:
-(IBAction)btnClickedDone:(id)sender
{
[self.view endEditing:YES];
}
La pregunta pregunta cómo hacerlo con la tecla de retorno, pero creo que esto podría ayudar a alguien con la intención de hacer que el teclado desaparezca al usar UITextView:
@IBOutlet weak var textView: UITextView!
private func addToolBarForTextView() {
let textViewToolbar: UIToolbar = UIToolbar()
textViewToolbar = UIBarStyle.Default
textViewToolbar = [
UIBarButtonItem(title: "Cancel", style: UIBarButtonItemStyle.Done, target: self, action: #selector(self.cancelInput)),
UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.FlexibleSpace, target: self, action: nil),
UIBarButtonItem(title: "Done", style: UIBarButtonItemStyle.Done, target: self, action: #selector(self.doneInput))
]
textViewToolbar()
self.textView.inputAccessoryView = textViewToolbar //do it for every relevant textView if there are more than one
}
func doneInput() {
self.textView.resignFirstResponder()
}
func cancelInput() {
self.textView.text = ""
self.textView.resignFirstResponder()
}
Llame a addToolBarForTextView () en viewDidLoad o algún otro método de ciclo de vida.
Parece que fue la solución perfecta para mí.
Aclamaciones,
Murat
Mi truco para esto:
1- crear un botón que cubra toda la vista; 2- envíelo al fondo de su vista, 3- cambie su Tipo de "Ronda Recta" a "Personalizado" en el Inspector de Atributos, 4- cree una acción 5- implemente el método de acción:
- (IBAction)bgTouched:(id)sender
{
//to dismiss keyboard on bg btn pressed
[_userInput resignFirstResponder];
}
donde _userInput es su salida de TextField
No olvide configurar el delegado para textView; de lo contrario, resignfirstresponder no funcionará.
Para Xcode 6.4., Swift 1.2. :
override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent)
{
super.touchesBegan(touches, withEvent: event)
if let touch = touches.first as? UITouch
{
self.meaningTextview.resignFirstResponder()
}
}
Pensé que en lugar de eso, publicaría el fragmento aquí:
Asegúrese de declarar soporte para el protocolo UITextViewDelegate
.
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
if([text isEqualToString:@"/n"]) {
[textView resignFirstResponder];
return NO;
}
return YES;
}
Actualización Swift 4.0:
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
if text == "/n" {
textView.resignFirstResponder()
return false
}
return true
}
Prueba esto .
NSInteger lengthOfText = [[textView.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] length];
Prueba esto :
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text{
if ([text isEqualToString:@"/n"]) {
[self.view endEditing:YES];
}
return YES;
}
Respuesta rápida:
override func viewDidLoad() {
super.viewDidLoad()
let tapGestureReconizer = UITapGestureRecognizer(target: self, action: "tap:")
view.addGestureRecognizer(tapGestureReconizer)
}
func tap(sender: UITapGestureRecognizer) {
view.endEditing(true)
}
Sé que esto ha sido respondido muchas veces, pero aquí están mis dos centavos para el problema.
Encontré las respuestas de samvermette y ribeto realmente útiles, y también el comentario de maxpower en la ribeto del ribeto . Pero hay un problema con esos enfoques. El problema que samvermette menciona en la samvermette del samvermette es que si el usuario quiere pegar algo con un salto de línea en su interior, el teclado se escondería sin pegar nada.
Así que mi enfoque es una mezcla de las tres soluciones mencionadas anteriormente y solo se comprueba si la cadena ingresada es una nueva línea cuando la longitud de la cadena es 1, por lo que nos aseguramos de que el usuario esté escribiendo en lugar de pegar.
Esto es lo que he hecho:
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
NSRange resultRange = [text rangeOfCharacterFromSet:[NSCharacterSet newlineCharacterSet] options:NSBackwardsSearch];
if ([text length] == 1 && resultRange.location != NSNotFound) {
[textView resignFirstResponder];
return NO;
}
return YES;
}
Sé que esto ya ha sido respondido pero realmente no me gusta usar el literal de cadena para la nueva línea, así que aquí está lo que hice.
- (BOOL)textView:(UITextView *)txtView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
if( [text rangeOfCharacterFromSet:[NSCharacterSet newlineCharacterSet]].location == NSNotFound ) {
return YES;
}
[txtView resignFirstResponder];
return NO;
}
Actualización Swift 4.0:
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
if (text as NSString).rangeOfCharacter(from: CharacterSet.newlines).location == NSNotFound {
return true
}
txtView.resignFirstResponder()
return false
}
Sé que no es la respuesta exacta a esta pregunta, pero encontré este hilo después de buscar en Internet una respuesta. Asumo que otros comparten ese sentimiento.
Esta es mi varianza del UITapGestureRecognizer, que me parece confiable y fácil de usar; simplemente configure el delegado de TextView en ViewController.
En lugar de ViewDidLoad, agrego el UITapGestureRecognizer cuando TextView se activa para editar:
-(void)textViewDidBeginEditing:(UITextView *)textView{
_tapRec = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tap:)];
[self.view addGestureRecognizer: _tapRec];
NSLog(@"TextView Did begin");
}
Cuando toco fuera de TextView, la vista finaliza el modo de edición y el UITapGestureRecognizer se elimina solo para que pueda continuar interactuando con otros controles en la vista.
-(void)tap:(UITapGestureRecognizer *)tapRec{
[[self view] endEditing: YES];
[self.view removeGestureRecognizer:tapRec];
NSLog(@"Tap recognized, tapRec getting removed");
}
Espero que esto ayude. Parece tan obvio, pero nunca he visto esta solución en ninguna parte de la web. ¿Estoy haciendo algo mal?
Solo resolví este problema de una manera diferente.
- Crea un botón que se colocará en el fondo.
- Desde el inspector de atributos, cambie el tipo de botón a personalizado y el botón se vuelve transparente.
- Expanda el botón para cubrir toda la vista y asegúrese de que esté detrás de todos los demás objetos. Una forma sencilla de hacerlo es arrastrar el botón a la parte superior de la vista de lista en la Vista
Control, arrastre el botón al archivo
viewController.h
y cree una acción (Evento enviado:viewController.h
interno) como:(IBAction)ExitKeyboard:(id)sender;
En
ViewController.m
debe verse como:(IBAction)ExitKeyboard:(id)sender { [self.view endEditing:TRUE]; }
- Ejecuta la aplicación, y cuando haces clic fuera de TextView, el teclado desaparece
También puede ocultar el teclado al tocar en la pantalla de visualización:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch * touch = [touches anyObject];
if(touch.phase == UITouchPhaseBegan) {
[txtDetail resignFirstResponder];
}
}
Una forma más elegante es descartar el teclado cuando el usuario toca en algún lugar fuera del marco del teclado.
Primero, configure la vista de su ViewController a la clase "UIControl" en el inspector de identidad en UIBuilder. Controle y arrastre la vista al archivo de encabezado de ViewController y vincúlelo como una acción con el evento como Retocar el interior, como:
ViewController.h
-(IBAction)dismissKeyboardOnTap:(id)sender;
En el archivo principal de ViewController, ViewController.m:
-(IBAction)dismissKeyboardOnTap:(id)sender
{
[[self view] endEditing:YES];
}
Puede requerir un toque doble o un toque largo utilizando técnicas similares. Es posible que deba configurar su ViewController para que sea un UITextViewDelegate y conectar el TextView al ViewController. Este método funciona tanto para UITextView como para UITextField.
Fuente: Big Nerd Ranch
EDITAR: También me gustaría agregar que si está utilizando un UIScrollView, la técnica anterior puede no funcionar tan fácilmente a través del Interface Builder. En ese caso, podría usar un UIGestureRecognizer y llamar al método [[self view] endEditing: YES] en su lugar. Un ejemplo sería:
-(void)ViewDidLoad{
....
UITapGestureRecognizer *tapRec = [[UITapGestureRecognizer alloc]
initWithTarget:self action:@selector(tap:)];
[self.view addGestureRecognizer: tapRec];
....
}
-(void)tap:(UITapGestureRecognizer *)tapRec{
[[self view] endEditing: YES];
}
Cuando el usuario toca fuera del teclado y no toca un espacio de entrada, el teclado se cerrará.
Usando el controlador de navegación para alojar una barra para descartar el teclado:
en el archivo .h:
UIBarButtonItem* dismissKeyboardButton;
en el archivo .m:
- (void)viewDidLoad {
dismissKeyboardButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(dismissKeyboard)];
}
-(void)textViewDidBeginEditing:(UITextView *)textView {
self.navigationItem.rightBarButtonItem = dismissKeyboardButton;
}
-(void)textFieldDidBeginEditing:(UITextField *)textField {
self.navigationItem.rightBarButtonItem = dismissKeyboardButton;
}
-(void)dismissKeyboard {
[self.textField resignFirstResponder];
[self.textView resignFirstResponder];
//or replace this with your regular right button
self.navigationItem.rightBarButtonItem = nil;
}
Utilicé este código para cambiar el respondedor.
- (BOOL)textView:(UITextView*) textView shouldChangeTextInRange: (NSRange) range replacementText: (NSString*) text
{
if ([text isEqualToString:@"/n"]) {
//[textView resignFirstResponder];
//return YES;
NSInteger nextTag = textView.tag + 1;
// Try to find next responder
UIResponder* nextResponder = [self.view viewWithTag:nextTag];
if (nextResponder) {
// Found next responder, so set it.
[nextResponder becomeFirstResponder];
} else {
// Not found, so remove keyboard.
[textView resignFirstResponder];
}
return NO;
return NO;
}
return YES;
}
código SWIFT
Implemente UITextViewDelegate en su clase / Vista así:
class MyClass: UITextViewDelegate { ...
establecer el textView delegado a sí mismo
myTextView.delegate = self
Y luego implementar lo siguiente:
func textViewDidChange(_ textView: UITextView) {
if textView.text.characters.count >= 1 {
if let lastChar = textView.text.characters.last {
if(lastChar == "/n"){
textView.text = textView.text.substring(to: textView.text.index(before: textView.text.endIndex))
textView.resignFirstResponder()
}
}
}
}
EDITAR Actualicé el código porque nunca es una buena idea cambiar la entrada del usuario en un campo de texto para un entorno de trabajo y no restablecer el estado después de que se complete el código de pirateo.
UITextView
no tiene ningún método al que se llamará cuando el usuario presione la tecla de retorno. Si desea que el usuario pueda agregar solo una línea de texto, use un UITextField
. Pulsar la devolución y ocultar el teclado para un UITextView
no sigue las pautas de la interfaz.
Incluso si desea hacer esto, implemente el método textView:shouldChangeTextInRange:replacementText:
de UITextViewDelegate
y en esa comprobación si el texto de reemplazo es /n
, oculte el teclado.
Puede haber otras formas pero no estoy al tanto de ninguna.
+ (void)addDoneButtonToControl:(id)txtFieldOrTextView
{
if([txtFieldOrTextView isKindOfClass:[UITextField class]])
{
txtFieldOrTextView = (UITextField *)txtFieldOrTextView;
}
else if([txtFieldOrTextView isKindOfClass:[UITextView class]])
{
txtFieldOrTextView = (UITextView *)txtFieldOrTextView;
}
UIToolbar* numberToolbar = [[UIToolbar alloc]initWithFrame:CGRectMake(0,
0,
[Global returnDeviceWidth],
50)];
numberToolbar.barStyle = UIBarStyleDefault;
UIBarButtonItem *btnDone = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"btn_return"]
style:UIBarButtonItemStyleBordered
target:txtFieldOrTextView
action:@selector(resignFirstResponder)];
numberToolbar.items = [NSArray arrayWithObjects:btnDone,nil];
[numberToolbar sizeToFit];
if([txtFieldOrTextView isKindOfClass:[UITextField class]])
{
((UITextField *)txtFieldOrTextView).inputAccessoryView = numberToolbar;
}
else if([txtFieldOrTextView isKindOfClass:[UITextView class]])
{
((UITextView *)txtFieldOrTextView).inputAccessoryView = numberToolbar;
}
}
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
{
if (range.length==0) {
if ([text isEqualToString:@"/n"]) {
[txtView resignFirstResponder];
if(textView.returnKeyType== UIReturnKeyGo){
[self PreviewLatter];
return NO;
}
return NO;
}
} return YES;
}
-(BOOL)textFieldShouldReturn:(UITextField *)textField; // called from textfield (keyboard)
-(BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text; // good tester function - thanks
-(BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
if([text isEqualToString:@"/n"])
[textView resignFirstResponder];
return YES;
}
yourtextView.delegate=self;
También agregue UITextViewDelegate
No olvides confirmar el protocolo.
SI no ha agregado if([text isEqualToString:@"/n"])
no puede editar