from delegate ios objective-c uitextfield uikeyboard

ios - delegate - textarea swift



¿Cómo puedo hacer que un UITextField se mueva hacia arriba cuando el teclado está presente? (30)

Con el SDK de iOS:

Tengo un UIView con UITextField s que UITextField un teclado. Lo necesito para poder:

  1. Permitir el desplazamiento de los contenidos de UIScrollView para ver los otros campos de texto una vez que se levanta el teclado

  2. Automáticamente "salta" (desplazándose hacia arriba) o acortando

Sé que necesito un UIScrollView . He intentado cambiar la clase de mi UIView a un UIScrollView pero todavía no puedo desplazar los cuadros de texto hacia arriba o hacia abajo.

¿Necesito tanto una UIView como una UIScrollView ? ¿Uno va dentro del otro?

¿Qué se debe implementar para desplazarse automáticamente al campo de texto activo?

Lo ideal es que la mayor parte de la configuración de los componentes se realice en Interface Builder. Me gustaría solo escribir código para lo que lo necesite.

Nota: la UIView (o UIScrollView ) con la que estoy trabajando aparece en una barra de pestañas ( UITabBar ), que debe funcionar con normalidad.

Editar: Estoy agregando la barra de desplazamiento solo para cuando se levante el teclado. Aunque no es necesario, siento que proporciona una mejor interfaz porque entonces el usuario puede desplazarse y cambiar los cuadros de texto, por ejemplo.

Lo tengo funcionando donde cambio el tamaño de marco de UIScrollView cuando el teclado sube y baja. Simplemente estoy usando:

-(void)textFieldDidBeginEditing:(UITextField *)textField { //Keyboard becomes visible scrollView.frame = CGRectMake(scrollView.frame.origin.x, scrollView.frame.origin.y, scrollView.frame.size.width, scrollView.frame.size.height - 215 + 50); //resize } -(void)textFieldDidEndEditing:(UITextField *)textField { //keyboard will hide scrollView.frame = CGRectMake(scrollView.frame.origin.x, scrollView.frame.origin.y, scrollView.frame.size.width, scrollView.frame.size.height + 215 - 50); //resize }

Sin embargo, esto no "avanza" automáticamente o centra los campos de texto inferiores en el área visible, que es lo que realmente me gustaría.


Para los programadores Swift :

Esto lo hará todo por usted, solo UITextFieldDelegate en su clase de controlador de vista e implemente el UITextFieldDelegate en su controlador de vista y establezca el delegado de textField en self

textField.delegate = self // Setting delegate of your UITextField to self

Implementar los métodos de devolución de llamada delegado:

func textFieldDidBeginEditing(textField: UITextField) { animateViewMoving(true, moveValue: 100) } func textFieldDidEndEditing(textField: UITextField) { animateViewMoving(false, moveValue: 100) } // Lifting the view up func animateViewMoving (up:Bool, moveValue :CGFloat){ let movementDuration:NSTimeInterval = 0.3 let movement:CGFloat = ( up ? -moveValue : moveValue) UIView.beginAnimations( "animateView", context: nil) UIView.setAnimationBeginsFromCurrentState(true) UIView.setAnimationDuration(movementDuration ) self.view.frame = CGRectOffset(self.view.frame, 0, movement) UIView.commitAnimations() }


Aquí encontré la solución más simple para manejar el teclado.

Solo tiene que copiar y pegar debajo del código de muestra y cambiar el campo de texto o cualquier vista que desee subir.

Paso 1

Simplemente copie y pegue debajo de dos métodos en su controlador

- (void)registerForKeyboardNotifications { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWasShown:) name:UIKeyboardDidShowNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillBeHidden:) name:UIKeyboardWillHideNotification object:nil]; } - (void)deregisterFromKeyboardNotifications { [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardDidHideNotification object:nil]; [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil]; }

Paso 2

registre y desregistre las notificaciones del teclado en los métodos viewWillAppear y viewWillDisappear respectivamente.

- (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; [self registerForKeyboardNotifications]; } - (void)viewWillDisappear:(BOOL)animated { [self deregisterFromKeyboardNotifications]; [super viewWillDisappear:animated]; }

Paso 3

Aquí viene la parte del alma, simplemente reemplaza tu campo de texto y cambia la altura cuánto quieres mover hacia arriba.

- (void)keyboardWasShown:(NSNotification *)notification { NSDictionary* info = [notification userInfo]; CGSize currentKeyboardSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size; //you need replace your textfield instance here CGPoint textFieldOrigin = self.tokenForPlaceField.frame.origin; CGFloat textFieldHeight = self.tokenForPlaceField.frame.size.height; CGRect visibleRect = self.view.frame; visibleRect.size.height -= currentKeyboardSize.height; if (!CGRectContainsPoint(visibleRect, textFieldOrigin)) { //you can add yor desired height how much you want move keypad up, by replacing "textFieldHeight" below CGPoint scrollPoint = CGPointMake(0.0, textFieldOrigin.y - visibleRect.size.height + textFieldHeight); //replace textFieldHeight to currentKeyboardSize.height, if you want to move up with more height [self.scrollView setContentOffset:scrollPoint animated:YES]; } } - (void)keyboardWillBeHidden:(NSNotification *)notification { [self.scrollView setContentOffset:CGPointZero animated:YES]; }

Referencia : bueno, por favor , aprecie a este tipo , que compartió este hermoso código, una solución limpia.

Espero que esto sería muy útil a alguien por ahí.


  1. Solo necesitarás un ScrollView si los contenidos que tienes ahora no caben en la pantalla del iPhone. (Si está agregando ScrollView como la vista de supervisión de los componentes. Para que TextField desplace hacia arriba cuando aparezca el teclado, no es necesario).

  2. Para mostrar los textfields sin estar ocultos por el teclado, la forma estándar es subir / bajar la vista con campos de texto cada vez que se muestra el teclado.

Aquí hay un código de ejemplo:

#define kOFFSET_FOR_KEYBOARD 80.0 -(void)keyboardWillShow { // Animate the current view out of the way if (self.view.frame.origin.y >= 0) { [self setViewMovedUp:YES]; } else if (self.view.frame.origin.y < 0) { [self setViewMovedUp:NO]; } } -(void)keyboardWillHide { if (self.view.frame.origin.y >= 0) { [self setViewMovedUp:YES]; } else if (self.view.frame.origin.y < 0) { [self setViewMovedUp:NO]; } } -(void)textFieldDidBeginEditing:(UITextField *)sender { if ([sender isEqual:mailTf]) { //move the main view, so that the keyboard does not hide it. if (self.view.frame.origin.y >= 0) { [self setViewMovedUp:YES]; } } } //method to move the view up/down whenever the keyboard is shown/dismissed -(void)setViewMovedUp:(BOOL)movedUp { [UIView beginAnimations:nil context:NULL]; [UIView setAnimationDuration:0.3]; // if you want to slide up the view CGRect rect = self.view.frame; if (movedUp) { // 1. move the view''s origin up so that the text field that will be hidden come above the keyboard // 2. increase the size of the view so that the area behind the keyboard is covered up. rect.origin.y -= kOFFSET_FOR_KEYBOARD; rect.size.height += kOFFSET_FOR_KEYBOARD; } else { // revert back to the normal state. rect.origin.y += kOFFSET_FOR_KEYBOARD; rect.size.height -= kOFFSET_FOR_KEYBOARD; } self.view.frame = rect; [UIView commitAnimations]; } - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; // register for keyboard notifications [[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]; // unregister for keyboard notifications while not visible. [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil]; [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil]; }


En textFieldDidBeginEditting y en textFieldDidEndEditing llame a la función [self animateTextField:textField up:YES] así:

-(void)textFieldDidBeginEditing:(UITextField *)textField { [self animateTextField:textField up:YES]; } - (void)textFieldDidEndEditing:(UITextField *)textField { [self animateTextField:textField up:NO]; } -(void)animateTextField:(UITextField*)textField up:(BOOL)up { const int movementDistance = -130; // tweak as needed const float movementDuration = 0.3f; // tweak as needed int movement = (up ? movementDistance : -movementDistance); [UIView beginAnimations: @"animateTextField" context: nil]; [UIView setAnimationBeginsFromCurrentState: YES]; [UIView setAnimationDuration: movementDuration]; self.view.frame = CGRectOffset(self.view.frame, 0, movement); [UIView commitAnimations]; }

Espero que este código te ayude.

En Swift 2

func animateTextField(textField: UITextField, up: Bool) { let movementDistance:CGFloat = -130 let movementDuration: Double = 0.3 var movement:CGFloat = 0 if up { movement = movementDistance } else { movement = -movementDistance } UIView.beginAnimations("animateTextField", context: nil) UIView.setAnimationBeginsFromCurrentState(true) UIView.setAnimationDuration(movementDuration) self.view.frame = CGRectOffset(self.view.frame, 0, movement) UIView.commitAnimations() } func textFieldDidBeginEditing(textField: UITextField) { self.animateTextField(textField, up:true) } func textFieldDidEndEditing(textField: UITextField) { self.animateTextField(textField, up:false) }

SWIFT 3

func animateTextField(textField: UITextField, up: Bool) { let movementDistance:CGFloat = -130 let movementDuration: Double = 0.3 var movement:CGFloat = 0 if up { movement = movementDistance } else { movement = -movementDistance } UIView.beginAnimations("animateTextField", context: nil) UIView.setAnimationBeginsFromCurrentState(true) UIView.setAnimationDuration(movementDuration) self.view.frame = self.view.frame.offsetBy(dx: 0, dy: movement) UIView.commitAnimations() } func textFieldDidBeginEditing(textField: UITextField) { self.animateTextField(textField: textField, up:true) } func textFieldDidEndEditing(textField: UITextField) { self.animateTextField(textField: textField, up:false) }


En realidad, es mejor usar la implementación de Apple, como se indica en los docs . Sin embargo, el código que proporcionan es defectuoso. Reemplace la parte que se encuentra en keyboardWasShown: justo debajo de los comentarios a lo siguiente:

NSDictionary* info = [aNotification userInfo]; CGRect keyPadFrame=[[UIApplication sharedApplication].keyWindow convertRect:[[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue] fromView:self.view]; CGSize kbSize =keyPadFrame.size; CGRect activeRect=[self.view convertRect:activeField.frame fromView:activeField.superview]; CGRect aRect = self.view.bounds; aRect.size.height -= (kbSize.height); CGPoint origin = activeRect.origin; origin.y -= backScrollView.contentOffset.y; if (!CGRectContainsPoint(aRect, origin)) { CGPoint scrollPoint = CGPointMake(0.0,CGRectGetMaxY(activeRect)-(aRect.size.height)); [backScrollView setContentOffset:scrollPoint animated:YES]; }

Los problemas con el código de Apple son los siguientes: (1) Siempre calculan si el punto está dentro del marco de la vista, pero es un ScrollView , por lo que es posible que ya se haya desplazado y usted deba tener en cuenta ese desplazamiento:

origin.y -= scrollView.contentOffset.y

(2) Cambian el contentOffset por la altura del teclado, pero queremos lo contrario (queremos cambiar el contentOffset por la altura visible en la pantalla, no por lo que no lo es):

activeField.frame.origin.y-(aRect.size.height)


He reunido una subclase universal UIScrollView , UITableView e incluso UICollectionView que se encarga de mover todos los campos de texto que se encuentran dentro del teclado.

Cuando el teclado está a punto de aparecer, la subclase encontrará la subvista que está a punto de editarse, y ajustará el marco y el desplazamiento del contenido para asegurarse de que la vista esté visible, con una animación que coincida con la ventana emergente del teclado. Cuando el teclado desaparece, restaura su tamaño anterior.

Básicamente debería funcionar con cualquier configuración, ya sea una interfaz basada en UITableView o una que consiste en vistas colocadas manualmente.

Aquí está la solución para mover los campos de texto fuera del camino del teclado.


Para Universal Solution , aquí estaba mi enfoque para implementar IQKeyboardManager .

Paso 1: - UITextField notificaciones globales de UITextField , UITextView y UIKeyboard en una clase de singleton. Lo llamo IQKeyboardManager .

Paso 2: - Si encuentro UIKeyboardWillShowNotification , UITextFieldTextDidBeginEditingNotification o UITextViewTextDidBeginEditingNotification notificaciones, trato de obtener la instancia topMostViewController de la jerarquía UIWindow.rootViewController . Para descubrir adecuadamente UITextField / UITextView en él, el marco de topMostViewController.view necesita ser ajustado.

Paso 3: topMostViewController.view distancia de movimiento esperada de topMostViewController.view con respecto al primer UITextField / UITextView respondido.

Paso 4: - topMostViewController.view.frame arriba / abajo de acuerdo con la distancia de movimiento esperada.

Paso 5: - Si se encuentra la UIKeyboardWillHideNotification , UITextFieldTextDidEndEditingNotification o UITextViewTextDidEndEditingNotification , nuevamente intento obtener la instancia topMostViewController de la jerarquía UIWindow.rootViewController .

Paso 6: - Calculé la distancia perturbada de topMostViewController.view que se debe restaurar a su posición original.

Paso 7: - topMostViewController.view.frame hacia abajo de acuerdo con la distancia perturbada.

Paso 8: - IQKeyboardManager la instancia de la clase IQKeyboardManager singleton en la carga de la aplicación, por lo que cada UITextField / UITextView en la aplicación se ajustará automáticamente de acuerdo con la distancia de movimiento esperada.

¡Eso es todo lo que IQKeyboardManager hace por ti sin NINGUNA LÍNEA DE CÓDIGO realmente! Solo es necesario arrastrar y soltar el archivo fuente relacionado al proyecto. IQKeyboardManager también es compatible con la orientación del dispositivo , la gestión automática de la barra de herramientas , la distancia entre teclas y el teclado y mucho más de lo que cree.


También tuve muchos problemas con una composición UIScrollView de varios UITextFields de UITextFields , de los cuales, uno o más de ellos se verían oscurecidos por el teclado cuando se estaban editando.

Aquí hay algunas cosas que debe considerar si su UIScrollView no se desplaza correctamente.

1) Asegúrese de que su contentSize sea mayor que el tamaño del marco UIScrollView . La forma de entender UIScrollViews es que UIScrollView es como una ventana de visualización en el contenido definido en contentSize. Entonces, para que el UIScrollview desplace a cualquier lugar, contentSize debe ser mayor que el UIScrollView . De lo contrario, no se requiere desplazamiento ya que todo lo definido en contentSize ya está visible. Por cierto, por defecto CGSizeZero = CGSizeZero .

2) Ahora que entiende que UIScrollView es realmente una ventana a su "contenido", la forma de asegurarse de que el teclado no UIScrollView''s "ventana" de visualización UIScrollView''s sería cambiar el tamaño de UIScrollView para que cuando el teclado esté presente, UIScrollView ventana de UIScrollView ajuste al tamaño original de UIScrollView frame.size.height menos la altura del teclado. Esto asegurará que su ventana sea solo esa pequeña área visible.

3) Aquí está el problema: cuando implementé esto por primera vez, pensé que tendría que obtener el CGRect del CGRect de texto editado y llamar UIScrollView''s método scrollRecToVisible UIScrollView''s . Implementé el método textFieldDidBeginEditing con la llamada al método scrollRecToVisible . Esto realmente funcionó con un extraño efecto secundario de que el desplazamiento colocaría el UITextField en su posición. Durante mucho tiempo no pude averiguar qué era. Luego comenté el método textFieldDidBeginEditing Delegate y ¡¡todo funciona !! (???). Al final resultó que, creo que el UIScrollView realidad lleva implícitamente implícitamente el UITextField editado actualmente a la ventana visible. Mi implementación del método UITextFieldDelegate y la posterior llamada a scrollRecToVisible fue redundante y fue la causa del extraño efecto secundario.

Así que aquí están los pasos para desplazar correctamente su UITextField en un UIScrollView hasta que aparezca el teclado.

// Implement viewDidLoad to do additional setup after loading the view, typically from a nib. - (void)viewDidLoad { [super viewDidLoad]; // register for keyboard notifications [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:self.view.window]; // register for keyboard notifications [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:self.view.window]; keyboardIsShown = NO; //make contentSize bigger than your scrollSize (you will need to figure out for your own use case) CGSize scrollContentSize = CGSizeMake(320, 345); self.scrollView.contentSize = scrollContentSize; } - (void)keyboardWillHide:(NSNotification *)n { NSDictionary* userInfo = [n userInfo]; // get the size of the keyboard CGSize keyboardSize = [[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size; // resize the scrollview CGRect viewFrame = self.scrollView.frame; // I''m also subtracting a constant kTabBarHeight because my UIScrollView was offset by the UITabBar so really only the portion of the keyboard that is leftover pass the UITabBar is obscuring my UIScrollView. viewFrame.size.height += (keyboardSize.height - kTabBarHeight); [UIView beginAnimations:nil context:NULL]; [UIView setAnimationBeginsFromCurrentState:YES]; [self.scrollView setFrame:viewFrame]; [UIView commitAnimations]; keyboardIsShown = NO; } - (void)keyboardWillShow:(NSNotification *)n { // This is an ivar I''m using to ensure that we do not do the frame size adjustment on the `UIScrollView` if the keyboard is already shown. This can happen if the user, after fixing editing a `UITextField`, scrolls the resized `UIScrollView` to another `UITextField` and attempts to edit the next `UITextField`. If we were to resize the `UIScrollView` again, it would be disastrous. NOTE: The keyboard notification will fire even when the keyboard is already shown. if (keyboardIsShown) { return; } NSDictionary* userInfo = [n userInfo]; // get the size of the keyboard CGSize keyboardSize = [[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size; // resize the noteView CGRect viewFrame = self.scrollView.frame; // I''m also subtracting a constant kTabBarHeight because my UIScrollView was offset by the UITabBar so really only the portion of the keyboard that is leftover pass the UITabBar is obscuring my UIScrollView. viewFrame.size.height -= (keyboardSize.height - kTabBarHeight); [UIView beginAnimations:nil context:NULL]; [UIView setAnimationBeginsFromCurrentState:YES]; [self.scrollView setFrame:viewFrame]; [UIView commitAnimations]; keyboardIsShown = YES; }

  1. Regístrese para las notificaciones de teclado en viewDidLoad
  2. Anular el registro de las nofiticaciones del teclado en viewDidUnload
  3. Asegúrese de que contentSize esté configurado y sea mayor que su UIScrollView en viewDidLoad
  4. Reduce el UIScrollView cuando el teclado está presente
  5. Revertir el UIScrollView cuando el teclado desaparece.
  6. Use un ivar para detectar si el teclado ya se muestra en la pantalla, ya que las notificaciones del teclado se envían cada vez que un UITextField tiene pestañas, incluso si el teclado ya está presente para evitar reducir el UIScrollView cuando ya está encogido

Una cosa a tener en cuenta es que la UIKeyboardWillShowNotification se UIKeyboardWillShowNotification incluso cuando el teclado ya se encuentre en la pantalla cuando se UITextField en otro UITextField . Me encargué de esto usando un ivar para evitar cambiar el tamaño del UIScrollView cuando el teclado ya está en la pantalla. ¡Cambiar el tamaño del UIScrollView cuando el teclado ya está allí sería desastroso!

Espero que este código les salve a muchos de ustedes muchos dolores de cabeza.


Ya hay muchas respuestas, pero ninguna de las soluciones anteriores tenía todas las funciones de posicionamiento sofisticadas necesarias para una animación "perfecta" sin errores, compatible con versiones anteriores y sin parpadeos. (error al animar cuadros / límites y contentOffset juntos, diferentes orientaciones de interfaz, teclado dividido de iPad, ...)
Déjame compartir mi solución:
(suponiendo que haya configurado la UIKeyboardWill(Show|Hide)Notification )

// Called when UIKeyboardWillShowNotification is sent - (void)keyboardWillShow:(NSNotification*)notification { // if we have no view or are not visible in any window, we don''t care if (!self.isViewLoaded || !self.view.window) { return; } NSDictionary *userInfo = [notification userInfo]; CGRect keyboardFrameInWindow; [[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] getValue:&keyboardFrameInWindow]; // the keyboard frame is specified in window-level coordinates. this calculates the frame as if it were a subview of our view, making it a sibling of the scroll view CGRect keyboardFrameInView = [self.view convertRect:keyboardFrameInWindow fromView:nil]; CGRect scrollViewKeyboardIntersection = CGRectIntersection(_scrollView.frame, keyboardFrameInView); UIEdgeInsets newContentInsets = UIEdgeInsetsMake(0, 0, scrollViewKeyboardIntersection.size.height, 0); // this is an old animation method, but the only one that retains compaitiblity between parameters (duration, curve) and the values contained in the userInfo-Dictionary. [UIView beginAnimations:nil context:NULL]; [UIView setAnimationDuration:[[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]]; [UIView setAnimationCurve:[[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue]]; _scrollView.contentInset = newContentInsets; _scrollView.scrollIndicatorInsets = newContentInsets; /* * Depending on visual layout, _focusedControl should either be the input field (UITextField,..) or another element * that should be visible, e.g. a purchase button below an amount text field * it makes sense to set _focusedControl in delegates like -textFieldShouldBeginEditing: if you have multiple input fields */ if (_focusedControl) { CGRect controlFrameInScrollView = [_scrollView convertRect:_focusedControl.bounds fromView:_focusedControl]; // if the control is a deep in the hierarchy below the scroll view, this will calculate the frame as if it were a direct subview controlFrameInScrollView = CGRectInset(controlFrameInScrollView, 0, -10); // replace 10 with any nice visual offset between control and keyboard or control and top of the scroll view. CGFloat controlVisualOffsetToTopOfScrollview = controlFrameInScrollView.origin.y - _scrollView.contentOffset.y; CGFloat controlVisualBottom = controlVisualOffsetToTopOfScrollview + controlFrameInScrollView.size.height; // this is the visible part of the scroll view that is not hidden by the keyboard CGFloat scrollViewVisibleHeight = _scrollView.frame.size.height - scrollViewKeyboardIntersection.size.height; if (controlVisualBottom > scrollViewVisibleHeight) { // check if the keyboard will hide the control in question // scroll up until the control is in place CGPoint newContentOffset = _scrollView.contentOffset; newContentOffset.y += (controlVisualBottom - scrollViewVisibleHeight); // make sure we don''t set an impossible offset caused by the "nice visual offset" // if a control is at the bottom of the scroll view, it will end up just above the keyboard to eliminate scrolling inconsistencies newContentOffset.y = MIN(newContentOffset.y, _scrollView.contentSize.height - scrollViewVisibleHeight); [_scrollView setContentOffset:newContentOffset animated:NO]; // animated:NO because we have created our own animation context around this code } else if (controlFrameInScrollView.origin.y < _scrollView.contentOffset.y) { // if the control is not fully visible, make it so (useful if the user taps on a partially visible input field CGPoint newContentOffset = _scrollView.contentOffset; newContentOffset.y = controlFrameInScrollView.origin.y; [_scrollView setContentOffset:newContentOffset animated:NO]; // animated:NO because we have created our own animation context around this code } } [UIView commitAnimations]; } // Called when the UIKeyboardWillHideNotification is sent - (void)keyboardWillHide:(NSNotification*)notification { // if we have no view or are not visible in any window, we don''t care if (!self.isViewLoaded || !self.view.window) { return; } NSDictionary *userInfo = notification.userInfo; [UIView beginAnimations:nil context:NULL]; [UIView setAnimationDuration:[[userInfo valueForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]]; [UIView setAnimationCurve:[[userInfo valueForKey:UIKeyboardAnimationCurveUserInfoKey] intValue]]; // undo all that keyboardWillShow-magic // the scroll view will adjust its contentOffset apropriately _scrollView.contentInset = UIEdgeInsetsZero; _scrollView.scrollIndicatorInsets = UIEdgeInsetsZero; [UIView commitAnimations]; }


developer.apple.com/library/ios/#documentation/StringsTextFonts/… documento detalla una solución a este problema. Mire el código fuente en ''Mover contenido que se encuentra debajo del teclado''. Es bastante sencillo.

EDIT: notó que hay un pequeño error en el ejemplo. Probablemente querrás escuchar en UIKeyboardWillHideNotificationlugar de UIKeyboardDidHideNotification. De lo contrario, la vista de desplazamiento detrás del teclado se recortará durante la animación de cierre del teclado.


La solución más fácil encontrada

- (void)textFieldDidBeginEditing:(UITextField *)textField { [self animateTextField: textField up: YES]; } - (void)textFieldDidEndEditing:(UITextField *)textField { [self animateTextField: textField up: NO]; } - (void) animateTextField: (UITextField*) textField up: (BOOL) up { const int movementDistance = 80; // tweak as needed const float movementDuration = 0.3f; // tweak as needed int movement = (up ? -movementDistance : movementDistance); [UIView beginAnimations: @"anim" context: nil]; [UIView setAnimationBeginsFromCurrentState: YES]; [UIView setAnimationDuration: movementDuration]; self.view.frame = CGRectOffset(self.view.frame, 0, movement); [UIView commitAnimations]; }


Nota : esta respuesta asume que tu campo de texto está en un scrollView.

Prefiero lidiar con esto usando scrollContentInset y scrollContentOffset en lugar de jugar con los marcos de mi vista.

Primero escuchemos las notificaciones del teclado.

//call this from viewWillAppear -(void)addKeyboardNotifications { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil]; } //call this from viewWillDisappear -(void)removeKeyboardNotifications{ [[NSNotificationCenter default Center] removeObserver:self name:UIKeyboardWillShowNotification object:nil]; [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil]; }

El siguiente paso es mantener una propiedad que represente al primer respondedor actual (UITextfield / UITextVew que actualmente tiene el teclado).

Usamos los métodos de delegado para establecer esta propiedad. Si está utilizando otro componente, necesitará algo similar.

Tenga en cuenta que para el campo de texto lo configuramos en didBeginEditing y para textView en shouldBeginEditing. Esto se debe a que textViewDidBeginEditing se llama después de UIKeyboardWillShowNotification por algún motivo.

-(BOOL)textViewShouldBeginEditing:(UITextView * )textView{ self.currentFirstResponder = textView; return YES; } -(void)textFieldDidBeginEditing:(UITextField *)textField{ self.currentFirstResponder = textField; }

Finalmente, aquí está la magia.

- (void)keyboardWillShow:(NSNotification*)aNotification{ NSDictionary* info = [aNotification userInfo]; CGRect kbFrame = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue]; /*if currentFirstResponder is overlayed by the keyboard, move it so it bottom ends where the keyboard begins*/ if(self.currentFirstResponder){ //keyboard origin in currentFirstResponderFrame CGPoint keyboardOrigin = [self.currentFirstResponder convertPoint:kbFrame.origin fromView:nil]; float spaceBetweenFirstResponderAndKeyboard = abs(self.currentFirstResponder.frame.size.height-keyboardOrigin.y); //only scroll the scrollview if keyboard overlays the first responder if(spaceBetweenFirstResponderAndKeyboard>0){ //if i call setContentOffset:animate:YES it behaves differently, not sure why [UIView animateWithDuration:0.25 animations:^{ [self.scrollView setContentOffset:CGPointMake(0,self.scrollView.contentOffset.y+spaceBetweenFirstResponderAndKeyboard)]; }]; } } //set bottom inset to the keyboard height so you can still scroll the whole content UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, kbFrame.size.height, 0.0); _scrollView.contentInset = contentInsets; _scrollView.scrollIndicatorInsets = contentInsets; } - (void)keyboardWillHide:(NSNotification*)aNotification{ UIEdgeInsets contentInsets = UIEdgeInsetsZero; _scrollView.contentInset = contentInsets; _scrollView.scrollIndicatorInsets = contentInsets; }


Sólo utilizando TextFields:

1a) Usando Interface Builder : seleccione Todos los campos de texto => Editar => Incrustar => ScrollView

1b) Incrustar manualmente TextFields en UIScrollView llamado scrollView

2) Establecer UITextFieldDelegate

3) Establezca cada textField.delegate = self; (o hacer conexiones en Interface Builder )

4) Copiar / Pegar:

- (void)textFieldDidBeginEditing:(UITextField *)textField { CGPoint scrollPoint = CGPointMake(0, textField.frame.origin.y); [scrollView setContentOffset:scrollPoint animated:YES]; } - (void)textFieldDidEndEditing:(UITextField *)textField { [scrollView setContentOffset:CGPointZero animated:YES]; }


Swift 4 .

Fácilmente puede moverse arriba y abajo UITextFieldO UIViewCon UIKeyBoardConAnimation

import UIKit class ViewController: UIViewController, UITextFieldDelegate { @IBOutlet var textField: UITextField! @IBOutlet var chatView: UIView! override func viewDidLoad() { super.viewDidLoad() NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillChange), name: .UIKeyboardWillChangeFrame, object: nil) } override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { textField.resignFirstResponder() } @objc func keyboardWillChange(notification: NSNotification) { let duration = notification.userInfo![UIKeyboardAnimationDurationUserInfoKey] as! Double let curve = notification.userInfo![UIKeyboardAnimationCurveUserInfoKey] as! UInt let curFrame = (notification.userInfo![UIKeyboardFrameBeginUserInfoKey] as! NSValue).cgRectValue let targetFrame = (notification.userInfo![UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue let deltaY = targetFrame.origin.y - curFrame.origin.y print("deltaY",deltaY) UIView.animateKeyframes(withDuration: duration, delay: 0.0, options: UIViewKeyframeAnimationOptions(rawValue: curve), animations: { self.chatView.frame.origin.y+=deltaY // Here You Can Change UIView To UITextField },completion: nil) } func textFieldShouldReturn(_ textField: UITextField) -> Bool { textField.resignFirstResponder() return true } }


@ usuario271753

Para obtener su vista de nuevo a añadir original:

-(BOOL)textFieldShouldReturn:(UITextField *)textField{ [textField resignFirstResponder]; [self setViewMovedUp:NO]; return YES; }


Esta es la solución usando Swift.

import UIKit class ExampleViewController: UIViewController, UITextFieldDelegate { @IBOutlet var scrollView: UIScrollView! @IBOutlet var textField1: UITextField! @IBOutlet var textField2: UITextField! @IBOutlet var textField3: UITextField! @IBOutlet var textField4: UITextField! @IBOutlet var textField5: UITextField! var activeTextField: UITextField! // MARK: - View override func viewDidLoad() { super.viewDidLoad() self.textField1.delegate = self self.textField2.delegate = self self.textField3.delegate = self self.textField4.delegate = self self.textField5.delegate = self } override func viewWillAppear(animated: Bool) { super.viewWillAppear(animated) self.registerForKeyboardNotifications() } override func viewWillDisappear(animated: Bool) { super.viewWillDisappear(animated) self.unregisterFromKeyboardNotifications() } // MARK: - Keyboard // Call this method somewhere in your view controller setup code. func registerForKeyboardNotifications() { let center: NSNotificationCenter = NSNotificationCenter.defaultCenter() center.addObserver(self, selector: "keyboardWasShown:", name: UIKeyboardDidShowNotification, object: nil) center.addObserver(self, selector: "keyboardWillBeHidden:", name: UIKeyboardWillHideNotification, object: nil) } func unregisterFromKeyboardNotifications () { let center: NSNotificationCenter = NSNotificationCenter.defaultCenter() center.removeObserver(self, name: UIKeyboardDidShowNotification, object: nil) center.removeObserver(self, name: UIKeyboardWillHideNotification, object: nil) } // Called when the UIKeyboardDidShowNotification is sent. func keyboardWasShown (notification: NSNotification) { let info : NSDictionary = notification.userInfo! let kbSize = (info.objectForKey(UIKeyboardFrameBeginUserInfoKey)?.CGRectValue() as CGRect!).size let contentInsets: UIEdgeInsets = UIEdgeInsetsMake(0.0, 0.0, kbSize.height, 0.0); scrollView.contentInset = contentInsets; scrollView.scrollIndicatorInsets = contentInsets; // If active text field is hidden by keyboard, scroll it so it''s visible // Your app might not need or want this behavior. var aRect = self.view.frame aRect.size.height -= kbSize.height; if (!CGRectContainsPoint(aRect, self.activeTextField.frame.origin) ) { self.scrollView.scrollRectToVisible(self.activeTextField.frame, animated: true) } } // Called when the UIKeyboardWillHideNotification is sent func keyboardWillBeHidden (notification: NSNotification) { let contentInsets = UIEdgeInsetsZero; scrollView.contentInset = contentInsets; scrollView.scrollIndicatorInsets = contentInsets; } // MARK: - Text Field func textFieldDidBeginEditing(textField: UITextField) { self.activeTextField = textField } func textFieldDidEndEditing(textField: UITextField) { self.activeTextField = nil } }


Para volver al estado de vista original, agregue:

-(void)textFieldDidEndEditing:(UITextField *)sender { //move the main view, so that the keyboard does not hide it. if (self.view.frame.origin.y < 0) { [self setViewMovedUp:NO]; } }


Poca solución que funciona para muchos campos de UITextFields.

#pragma mark UIKeyboard handling #define kMin 150 -(void)textFieldDidBeginEditing:(UITextField *)sender { if (currTextField) { [currTextField release]; } currTextField = [sender retain]; //move the main view, so that the keyboard does not hide it. if (self.view.frame.origin.y + currTextField.frame.origin. y >= kMin) { [self setViewMovedUp:YES]; } } //method to move the view up/down whenever the keyboard is shown/dismissed -(void)setViewMovedUp:(BOOL)movedUp { [UIView beginAnimations:nil context:NULL]; [UIView setAnimationDuration:0.3]; // if you want to slide up the view CGRect rect = self.view.frame; if (movedUp) { // 1. move the view''s origin up so that the text field that will be hidden come above the keyboard // 2. increase the size of the view so that the area behind the keyboard is covered up. rect.origin.y = kMin - currTextField.frame.origin.y ; } else { // revert back to the normal state. rect.origin.y = 0; } self.view.frame = rect; [UIView commitAnimations]; } - (void)keyboardWillShow:(NSNotification *)notif { //keyboard will be shown now. depending for which textfield is active, move up or move down the view appropriately if ([currTextField isFirstResponder] && currTextField.frame.origin.y + self.view.frame.origin.y >= kMin) { [self setViewMovedUp:YES]; } else if (![currTextField isFirstResponder] && currTextField.frame.origin.y + self.view.frame.origin.y < kMin) { [self setViewMovedUp:NO]; } } - (void)keyboardWillHide:(NSNotification *)notif { //keyboard will be shown now. depending for which textfield is active, move up or move down the view appropriately if (self.view.frame.origin.y < 0 ) { [self setViewMovedUp:NO]; } } - (void)viewWillAppear:(BOOL)animated { // register for keyboard notifications [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:self.view.window]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:self.view.window]; } - (void)viewWillDisappear:(BOOL)animated { // unregister for keyboard notifications while not visible. [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil]; }


Utilice este tercero que no necesita escribir ni una línea

github.com/hackiftekhar/IQKeyboardManager

descargue el proyecto y arrastre y suelte IQKeyboardManager en su proyecto. Si encuentra algún problema, lea el documento README.

Chicos realmente su eliminar el dolor de cabeza para administrar el teclado ...

Gracias y mucha suerte!


prueba este pequeño truco ...

- (void)textFieldDidBeginEditing:(UITextField *)textField { [self animateTextField: textField up: YES]; } - (void)textFieldDidEndEditing:(UITextField *)textField { [self animateTextField: textField up: NO]; } - (void) animateTextField: (UITextField*) textField up: (BOOL) up { const int movementDistance = textField.frame.origin.y / 2; // tweak as needed const float movementDuration = 0.3f; // tweak as needed int movement = (up ? -movementDistance : movementDistance); [UIView beginAnimations: @"anim" context: nil]; [UIView setAnimationBeginsFromCurrentState: YES]; [UIView setAnimationDuration: movementDuration]; self.view.frame = CGRectOffset(self.view.frame, 0, movement); [UIView commitAnimations]; }

Feliz codificación:) ....


Aquí está la solución de pirateo que se me ocurrió para un diseño específico. Esta solución es similar a la solución de Matt Gallagher en la que se desplaza una sección a la vista. Todavía soy nuevo en el desarrollo de iPhone y no estoy familiarizado con el funcionamiento de los diseños. Por lo tanto, este hack.

Mi implementación necesitaba admitir el desplazamiento al hacer clic en un campo y también el desplazamiento cuando el usuario selecciona el siguiente en el teclado.

Tuve un UIView con una altura de 775. Los controles se distribuyen básicamente en grupos de 3 en un espacio grande. Terminé con el siguiente diseño de IB.

UIView -> UIScrollView -> [UI Components]

Aquí viene el hack

Configuré la altura de UIScrollView a 500 unidades más que el diseño real (1250). Luego creé una matriz con las posiciones absolutas a las que necesito desplazarme y una función simple para obtenerlas según el número de etiqueta IB.

static NSInteger stepRange[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 140, 140, 140, 140, 140, 410 }; NSInteger getScrollPos(NSInteger i) { if (i < TXT_FIELD_INDEX_MIN || i > TXT_FIELD_INDEX_MAX) { return 0 ; return stepRange[i] ; }

Ahora todo lo que necesita hacer es usar las siguientes dos líneas de código en textFieldDidBeginEditing y textFieldShouldReturn (la última si está creando una navegación de campo siguiente)

CGPoint point = CGPointMake(0, getScrollPos(textField.tag)) ; [self.scrollView setContentOffset:point animated:YES] ;

Un ejemplo.

- (void) textFieldDidBeginEditing:(UITextField *)textField { CGPoint point = CGPointMake(0, getScrollPos(textField.tag)) ; [self.scrollView setContentOffset:point animated:YES] ; } - (BOOL)textFieldShouldReturn:(UITextField *)textField { NSInteger nextTag = textField.tag + 1; UIResponder* nextResponder = [textField.superview viewWithTag:nextTag]; if (nextResponder) { [nextResponder becomeFirstResponder]; CGPoint point = CGPointMake(0, getScrollPos(nextTag)) ; [self.scrollView setContentOffset:point animated:YES] ; } else{ [textField resignFirstResponder]; } return YES ; }

Este método no se "desplaza hacia atrás" como lo hacen otros métodos. Esto no era un requisito. Nuevamente, esto fue para un UIView bastante ''alto'', y no tuve días para aprender los motores de diseño interno.


Cuando UITextFieldestá en un UITableViewCelldesplazamiento debe configurarse automáticamente.

Si no lo está, probablemente se deba a un código / configuración incorrectos de la vista de tabla.

Por ejemplo, cuando recargué mi tabla larga con una UITextFielden la parte inferior de la siguiente manera,

-(void) viewWillAppear:(BOOL)animated { [self.tableview reloadData]; }

luego mi campo de texto en la parte inferior quedó oculto por el teclado que apareció cuando hice clic dentro del campo de texto.

Para arreglar esto tuve que hacer esto -

-(void) viewWillAppear:(BOOL)animated { //add the following line to fix issue [super viewWillAppear:animated]; [self.tableview reloadData]; }


El código de RPDP mueve con éxito el campo de texto fuera del camino del teclado. Pero cuando se desplaza hacia la parte superior después de usar y descartar el teclado, la parte superior se ha desplazado hacia arriba fuera de la vista. Esto es cierto para el simulador y el dispositivo. Para leer el contenido en la parte superior de esa vista, uno tiene que volver a cargar la vista.

¿No se supone que su siguiente código haga retroceder la vista?

else { // revert back to the normal state. rect.origin.y += kOFFSET_FOR_KEYBOARD; rect.size.height -= kOFFSET_FOR_KEYBOARD; }


Hay tantas soluciones, pero he pasado algunas horas antes de que empiece a funcionar. Por lo tanto, coloco este código aquí (solo pégalo al proyecto, no es necesario realizar ninguna modificación):

@interface RegistrationViewController : UIViewController <UITextFieldDelegate>{ UITextField* activeField; UIScrollView *scrollView; } @end - (void)viewDidLoad { [super viewDidLoad]; scrollView = [[UIScrollView alloc] initWithFrame:self.view.frame]; //scrool view must be under main view - swap it UIView* natView = self.view; [self setView:scrollView]; [self.view addSubview:natView]; CGSize scrollViewContentSize = self.view.frame.size; [scrollView setContentSize:scrollViewContentSize]; [self registerForKeyboardNotifications]; } - (void)viewDidUnload { activeField = nil; scrollView = nil; [self unregisterForKeyboardNotifications]; [super viewDidUnload]; } - (void)registerForKeyboardNotifications { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShown:) name:UIKeyboardWillShowNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillBeHidden:) name:UIKeyboardWillHideNotification object:nil]; } -(void)unregisterForKeyboardNotifications { [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil]; // unregister for keyboard notifications while not visible. [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil]; } - (void)keyboardWillShown:(NSNotification*)aNotification { NSDictionary* info = [aNotification userInfo]; CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size; CGRect frame = self.view.frame; frame.size.height -= kbSize.height; CGPoint fOrigin = activeField.frame.origin; fOrigin.y -= scrollView.contentOffset.y; fOrigin.y += activeField.frame.size.height; if (!CGRectContainsPoint(frame, fOrigin) ) { CGPoint scrollPoint = CGPointMake(0.0, activeField.frame.origin.y + activeField.frame.size.height - frame.size.height); [scrollView setContentOffset:scrollPoint animated:YES]; } } - (void)keyboardWillBeHidden:(NSNotification*)aNotification { [scrollView setContentOffset:CGPointZero animated:YES]; } - (void)textFieldDidBeginEditing:(UITextField *)textField { activeField = textField; } - (void)textFieldDidEndEditing:(UITextField *)textField { activeField = nil; } -(BOOL) textFieldShouldReturn:(UITextField *)textField { [textField resignFirstResponder]; return YES; }

PD: Espero que el código ayude a alguien a hacer el efecto deseado rápidamente. (Xcode 4.5)


No estoy seguro de si mover la vista hacia arriba es el enfoque correcto, lo hice de una manera diferente, cambiando el tamaño del UIScrollView. Lo expliqué en detalle en un pequeño article


No requiere una vista de desplazamiento para poder mover el marco de vista. Puede cambiar el marco de una viewcontroller''svista para que la vista completa se mueva hacia arriba lo suficiente como para colocar el campo de texto del primer respondedor sobre el teclado. Cuando me encontré con este problema, creé una subclase UIViewControllerque hace esto. Observa que en el teclado aparecerá una notificación y encuentra la primera subvista de respuesta y (si es necesario) anima la vista principal hacia arriba solo lo suficiente para que la primera respuesta esté por encima del teclado. Cuando el teclado se oculta, anima la vista donde estaba.

Para usar esta subclase, haga que su controlador de vista personalizado sea una subclase de GMKeyboardVC y herede esta característica (solo asegúrese de implementar viewWillAppeary viewWillDisappeardeben llamar super). La clase está en github .


Según los documentos , a partir de iOS 3.0, la UITableViewControllerclase redimensiona y vuelve a colocar automáticamente su vista de tabla cuando hay edición en línea de campos de texto. Creo que no es suficiente colocar el campo de texto dentro de una, UITableViewCellcomo algunos han indicado.

De la documentación :

Un controlador de vista de tabla admite la edición en línea de las filas de vista de tabla; Si, por ejemplo, las filas tienen campos de texto incrustados en el modo de edición, desplaza la fila que se está editando sobre el teclado virtual que se muestra.


Shiun dijo: "Al final resultó que, creo que UIScrollView en realidad lleva implícitamente implícitamente el UITextField editado actualmente a la ventana visible" Esto parece ser cierto para iOS 3.1.3, pero no 3.2, 4.0 o 4.1. Tuve que agregar un scrollRectToVisible explícito para hacer visible el UITextField en iOS> = 3.2.


Sido la búsqueda de un buen tutorial para principiantes en la materia, que se encuentra el mejor tutorial here .

En el MIScrollView.hejemplo al final del tutorial, asegúrese de poner un espacio en

@property (nonatomic, retain) id backgroundTapDelegate;

como ves.


Una cosa a considerar es si alguna vez desea utilizar un UITextFieldsolo. No he encontrado ninguna aplicación para iPhone bien diseñada que realmente use UITextFieldsfuera de UITableViewCells.

Será un trabajo adicional, pero le recomiendo que implemente todas las vistas de entrada de datos y vistas de tabla. Agregue un UITextViewa su UITableViewCells.