¿Cómo calcular el desplazamiento inferior de una vista modal en el iPad?

Cuando un usuario toca un UITextField, aparecerá el keyboard. Me desploop hacia arriba del UITextField para sentarme justo encima del keyboard. Esto funciona bien en iPhone:

introduzca la descripción de la imagen aquí

- (void) someWhere { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onKeyboardShow:) name:UIKeyboardWillShowNotification object:nil]; } - (void) onKeyboardShow:(NSNotification *)notification { CGRect keyboardRect = [[[notification userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue ]; if (keyboardRect.size.height >= IPAD_KEYBOARD_PORTRAIT_HEIGHT) { self.containerView.y = self.containerView.y - keyboardRect.size.width; } else { self.containerView.y = self.containerView.y - keyboardRect.size.height; } } 

Sin embargo, está roto en iPad. En el iPad, los controlleres de vista modal se pueden presentar como una hoja que ocupa solo una parte de la pantalla. Puede ver que hay una brecha entre el último UITextField y el keyboard en el iPad.

introduzca la descripción de la imagen aquí

 UINavigationController* nav = [[UINavigationController alloc] initWithRootViewController:someRootViewController]; nav.modalPresentationStyle = UIModalPresentationFormSheet; [self presentViewController:nav animated:YES completion:nil]; 

Necesito detectar el desplazamiento de la vista modal desde la parte inferior de la pantalla y agregarlo a la coorderada Y del UITextField. Esto hará que el UITextField se enjuague con la parte superior del keyboard. A través de una ingeniería inversa, obtuve el marco de la vista modal al atravesar la jerarquía de vistas indocumentadas:

 - (void) viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; // describe is a category function on UIView that prints out the frame [self.viewController.view.superview.superview.superview.superview describe]; } 

x: 114.000000,
y: 192.000000,
w: 540,000000,
h: 620.000000

Finalmente, para get el desplazamiento de la vista modal desde la parte inferior de la pantalla, hago lo siguiente:

 UIView* modalView = self.viewController.view.superview.superview.superview.superview; // usage of self-explanatory UIView category methods CGFloat bottomOffset = modalView.superview.height - (modalView.y + modalView.height); 

Para mi disgusto, esto solo funciona en modo vertical. Por alguna razón, la vista de supervisión de la vista modal siempre está atrapada con un ancho de 768 y una altura de 1024 sin importar en qué orientación esté el iPad. Aquí es donde estoy pidiendo ayuda. ¿Cómo configuro de manera confiable el desplazamiento de la vista modal desde la parte inferior de la pantalla, independientemente de la orientación, en el iPad?

Veo dos posibles soluciones:

  1. Use un inputAccessoryView para adjuntar el campo de text al keyboard automáticamente.

  2. Convierta el rectángulo del keyboard en la vista supervista del contenedorView que está intentando mover. A continuación, puede get su valor Y superior en las coorderadas de la vista de supervisión de containerView .

Algo como:

 CGRect rectInWindowCoordinates = [self.containerView.window convertRect:keyboardRect fromWindow:nil]; CGRect rectCovenetworkingByKeyboard = [self.containerView.superview convertRect:rectInWindowCoordinates fromView:nil]; CGFloat top = CGRectGetMinY(rectCovenetworkingByKeyboard); self.containerView.y = top - self.containerView.frame.size.height; 
 - (void) onKeyboardShow:(NSNotification *)notification { CGRect keyboardRect = [[[notification userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue ]; UIInterfaceOrientation orientation = [UIApplication shanetworkingApplication].statusBarOrientation; // The keyboard height is only correct when in portrait mode. To get the // real height, we make the assumption that keyboards are always wider than // they are tall. CGFloat keyboardHeight; if (keyboardRect.size.width < keyboardRect.size.height) { keyboardHeight = keyboardRect.size.width; } else { keyboardHeight = keyboardRect.size.height; } CGPoint originOfKeyboardInWindowContext; switch (orientation) { // // (0,0) ___________ // | | // | | // | | // | | // | | // |===========| // |===========| // case UIInterfaceOrientationPortrait: originOfKeyboardInWindowContext = CGPointMake(0.0, [VeetleAppDelegate instance].window.height - keyboardHeight); break; // // ___________ // | | // | | // | | // | | // | | // |===========| // |===========| (0,0) // case UIInterfaceOrientationPortraitUpsideDown: originOfKeyboardInWindowContext = CGPointMake(0.0, keyboardHeight); break; // // _________________ // | | // | | // | | // |=================| // |=================| // (0,0) // case UIInterfaceOrientationLandscapeRight: originOfKeyboardInWindowContext = CGPointMake(keyboardHeight, 0.0); break; // // _________________ (0,0) // | | // | | // | | // |=================| // |=================| // case UIInterfaceOrientationLandscapeLeft: originOfKeyboardInWindowContext = CGPointMake([VeetleAppDelegate instance].window.width - keyboardHeight, 0.0); break; } CGPoint originOfKeyboardInTextFieldContext = [[VeetleAppDelegate instance].window convertPoint:originOfKeyboardInWindowContext toView:self.containerView.superview]; [UIView beginAnimations:nil context:NULL]; [UIView setAnimationDuration:[[[notification userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]]; [UIView setAnimationCurve:[[[notification userInfo] objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue]]; self.containerView.y = originOfKeyboardInTextFieldContext.y - self.containerView.height; [UIView commitAnimations]; }