2013-03-14 14 views
25

dla stałej UIKeyboardFrameEndUserInfoKey w docs firmy Apple mówi:Konwersja UIKeyboardFrameEndUserInfoKey aby wyświetlić lub Okno Współrzędne

Współrzędne te nie biorą pod uwagę wszelkie rotacja czynników zastosowany do zawartości okna w wyniku orientacji interfejsu zmian. W związku z tym konieczne może być przekształcenie współrzędnych prostokątnych na okno (przy użyciu metody convertRect: fromWindow:) lub wyświetlenie współrzędnych (przy użyciu metody convertRect: fromView:) przed użyciem.

Więc jeśli mogę użyć [view1 convertRect:rect fromView:view2]

Co chciałbym wstawić na powyższe parametry, aby ją przekształcić wartości rotacji prawidłowo? tj:

view1 =? rect =? (rama klawiatury zakładam) view2 =?

Próbowałem niektórych rzeczy i robiłem zabawne rzeczy.

+0

Nadzieję poniżej odpowiedź pomaga. Wcześniej używałam również 'convertRect', ale poniższy kod jest czystszy, IMO. – memmons

+0

Oczywiście nie zgadzam się z @Answerbot co do tego, co jest "czystsze" :) BTW kod, który pokazuję, pochodzi z mojej książki, którą możesz skonsultować w tej sprawie: http://www.apeth.com/iOSBook/ ch23.html # _summoning_and_dismissing_the_keyboard – matt

+0

@matt Dobre rzeczy. Czytałem jedną z twoich książek i naprawdę mi się podobało. Powodem, dla którego przestałem używać 'convertRect' jest fakt, że działa on bardzo dobrze w kontrolerze widoku, w którym znajduje się' myView', który reprezentuje najwyższy widok. Jeśli jednak słuchasz powiadomień z podklasy 'UITextField', transformacja z użyciem self nie jest szczególnie pomocna. – memmons

Odpowiedz

66

Pierwszy widok powinien być twoim widokiem. Drugi widok powinien być zerowy, co oznacza współrzędne okna/ekranu. W ten sposób:

NSDictionary* d = [notification userInfo]; 
CGRect r = [d[UIKeyboardFrameEndUserInfoKey] CGRectValue]; 
r = [myView convertRect:r fromView:nil]; 

Teraz masz prostą, że klawiatura zajmie, pod względem twojego widoku. Jeśli widok jest widokiem bieżącego kontrolera widoku (lub jego podglądu), obrót i tak dalej są uwzględniane.

+4

+1, ale myślę, że jest to przydatne tylko wtedy, gdy 'myView' reprezentuje główny widok kontrolera widoku. Co jeśli to nie działa, a zamiast tego myView jest podzbiorem typu '{100,100,200,200}'? – memmons

+1

Należy pamiętać, że należy również przekonwertować układ współrzędnych prostokąt na okno! Odpowiedź z @ david-m-syzdek jest bardziej kompletna. –

+1

@DiogoTridapalli Dla jasności, w systemie iOS 8 nie ma potrzeby konwertowania za pomocą układu współrzędnych okna, aby obsłużyć przypadek orientacji poziomej, ponieważ cała aplikacja obraca się, a klawiatura obraca się wraz z nią. – matt

21

Próbowałem zaakceptowanej odpowiedzi i stwierdziłem, że w rzeczywistości nie dostarcza ona CGRect klawiatury w widoku. Okazało się, że mam do konwersji CGRect od obiektu UIScreen do obiektu UIWindow, a od obiektu UIWindow do obiektu 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]; 

używam powyżej aby zmienić rozmiar widoku głównego, aby nie zostać ukryte przez klawiatura:

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

Wpadłem na skrzynkę, w której również musiałem to zrobić. Tak więc od teraz będę to robił w ten sposób. – ma11hew28

+0

Używam tej metody, ale otrzymuję oczywiście niepoprawne wartości 'origin' w viewRect dla orientacji poziomej (ujemne' y'). W twoim rozwiązaniu używasz tylko 'wysokości'. Czy twoje "pochodzenie" zawiera poprawną wartość "y"? – 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); 
} 

Może być używany jak to

- (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]; 
    }]; 
} 
Powiązane problemy