Pregunta

Tengo una aplicación donde, en Interface Builder , que estableció un UIView que tiene un campo de texto en la parte inferior de la vista. Cuando ejecuto la aplicación y tratar de introducir texto en ese campo, el teclado se desliza hacia arriba overtop del campo así que no puedo ver lo que estoy escribiendo hasta que ocultar el teclado de nuevo.

Alguien más con este problema y ha encontrado una buena manera de resolverlo sin que ninguna de hacer la vista padre desplazable o mover el campo de texto más arriba en la pantalla?

¿Fue útil?

Solución

La solución habitual es deslizar el campo (y todo por encima de ella) con una animación, y luego retractarse cuando haya terminado. Puede que tenga que poner el campo de texto y algunos de los otros artículos en otro punto de vista y deslice la vista como una unidad. (Yo llamo a estas cosas "placas", como en "placas tectónicas", pero eso es sólo conmigo). Pero aquí es la idea general si no es necesario conseguir la suposición.

- (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];
}

Otros consejos

Este hecho maravillas para mí deslizamiento uitextfields

En particular, se tiene la ventaja de calcular la distancia de animación de diapositivas en función de la posición del campo de texto.

IQKeyboardManager hacer esto para usted con NO línea de código , sólo es necesario para arrastrar y soltar archivos fuente Participa en el proyecto. IQKeyboardManager también el apoyo Orientación dispositivo , Administración UIToolbar automática , keyboardDistanceFromTextField y mucho más de lo que cree.

introducir descripción de la imagen aquí

Aquí está el diagrama de flujo de control: Flow Chart Control

Paso 1: - Añadido notificaciones globales de UITextField, UITextView y UIKeyboard en una clase Singleton. Lo he llamado IQKeyboardManager .

Paso 2: - Si se encuentran las notificaciones UIKeyboardWillShowNotification, UITextFieldTextDidBeginEditingNotification o UITextViewTextDidBeginEditingNotification, a continuación, tratar de conseguir topMostViewController ejemplo de la jerarquía UIWindow.rootViewController. Con el fin de descubrir adecuadamente UITextField / UITextView en él, marco de topMostViewController.view necesita ser ajustado.

Paso 3: -. Calculado esperado distancia de movimiento de topMostViewController.view con respecto a respondido primera UITextField / UITextView

Paso 4: -. topMostViewController.view.frame Movido hacia arriba / abajo de acuerdo a la distancia medida que se espera

Paso 5: -. Si se encuentra UIKeyboardWillHideNotification, UITextFieldTextDidEndEditingNotification o notificación UITextViewTextDidEndEditingNotification, luego otra vez tratan de conseguir topMostViewController ejemplo de la jerarquía UIWindow.rootViewController

Paso 6: -. Calculado distancia perturbado de topMostViewController.view que necesita ser restaurado a su posición original

Paso 7: -. topMostViewController.view.frame restaurada en función de la distancia a perturbado

Paso 8: - crea la instancia singleton IQKeyboardManager instancia de clase de la carga de aplicación, por lo cada UITextField / UITextView en la aplicación ajustará automáticamente en función de la distancia medida que se espera.

Eso es todo

Para ampliar la respuesta Amagrammer, aquí es una clase de ejemplo:

LoginViewController.h

@interface LoginViewController : UIViewController <UITextFieldDelegate> {

}

@property (nonatomic, retain) IBOutlet UITextField    *emailTextField;
@property (nonatomic, retain) IBOutlet UITextField    *passwordTextField;

Aviso estamos implementando el "UITextFieldDelegate"

LoginViewController.m

@implementation LoginViewController
@synthesize emailTextField=_emailTextField;
@synthesize passwordTextField=_passwordTextField;

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        //Register to receive an update when the app goes into the backround
        //It will call our "appEnteredBackground method
        [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(appEnteredBackground)
                                                 name:UIApplicationDidEnterBackgroundNotification
                                               object:nil];
    }
    return self;
}


- (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];
}

- (void)textFieldDidBeginEditing:(UITextField *)textField
{
    [self animateTextField: textField up: YES];
}


- (void)textFieldDidEndEditing:(UITextField *)textField
{
    [self animateTextField: textField up: NO];
}

- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
    [textField resignFirstResponder];
    return YES;
}
//This is called when the app goes into the background.
//We must reset the responder because animations will not be saved
- (void)appEnteredBackground{
    [self.emailTextField resignFirstResponder];
    [self.passwordTextField resignFirstResponder];
}

¿Qué hay de la solución oficial: contenido que se encuentra debajo del teclado en movimiento

  

El ajuste de su contenido por lo general implica el cambio de tamaño temporalmente uno o   más vistas y posicionarlos para que los restos de objetos de texto   visible. La forma más sencilla de gestionar los objetos de texto con el teclado es   incorporarlos dentro de un objeto UIScrollView (o una de sus subclases   como UITableView). Cuando se visualiza el teclado, todo lo que tiene que hacer   se restablece el área de contenido de la vista de desplazamiento y desplazar la deseada   objeto de texto en su posición. Por lo tanto, en respuesta a una   UIKeyboardDidShowNotification, su método de control haría lo   siguiente:

     
      
  1. Obtener el tamaño del teclado.
  2.   
  3. Ajustar el contenido del recuadro inferior de la vista de desplazamiento por el teclado   altura.
  4.   
  5. Desplazar el campo de texto de destino a la vista.
  6.   
// Call this method somewhere in your view controller setup code.
- (void)registerForKeyboardNotifications
{
    [[NSNotificationCenter defaultCenter] addObserver:self
            selector:@selector(keyboardWasShown:)
            name:UIKeyboardDidShowNotification object:nil];

   [[NSNotificationCenter defaultCenter] addObserver:self
             selector:@selector(keyboardWillBeHidden:)
             name:UIKeyboardWillHideNotification object:nil];

}

// Called when the UIKeyboardDidShowNotification is sent.
- (void)keyboardWasShown:(NSNotification*)aNotification
{
    NSDictionary* info = [aNotification userInfo];
    CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;

    UIEdgeInsets contentInsets = 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.
    CGRect aRect = self.view.frame;
    aRect.size.height -= kbSize.height;
    if (!CGRectContainsPoint(aRect, activeField.frame.origin) ) {
        [self.scrollView scrollRectToVisible:activeField.frame animated:YES];
    }
}

// Called when the UIKeyboardWillHideNotification is sent
- (void)keyboardWillBeHidden:(NSNotification*)aNotification
{
    UIEdgeInsets contentInsets = UIEdgeInsetsZero;
    scrollView.contentInset = contentInsets;
    scrollView.scrollIndicatorInsets = contentInsets;
}

Tengo frente a la misma cuestión en las células UITableView campo de texto. Puedo solucionar este problema mediante la implementación siguiente método para escuchar la notificación teclado.

Observador de las notificaciones aquí:

[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(keyboardWasShown:) name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(keyboardWillBeHidden:) name:UIKeyboardWillHideNotification object:nil];

manejar esas notificación mediante el siguiente función:

(void)keyboardWasShown:(NSNotification*)aNotification 
(void)keyboardWillBeHidden:(NSNotification*)aNotification 

Mira esto. Sin problemas para usted.

Esta solución es muy ordenada. Todo lo que tiene que hacer es añadir los campos de texto en un UIScrollView y cambiar su clase con el TPKeyboardAvoidingScollView, si está utilizando guiones gráficos. La vista de desplazamiento se extiende de tal manera que sería detectar cuando el teclado es visible y se moverá por encima de teclado a una distancia razonable. Es la solución perfecta, ya que su independiente de su UIViewController. Cada cosa necesaria se realiza dentro de la clase antes mencionada. Gracias Michael Tyson et all.

TPKeyboardAvoiding

A continuación se muestra una versión rápida de la respuesta de Amagrammer. Además, una variación utilizando el evento UIKeyboardWillShowNotification ya que necesitaba saber el tamaño teclados antes de mover la vista del camino.

var keyboardHeight:CGFloat = 0

override func viewDidLoad() {
    super.viewDidLoad()
    NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillChange:", name: UIKeyboardWillShowNotification, object: nil)
}

func textFieldDidBeginEditing(textField: UITextField) {
    //keyboardWillChange (below) is used instead of textFieldDidBeginEditing because textFieldDidBeginEditing
    //is called before the UIKeyboardWillShowNotification necessary to determine the keyboard height.
}

func textFieldDidEndEditing(textField: UITextField) {
    animateTextField(false)
}

func animateTextField(textFieldUp:Bool) {
    let movementDistance:CGFloat = keyboardHeight
    let movementDuration = 0.3

    let movement:CGFloat = (textFieldUp ? -movementDistance : movementDistance)

    UIView.beginAnimations("anim", context: nil)
    UIView.setAnimationBeginsFromCurrentState(true)
    UIView.setAnimationDuration(movementDuration)
    self.view.frame = CGRectOffset(self.view.frame, 0, movement)
    UIView.commitAnimations()
}

func keyboardWillChange(notification:NSNotification) {
    let keyboardRect:CGRect = ((notification.userInfo![UIKeyboardFrameEndUserInfoKey])?.CGRectValue)!
    keyboardHeight = keyboardRect.height
    animateTextField(true)
}

Hubo un gran tutorial en edición campos de texto sin oscurecer (vínculo roto ahora, aquí hay un enlace Wayback: https://web.archive.org/web/20091123074029/http://acts-as-geek.blogspot.com/2009 /11/editing-textfields-without-obscuring.html ). Se muestra cómo mover un UIView existente en un UIScrollView, y para desplazarse de forma automática cuando aparezca el teclado.

He actualizado un poco para calcular la altura correcta para el UIScrollView cuando hay controles (como un UITabBar) por debajo de la UIScrollBar. Ver posterior actualización UIView .

Aquí hay una solución utilizando Xcode5, iOS7:

Utilice los bloques UITextfieldDelegate y animación.

Esto es casi todo el código para la ViewController pero quería incluir el código de delegado para los que siguen un poco familiarizado con el patrón de delegado (como yo). También incluí código para ocultar el teclado cuando se toca fuera de la TextView.

Puede mover los puntos de vista (botones, campos de texto, etc.) tan alto como desee sólo asegúrese de volver a ponerlos en su lugar (100 luego -100).

@interface ViewController () <UITextFieldDelegate>
@property (strong, nonatomic) IBOutlet UITextField *MyTextField;

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.MyTextField.delegate = self;

}

- (void)textFieldDidBeginEditing:(UITextField *)textField
{
      NSLog(@"text began editing");

      CGPoint MyPoint = self.MyTextField.center;

      [UIView animateWithDuration:0.3
                    animations:^{

                    self.MyTextField.center = CGPointMake(MyPoint.x, MyPoint.y - 100);
                                }];
}

- (void)textFieldDidEndEditing:(UITextField *)textField
{
     NSLog(@"text ENDED editing");

     CGPoint MyPoint = self.MyTextField.center;

     [UIView animateWithDuration:0.3
                 animations:^{

     self.MyTextField.center = CGPointMake(MyPoint.x, MyPoint.y + 100);
                             }];
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
     [self.view endEditing:YES];
}

Creo que una manera sería para mover su posición de puntos de vista todo a partir de (x, y) a (x, y keybaardHeight) cuando se hace clic en el campo de texto y poner de nuevo cuando se desestimó el teclado, puede tener un aspecto un poco extraño como la vista apenas viene hacia arriba (tal vez no sería malo si se anima ella).

- (void)textFieldDidBeginEditing:(UITextField *)textField
{
    CGRect frame=self.view.frame;
    frame.origin=CGPointMake(x...//set point here
    self.view.frame=frame;
}

Además de la solución de Amagrammer, si está utilizando cocos2d en modo vertical cambiar esta línea:

self.view.frame = CGRectOffset(self.view.frame, 0, movement);

a esto:

[CCDirector sharedDirector].openGLView.frame = CGRectOffset([CCDirector sharedDirector].openGLView.frame, movement, 0);

Si está utilizando cocos2d en modo horizontal, realice el cambio anterior y cambiar los valores up en textFieldDidBeginEditing: y textFieldDidEndEditing:

- (void)textFieldDidBeginEditing:(UITextField *)textField {
    [self animateTextField:textField up:NO];
}

- (void)textFieldDidEndEditing:(UITextField *)textField {
    [self animateTextField:textField up:YES];
}

Yo tenía el mismo problema y encontré GTKeyboardHelper ser una salida fácil.

Después de arrastrar y soltar el marco de su proyecto, incluir el archivo de cabecera. Descargar y abrir el proyecto de ejemplo, a continuación, arrastre el objeto "ayudante del teclado" de la sección de objetos en el xib a la sección de objetos en el constructor de interfaces de su proyecto.

Arrastrar y soltar todos sus puntos de vista al ser hijos de la "ayudante del teclado".

Arrastrar y soltar marco que utilizo en mis proyectos. Es compatible con el despido automático cuando puntea fuera de un primer nivel de respuesta o cuando se desplaza.

GTKeyboardHelper

Sólo tiene que deslizar la vista hacia arriba y hacia abajo según sea necesario:

- (void)textFieldDidEndEditing:(UITextField *)textField {
    self.currentTextField = nil;
    [self animateTextField: textField up: NO];
}

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

- (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 animateWithDuration:movementDuration animations:^{
        self.view.frame = CGRectOffset(self.view.frame, 0, movement);
    }];
}

No se olvide de establecer self como UITextFieldDelegate y como el delegate textField real.

(Gracias a Ammagrammer, esto es sólo una respuesta más corto utilizando bloques para animaciones)

Tengo algo más si lo desea. El punto aquí es que desea establecer el centro de su UIView en el campo de texto que se está editando.

Antes de eso, usted tiene que guardar su INITIAL_CENTER , como CGPoint , de self.view.center y su INITIAL_VIEW como < strong> CGRect self.view.frame en una propiedad const.

Se puede crear un método como este:

- (void) centerOn: (CGRect) fieldFrame {

    // Set up the center by taking the original view center
    CGPoint center = CGPointMake(INITIAL_CENTER.x,
                             INITIAL_CENTER.y - ((fieldFrame.origin.y + fieldFrame.size.height/2) - INITIAL_CENTER.y));


    [UIView beginAnimations:@"centerViewOnField" context:nil];
    [UIView setAnimationDuration:0.50];

    if (CGRectEqualToRect(fieldFrame,INITIAL_VIEW)) {
        self.view.frame = INITIAL_VIEW;
        [self.view setCenter:INITIAL_CENTER];
    } else {
        [self.view setCenter:center];
    }


    [UIView commitAnimations];
}

A continuación, en su UITextFieldDelegate , que tiene que llamar a centerOn: (CGRect) en los siguientes métodos:

textFieldDidBeginEditing: (UITextField *) con, como parámetro, el marco del campo de texto que desea centrar sucesivamente.

Y hay que llamar en su controlador de eventos, donde se cierra el teclado,

textFieldDidEndEditing: (UITextField *) puede ser una de las maneras de hacerlo, poniendo el INITIAL_VIEW como un parámetro de centerOn:. (CGRect)

Creo en las nuevas versiones de iOS (6.1 y superiores, posiblemente incluso antes), la vista subyacente, por lo menos para UITableView, auto-contrae cuando aparezca el teclado. Por lo que sólo necesita para hacer el campo de texto visible en ese punto de vista. En init:

[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(keyboardWasShown:)
                                             name:UIKeyboardDidShowNotification
                                           object:nil];

a continuación:

- (void)keyboardWasShown:(NSNotification*)notification
{
    // Scroll the text field into view so it's not under the keyboard.
    CGRect rect = [self.tableView convertRect:inputView.bounds fromView:inputView];
    [self.tableView scrollRectToVisible:rect animated:YES];
}

https://github.com/ZulwiyozaPutra/Shift-Keyboard-Example Espero que esta solución ayudó. Todos ellos están escritos Swift 3.

//
//  ViewController.swift
//  Shift Keyboard Example
//
//  Created by Zulwiyoza Putra on 11/23/16.
//  Copyright © 2016 Zulwiyoza Putra. All rights reserved.
//

import UIKit

class ViewController: UIViewController, UITextFieldDelegate {
    
    
    //connecting textfield from storyboard
    @IBOutlet weak var textField: UITextField!
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        subscribeToKeyboardNotifications()
    }
    
    override func viewDidAppear(_ animated: Bool) {
        self.textField.delegate = self
    }
    
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        unsubscribeFromKeyboardNotifications()
    }
    
    //Hide keyboard after finished editing
    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        textField.resignFirstResponder()
        return true
    }
    
    //Setup view before keyboard appeared
    func keyboardWillAppear(_ notification:Notification) {
        view.frame.origin.y = 0 - getKeyboardHeight(notification)
    }
    
    //Setup view before keyboard disappeared
    func keyboardWillDisappear(_ notification: Notification) {
        view.frame.origin.y = 0
    }
    
    //Getting keyboard height
    func getKeyboardHeight(_ notification:Notification) -> CGFloat {
        let userInfo = notification.userInfo
        let keyboardSize = userInfo![UIKeyboardFrameEndUserInfoKey] as! NSValue // of CGRect
        return keyboardSize.cgRectValue.height
    }
    
    //Subscribing to notifications to execute functions
    func subscribeToKeyboardNotifications() {
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillAppear(_:)), name: .UIKeyboardWillShow, object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillDisappear(_:)), name: .UIKeyboardWillHide, object: nil)
    }
    
    //Unsubscribing from notifications
    func unsubscribeFromKeyboardNotifications() {
        NotificationCenter.default.removeObserver(self, name: .UIKeyboardWillShow, object: nil)
        NotificationCenter.default.removeObserver(self, name: .UIKeyboardWillHide, object: nil)
    }
    
}

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top