UIKeyboardBoundsUserInfoKey está en desuso, ¿qué usar en su lugar?


Estoy trabajando en una aplicación para iPad usando 3.2 sdk. Estoy tratando de obtener el tamaño del teclado para evitar que mis campos de texto se escondan detrás de él.

Estoy recibiendo una advertencia en Xcode -> UIKeyboardBoundsUserInfoKey está obsoleto ¿qué debo usar en su lugar para no recibir esta advertencia?

Author: Meet Doshi, 2010-05-11

8 answers

Jugué con la solución ofrecida anteriormente, pero todavía tenía problemas. Esto es lo que se me ocurrió en su lugar:

    - (void)keyboardWillShow:(NSNotification *)aNotification {
    [self moveTextViewForKeyboard:aNotification up:YES];
}

    - (void)keyboardWillHide:(NSNotification *)aNotification {
        [self moveTextViewForKeyboard:aNotification up:NO]; 
    }

- (void) moveTextViewForKeyboard:(NSNotification*)aNotification up: (BOOL) up{
NSDictionary* userInfo = [aNotification userInfo];

// Get animation info from userInfo
NSTimeInterval animationDuration;
UIViewAnimationCurve animationCurve;

CGRect keyboardEndFrame;

[[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] getValue:&animationCurve];
[[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] getValue:&animationDuration];


[[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] getValue:&keyboardEndFrame];


// Animate up or down
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:animationDuration];
[UIView setAnimationCurve:animationCurve];

CGRect newFrame = textView.frame;
CGRect keyboardFrame = [self.view convertRect:keyboardEndFrame toView:nil];

newFrame.origin.y -= keyboardFrame.size.height * (up? 1 : -1);
textView.frame = newFrame;

[UIView commitAnimations];
}
 87
Author: Jay,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-08-16 15:36:46

De la documentación para UIKeyboardBoundsUserInfoKey:

Tecla para un objeto NSValue que contiene un CGRect que identifica el rectángulo de límites del teclado en coordenadas de ventana. Este valor es suficiente para obtener el tamaño del teclado. Si desea obtener el origen del teclado en la pantalla (antes o después de la animación) utilice los valores obtenidos del diccionario de información del usuario a través de las constantes UIKeyboardCenterBeginUserInfoKey o UIKeyboardCenterEndUserInfoKey. Utilice la clave UIKeyboardFrameBeginUserInfoKey o UIKeyboardFrameEndUserInfoKey en su lugar.

Apple recomienda implementar una rutina de conveniencia como esta (que podría implementarse como una adición de categoría a UIScreen):

+ (CGRect) convertRect:(CGRect)rect toView:(UIView *)view {
    UIWindow *window = [view isKindOfClass:[UIWindow class]] ? (UIWindow *) view : [view window];
    return [view convertRect:[window convertRect:rect fromWindow:nil] fromView:nil];
}

Para recuperar las propiedades de tamaño de fotograma del teclado ajustadas por ventana.

Tomé un enfoque diferente, que implica verificar la orientación del dispositivo:

CGRect _keyboardEndFrame;
[[notification.userInfo valueForKey:UIKeyboardFrameEndUserInfoKey] getValue:&_keyboardEndFrame];
CGFloat _keyboardHeight = ([[UIDevice currentDevice] orientation] == UIDeviceOrientationPortrait || [[UIDevice currentDevice] orientation] == UIDeviceOrientationPortraitUpsideDown) ? _keyboardEndFrame.size.height : _keyboardEndFrame.size.width;
 55
Author: Alex Reynolds,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-05-02 20:45:58

Simplemente usa este código:

//NSVale *aValue = [info objectForKey:UIKeyboardBoundsUserInfoKey];
//instead of Upper line we can use either next line or nextest line.
//NSValue *aValue = [info objectForKey:UIKeyboardFrameEndUserInfoKey];
NSValue *aValue = [info objectForKey:UIKeyboardFrameBeginUserInfoKey];
 9
Author: iOS_User,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-01-05 06:45:17

El siguiente código corrige un problema en La respuesta de Jay, que asume que UIKeyboardWillShowNotification no se disparará de nuevo cuando el teclado ya está presente.

Al escribir con el teclado japonés/chino, iOS dispara un UIKeyboardWillShowNotification extra con el nuevo marco de teclado a pesar de que el teclado ya está presente, lo que lleva a que la altura del self.textView se reduzca por segunda vez en el código original.

Esto reduce self.textView a casi nada. Entonces se vuelve imposible recuperarse de esto problema ya que solo esperaremos un único UIKeyboardWillHideNotification la próxima vez que se desestime el teclado.

En lugar de restar/agregar altura a self.textView dependiendo de si el teclado se muestra/oculta como en el código original, el siguiente código solo calcula la altura máxima posible para self.textView después de restar la altura del teclado en pantalla.

Esto asume que self.textView se supone que debe llenar toda la vista del controlador de vista, y no hay otra subview que necesite ser visible.

- (void)resizeTextViewWithKeyboardNotification:(NSNotification*)notif {

    NSDictionary* userInfo = [notif userInfo];
    NSTimeInterval animationDuration;
    UIViewAnimationCurve animationCurve;
    CGRect keyboardFrameInWindowsCoordinates;

    [[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] getValue:&animationCurve];
    [[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] getValue:&animationDuration];
    [[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] getValue:&keyboardFrameInWindowsCoordinates];

    [self resizeTextViewToAccommodateKeyboardFrame:keyboardFrameInWindowsCoordinates
                             withAnimationDuration:animationDuration
                                    animationCurve:animationCurve];

}

- (void)resizeTextViewToAccommodateKeyboardFrame:(CGRect)keyboardFrameInWindowsCoordinates
                           withAnimationDuration:(NSTimeInterval)duration
                                  animationCurve:(UIViewAnimationCurve)curve
{

    CGRect fullFrame = self.view.frame;

    CGRect keyboardFrameInViewCoordinates =
    [self.view convertRect:keyboardFrameInWindowsCoordinates fromView:nil];

    // Frame of the keyboard that intersects with the view. When keyboard is
    // dismissed, the keyboard frame still has width/height, although the origin
    // keeps the keyboard out of the screen.
    CGRect keyboardFrameVisibleOnScreen =
    CGRectIntersection(fullFrame, keyboardFrameInViewCoordinates);

    // Max frame availble for text view. Assign it to the full frame first
    CGRect newTextViewFrame = fullFrame;

    // Deduct the the height of any keyboard that's visible on screen from
    // the height of the text view
    newTextViewFrame.size.height -= keyboardFrameVisibleOnScreen.size.height;

    if (duration)
    {
        [UIView beginAnimations:nil context:nil];
        [UIView setAnimationDuration:duration];
        [UIView setAnimationCurve:curve];
    }

    // Adjust the size of the text view to the new one
    self.textView.frame = newTextViewFrame;

    if (duration)
    {
        [UIView commitAnimations];
    }

}

Además, no olvides registrar las notificaciones del teclado en viewDidLoad:

- (void)viewDidLoad
{
    [super viewDidLoad];
    NSNotificationCenter* notifCenter = [NSNotificationCenter defaultCenter];

    [notifCenter addObserver:self selector:@selector(resizeTextViewWithKeyboardNotification:) name:UIKeyboardWillShowNotification object:nil];
    [notifCenter addObserver:self selector:@selector(resizeTextViewWithKeyboardNotification:) name:UIKeyboardWillHideNotification object:nil];
}

Acerca de dividir el código de redimensionamiento en dos partes

La razón por la que el código de redimensionamiento de TextView se divide en dos partes (resizeTextViewWithKeyboardNotification: y resizeViewToAccommodateKeyboardFrame:withAnimationDuration:animationCurve:) es para solucionar otro problema cuando el teclado persiste a través de un empuje de un controlador de vista a otro (ver ¿Cómo detecto el teclado iOS cuando se mantiene entre controladores?).

Puesto que el teclado es ya presente antes de que se empuje el controlador de vista, no hay notificaciones de teclado adicionales generadas por iOS, y por lo tanto no hay forma de cambiar el tamaño de textView en función de esas notificaciones de teclado.

El código anterior (así como el código original) que redimensiona self.textView solo funcionará cuando se muestre el teclado después de que se haya cargado la vista.

Mi solución es crear un singleton que almacene las últimas coordenadas de teclado, y en - viewDidAppear: del controlador ViewController, llamada:

- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];

    // Resize the view if there's any keyboard presence before this
    // Only call in viewDidAppear as we are unable to convertRect properly
    // before view is shown
    [self resizeViewToAccommodateKeyboardFrame:[[UASKeyboard sharedKeyboard] keyboardFrame]
                         withAnimationDuration:0
                                animationCurve:0];
}

UASKeyboard es mi singleton aquí. Idealmente deberíamos llamar a esto en - viewWillAppear:, sin embargo, en mi experiencia (al menos en iOS 6), el método convertRect:fromView: que necesitamos usar en resizeViewToAccommodateKeyboardFrame:withAnimationDuration:animationCurve: no convierte correctamente el marco del teclado a las coordenadas de la vista antes de que la vista sea completamente visible.

 3
Author: junjie,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 10:27:45

Simplemente use la tecla UIKeyboardFrameBeginUserInfoKey o UIKeyboardFrameEndUserInfoKey en lugar de UIKeyboardBoundsUserInfoKey

 2
Author: Anand Mishra,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-10-05 07:49:41

@ Jason, codifica si está bien excepto por un punto.

En este momento no está animando nada y la vista simplemente `pop' a su nuevo tamaño.altura.

Tiene que especificar un estado desde el que animar. Una animación es una especie de(de estado)->(a estado) cosa.

Afortunadamente hay un método muy conveniente para especificar el estado actual de la vista como el (estado de).

[UIView setAnimationBeginsFromCurrentState:YES];

Si agrega esa línea justo después de beginAnimations: context: su código funciona perfectamente.

 1
Author: Thomas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-06-22 09:39:14
- (CGSize)keyboardSize:(NSNotification *)aNotification {
    NSDictionary *info = [aNotification userInfo];
    NSValue *beginValue = [info objectForKey:UIKeyboardFrameBeginUserInfoKey];

    UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];

    CGSize keyboardSize;
    if ([UIKeyboardDidShowNotification isEqualToString:[aNotification name]]) {
        _screenOrientation = orientation;
        if (UIDeviceOrientationIsPortrait(orientation)) {
            keyboardSize = [beginValue CGRectValue].size;
        } else {
            keyboardSize.height = [beginValue CGRectValue].size.width;
            keyboardSize.width = [beginValue CGRectValue].size.height;
        }
    } else if ([UIKeyboardDidHideNotification isEqualToString:[aNotification name]]) {
        // We didn't rotate
        if (_screenOrientation == orientation) {
            if (UIDeviceOrientationIsPortrait(orientation)) {
                keyboardSize = [beginValue CGRectValue].size;
            } else {
                keyboardSize.height = [beginValue CGRectValue].size.width;
                keyboardSize.width = [beginValue CGRectValue].size.height;
            }
        // We rotated
        } else if (UIDeviceOrientationIsPortrait(orientation)) {
            keyboardSize.height = [beginValue CGRectValue].size.width;
            keyboardSize.width = [beginValue CGRectValue].size.height;
        } else {
            keyboardSize = [beginValue CGRectValue].size;
        }
    }


    return keyboardSize;
}
 1
Author: Cameron Lowell Palmer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-03-07 10:32:02
 0
Author: karim,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-01-18 11:47:22