2012-03-17 25 views
22

Ho un controller di visualizzazione in ascolto per UIKeyboardWillShowNotification e UIKeyboardWillHideNotification. I gestori di queste notifiche regolano varie parti della vista, che è una procedura standard.Tastiera "WillShow" e "WillHide" rispetto alla rotazione

Il codice seguente viene utilizzato per convertire il rect tastiera dalla schermata coordinate:

CGRect keyboardBounds = [self.view convertRect:[keyboardBoundsValue CGRectValue] fromView:nil]; 

Nuovamente, la procedura standard. Sfortunatamente, c'è una situazione critica in cui questa conversione fallisce. Osserva cosa succede quando un iPhone viene ruotato da verticale a orizzontale mentre la tastiera è dispiegata:

1) iOS attiva automaticamente UIKeyboardWillHideNotification; self.interfaceOrientation è segnalato come portrait; keyboardBounds.height è 216,0. Questo ha senso. Perché? Poiché al gestore di notifiche viene data la possibilità di "ripulire" prima che la vista passi alla modalità orizzontale.

2) iOS attiva automaticamente UIKeyboardWillShowNotification; self.interfaceOrientation è segnalato come portrait; keyboardBounds.height è 480,0. Questo NON ha senso. Perchè no? Perché il gestore delle notifiche farà il suo lavoro pensando che l'altezza della tastiera sia 480.0!

La mela ha lasciato cadere la palla su questo, o sto facendo qualcosa di sbagliato?

Si prega di notare che l'ascolto invece per UIKeyboard ha ShowNotification non è una soluzione valida, perché degrada in modo significativo l'esperienza dell'utente. Perché? Poiché l'animazione delle mie modifiche alla vista dopo l'animazione di distribuzione della tastiera avviene ... beh, sembra piuttosto terribile.

Qualcuno è riuscito a far funzionare perfettamente l'autorotazione mentre la tastiera è stata installata? Sembra un'esplosione di caos che Apple ha completamente trascurato. >: |

+0

Quale versione iOS stai provando? – Till

+0

5.1, 5.0 e 4.3.2 – Voobr

risposta

52

Forse un po 'tardi, ma ho appena incontrato lo stesso problema e hanno una bella soluzione per esso che evita qualsiasi tipo di arounds di lavoro (a meno che, naturalmente, le cose cambiano di mele)

In sostanza, quando la notifica centre chiama il tuo metodo per UIKeyboardWillShowNotification (o una qualsiasi delle altre notifiche), il frame che ti dà per UIKeyboardFrameBeginUserInfoKey è nel contesto della finestra, NON la tua vista. Il problema con questo, è che il sistema di coordinate di Windows è sempre in verticale, indipendentemente dall'orientamento del dispositivo, quindi stai trovando la larghezza e l'altezza nel modo sbagliato.

Se si desidera evitare il proprio lavoro, è sufficiente convertire il rettangolo nel sistema di coordinate della vista (che cambia in base all'orientamento). Per fare questo, fare qualcosa di simile al seguente:

- (void) keyboardWillShow:(NSNotification *)aNotification 
{ 
    CGRect keyboardFrame = [[[aNotification userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue]; 
    CGRect convertedFrame = [self.view convertRect:keyboardFrame fromView:self.view.window]; 

    ...... 
    /* Do whatever you want now with the new frame. 
    * The width and height will actually be correct now 
    */ 
    ...... 
} 

Speriamo che questo dovrebbe essere quello che stai dopo :)

+0

Fare attenzione a inviare 'convertRect' alla vista corretta. – Nestor

+2

Grazie mille amico! Sembra che UIKeyboardFrameBeginUserInfoKey nella rotazione capovolta restituisca origini {0,0}. – Razvan

0

Bene, prova a guardare la larghezza della tastiera. Se è il valore che ti aspetti, allora presumo che i valori siano semplicemente commutati;). 480 ha senso come larghezza della tastiera per andare nel paesaggio, che è ciò che mi dà questa impressione.

Se ciò non riesce, è sufficiente memorizzare separatamente i rettangoli verticale e orizzontale. Sono well documented;)

+0

Grazie, ma vorrei evitare di codificare tali valori. C'è un motivo per cui il sistema operativo riporta le dimensioni della tastiera al processo in esecuzione. – Voobr

+0

Immagino che non siano stati semplicemente invertiti, allora? – borrrden

3

Ho incontrato lo stesso problema. iOS mi dà una larghezza/altezza errata della tastiera.Ho usato il seguente stato tagliato in un gestore keyboardDidShow:

CGSize keyboardSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size; 
CGSize keyboardSize2 = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size; 
LogDbg(@"keyboard size: frameBegin=%@; frameEnd=%@", NSStringFromCGSize(keyboardSize), NSStringFromCGSize(keyboardSize2)); 

e verticale e orizzontale modalità di iPad ho ottenuto rispettivamente:

2012-06-14 04:09:49.734 -[LoginViewController keyboardDidShow:] 132 [DBG]:keyboard size: frameBegin={768, 264}; frameEnd={768, 264} 
2012-06-14 04:10:07.971 -[LoginViewController keyboardDidShow:] 132 [DBG]:keyboard size: frameBegin={352, 1024}; frameEnd={352, 1024} 

indovinando che la larghezza della tastiera dovrebbe essere maggiore, allora l'altezza (Sì, io sono così ingenuo) ho fatto una soluzione come seguire:

if (keyboardSize.width < keyboardSize.height) 
{ 
    // NOTE: fixing iOS bug: http://stackoverflow.com/questions/9746417/keyboard-willshow-and-willhide-vs-rotation 
    CGFloat height = keyboardSize.height; 
    keyboardSize.height = keyboardSize.width; 
    keyboardSize.width = height; 
} 
-1

Qui è la mia soluzione:

CGSize keyboardSize = [[[notification userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size; 
float keyboardHeight = self.interfaceOrientation == UIInterfaceOrientationPortrait ? keyboardSize.height : keyboardSize.width; 

Spero che questo aiuti :)

-1

Io uso il seguente codice per ottenere la dimensione della tastiera che funziona bene per tutte le rotazioni

NSDictionary *info = [aNotification userInfo]; 
if (UIInterfaceOrientationIsLandscape(self.interfaceOrientation)) 
    kbHeight = [[NSNumber numberWithFloat:[[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size.width] floatValue]; 
else 
    kbHeight = [[NSNumber numberWithFloat:[[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size.height] floatValue]; 
NSLog(@"keyboard height = %F",kbHeight); 

Ho poi prova per l'orientamento utilizzando l'orientamento barra di stato (che funziona nel primo caso di avvio per iPad) e sposta la vista nella direzione relativa necessaria per creare spazio per la tastiera. Funziona perfettamente, se la tastiera è visibile, quindi si sposta nella posizione corretta sulle rotazioni.

UIDeviceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation; 


if (orientation == UIDeviceOrientationPortrait) 
    { 
    NSLog(@"Orientation: portrait"); 
    self.originalCenter = self.view.center; 
    self.view.center = CGPointMake(self.originalCenter.x, self.originalCenter.y-kbHeight); 
    } 

if (orientation == UIDeviceOrientationPortraitUpsideDown) 
    { 
    NSLog(@"Orientation: portrait upside down"); 
    self.originalCenter = self.view.center; 
    self.view.center = CGPointMake(self.originalCenter.x, self.originalCenter.y+kbHeight); 
    } 

if (orientation == UIDeviceOrientationLandscapeLeft) 
    { 
    NSLog(@"Orientation: landscape left"); 
    self.originalCenter = self.view.center; 
    self.view.center = CGPointMake(self.originalCenter.x+kbHeight,self.originalCenter.y); 
    } 

if (orientation == UIDeviceOrientationLandscapeRight) 
    { 
    NSLog(@"Orientation: landscape right"); 
    self.originalCenter = self.view.center; 
    self.view.center = CGPointMake(self.originalCenter.x-kbHeight,self.originalCenter.y); 
    } 

È possibile tornare la vista nella sua posizione originale quando la tastiera scompare o tramite una funzione textFileDidEndEditing.

0

So che questa risposta molto molto tardi. Ora sono venuto solo su questa situazione e ho trovato la domanda senza risposta. Quindi ho pensato di condividere la mia soluzione. Ci sarà un altro modo migliore, ma in questo modo possiamo risolvere anche questo.

Il KBKeyboardHandler che ho usato da: UITextField: move view when keyboard appears

Ho appena cambiato la mia delegato come segue:

- (void)keyboardSizeChanged:(CGSize)delta 
{  
    CGRect frame = self.view.frame;  
    UIInterfaceOrientation interfaceOrientation = [[UIApplication sharedApplication] statusBarOrientation]; 
    switch (interfaceOrientation) { 
     case UIInterfaceOrientationPortrait: 
      frame.origin.y-=delta.height; 
      break; 
     case UIInterfaceOrientationPortraitUpsideDown: 
      frame.origin.y+=delta.height; 
      break; 
     case UIInterfaceOrientationLandscapeLeft: 
      frame.origin.x-=delta.height; 
      break; 
     case UIInterfaceOrientationLandscapeRight: 
      frame.origin.x+=delta.height; 
      break; 
     default: 
      break; 
    } 
    self.view.frame = frame; 
} 

E stava funzionando benissimo.

4

Recentemente ho scritto un post sul blog su questo problema esatto che hai descritto e su come risolverlo con un modo breve ed elegante.Ecco il link al post: Synchronizing rotation animation between the keyboard and the attached view

Se non si vuole tuffarsi nel lungo spiegazione descritto nel post del blog Ecco una breve descrizione con un esempio di codice:

Il principio di base è quello di utilizzare lo stesso metodo che tutti usano - osservando le notifiche della tastiera per animare la vista allegata su e giù. Ma oltre a questo, devi cancellare queste animazioni quando le notifiche della tastiera vengono attivate come conseguenza del cambio di orientamento dell'interfaccia.

esempio di rotazione senza cancellazione animazione personalizzata sul cambiamento dell'orientamento interfaccia: esempio

rotazione con l'annullamento di animazione sul cambiamento dell'orientamento interfaccia:

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

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

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

    [[NSNotificationCenter defaultCenter] 
      removeObserver:self name:UIKeyboardWillShowNotification object:nil]; 
    [[NSNotificationCenter defaultCenter] 
      removeObserver:self name:UIKeyboardWillHideNotification object:nil]; 
} 

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration { 
    [super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration]; 
    self.animatingRotation = YES; 
} 

- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation { 
    [super didRotateFromInterfaceOrientation:fromInterfaceOrientation]; 
    self.animatingRotation = NO; 
} 

- (void)adjustViewForKeyboardNotification:(NSNotification *)notification { 
    NSDictionary *notificationInfo = [notification userInfo]; 

    // Get the end frame of the keyboard in screen coordinates. 
    CGRect finalKeyboardFrame = [[notificationInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue]; 

    // Convert the finalKeyboardFrame to view coordinates to take into account any rotation 
    // factors applied to the window’s contents as a result of interface orientation changes. 
    finalKeyboardFrame = [self.view convertRect:finalKeyboardFrame fromView:self.view.window]; 

    // Calculate new position of the commentBar 
    CGRect commentBarFrame = self.commentBar.frame; 
    commentBarFrame.origin.y = finalKeyboardFrame.origin.y - commentBarFrame.size.height; 

    // Update tableView height. 
    CGRect tableViewFrame = self.tableView.frame; 
    tableViewFrame.size.height = commentBarFrame.origin.y; 

    if (!self.animatingRotation) { 
     // Get the animation curve and duration 
     UIViewAnimationCurve animationCurve = (UIViewAnimationCurve) [[notificationInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] integerValue]; 
     NSTimeInterval animationDuration = [[notificationInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]; 

     // Animate view size synchronously with the appearance of the keyboard. 
     [UIView beginAnimations:nil context:nil]; 
     [UIView setAnimationDuration:animationDuration]; 
     [UIView setAnimationCurve:animationCurve]; 
     [UIView setAnimationBeginsFromCurrentState:YES]; 

     self.commentBar.frame = commentBarFrame; 
     self.tableView.frame = tableViewFrame; 

     [UIView commitAnimations]; 
    } else { 
     self.commentBar.frame = commentBarFrame; 
     self.tableView.frame = tableViewFrame; 
    } 
} 

La risposta è stata anche pubblicato in domanda simile: UIView atop the Keyboard similar to iMessage App

Problemi correlati