2013-03-14 13 views
25

Per la costante UIKeyboardFrameEndUserInfoKey, nella documentazione di Apple si dice:Conversione UIKeyboardFrameEndUserInfoKey per visualizzare o Finestra Coordinate

Queste coordinate non tengono conto di eventuali rotazione fattori applicata al contenuto della finestra a causa di orientamento dell'interfaccia modifiche. Pertanto, potrebbe essere necessario convertire il rettangolo nelle coordinate della finestra (utilizzando convertRect: fromWindow: method) o per visualizzare le coordinate (utilizzando il metodo convertRect: fromView:) prima di utilizzarlo.

Quindi, se io uso [view1 convertRect:rect fromView:view2]

Cosa farei inserire i parametri di cui sopra per farlo convertire correttamente i valori di rotazione? es .:

view1 =? rect =? (la cornice della tastiera presumo) view2 =?

State provando alcune cose e ottenendo alcune cose divertenti.

+0

Spero che la risposta qui sotto aiuta. Ho già usato 'convertRect', ma il codice qui sotto è più pulito, IMO. – memmons

+0

Ovviamente non sono d'accordo con @Answerbot riguardo a cosa è "più pulito" :) A proposito il codice che mostro proviene dal mio libro, che potresti voler consultare su questo argomento: http://www.apeth.com/iOSBook/ ch23.html # _summoning_and_dismissing_the_keyboard – matt

+0

@matt Roba buona. Ho letto uno dei tuoi libri e mi è piaciuto molto. Il motivo per cui ho smesso di usare l'uso di 'convertRect' è perché funziona davvero bene solo all'interno di un controller di visualizzazione in cui si ha un' myView' che rappresenta la vista più in alto. Se tuttavia stai ascoltando le notifiche da una sottoclasse di 'UITextField', la trasformazione usando self non è particolarmente utile. – memmons

risposta

66

La prima vista dovrebbe essere la vostra vista. La seconda vista dovrebbe essere nulla, ovvero le coordinate di finestra/schermo. Quindi:

Ora hai il rettangolo che occuperà la tastiera, in termini di visualizzazione. Se la vista è la vista corrente del controllore della vista (o una sua sottoview), la rotazione e così via vengono ora considerate.

+4

+1, ma penso che questo sia utile solo se 'myView' rappresenta la vista radice di un controller di visualizzazione. Cosa succede se non lo fa e invece myView è una sottoview come '{100,100,200,200}'? – memmons

+1

Ricorda che è necessario convertire anche il sistema di coordinate da retto a finestra! La risposta di @ david-m-syzdek è più completa. –

+1

@DiogoTridapalli Giusto per essere chiari, in iOS 8 non è necessario convertire il sistema di coordinate della finestra per gestire il caso dell'orientamento orizzontale, perché l'intera app ruota e la tastiera è ruotata con esso. – matt

21

Ho provato la risposta accettata e ho scoperto che in realtà non fornisce il CGRect della tastiera all'interno della vista. Ho scoperto che devo convertire il CGRect dall'oggetto UIScreen all'oggetto UIWindow, e dall'oggetto UIWindow all'oggetto UIView:

NSValue * keyboardEndFrame; 
CGRect screenRect; 
CGRect windowRect; 
CGRect viewRect; 

// determine's keyboard height 
screenRect = [[[notification userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue]; 
windowRect = [self.view.window convertRect:screenRect fromWindow:nil]; 
viewRect  = [self.view  convertRect:windowRect fromView:nil]; 

Io uso il sopra per ridimensionare la visualizzazione della radice di non essere nascosto dalla tastiera:

NSTimeInterval duration; 
CGRect   frame; 

// determine length of animation 
duration = [[[notification userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]; 

// resize the view 
frame    = self.view.frame; 
frame.size.height -= viewRect.size.height; 

// animate view resize with the keyboard movement 
[UIView beginAnimations:nil context:NULL]; 
[UIView setAnimationBeginsFromCurrentState:YES]; 
[UIView setAnimationDuration:duration]; 
self.view.frame = frame; 
[UIView commitAnimations]; 
+0

Mi sono imbattuto in un caso in cui ho dovuto fare anche questo. Quindi, ho intenzione di farlo in questo modo da ora in poi. – ma11hew28

+0

Sto usando questo metodo, ma ottenendo ovviamente valori di 'origine' errati di viewRect per gli orientamenti orizzontali (negativo' y'). Nella tua soluzione, usi solo l'altezza. Il tuo 'origine' contiene il valore' y' corretto? – burax

1
+ (void)parseKeyboardNotification:(NSNotification *)notification 
       inRelationToView:(UIView *)view 
          info:(void(^)(NSTimeInterval keyboardAnimationDuration, CGRect keyboardFrameInView, UIViewAnimationOptions keyboardAnimationOptions))callback 
{ 
    NSParameterAssert(notification != nil); 
    NSParameterAssert(view != nil); 

    NSDictionary *userInfo = [notification userInfo]; 

    UIViewAnimationCurve animationCurve = [userInfo[UIKeyboardAnimationCurveUserInfoKey] integerValue]; 
    UIViewAnimationOptions animationOption = animationCurve << 16; // https://devforums.apple.com/message/878410#878410 
    NSTimeInterval animationDuration = [userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue]; 

    // http://stackoverflow.com/a/16615391/202451 
    CGRect screenRect = [[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue]; 
    CGRect windowRect = [view.window convertRect:screenRect fromWindow:nil]; 
    CGRect viewRect  = [view  convertRect:windowRect fromView:nil]; 

    callback(animationDuration, viewRect, animationOption); 
} 

Può essere utilizzato come questo

- (void)keyboardWillShowOrHide:(NSNotification *)notification 
{  
    [AGKeyboardInfo parseKeyboardNotification:notification inRelationToView:self.view info:^(NSTimeInterval keyboardAnimationDuration, CGRect keyboardFrameInView, UIViewAnimationOptions keyboardAnimationOptions) { 

     [UIView animateWithDuration:keyboardAnimationDuration delay:0 options:keyboardAnimationOptions animations:^{ 

      // do any modifications to your views 

     } completion:nil]; 
    }]; 
} 
Problemi correlati