UIKeyboardBoundsUserInfoKey jest przestarzały, czego zamiast tego użyć?

Pracuję nad aplikacją na iPada przy użyciu sdk 3.2. Mam do czynienia z uzyskaniem rozmiaru klawiatury, aby zapobiec ukrywaniu się za nią pól tekstowych.

I ' m getting a Warning in Xcode - > UIKeyboardBoundsUserInfoKey is deprecated what should I use instead not to get this warning?

Author: Meet Doshi, 2010-05-11

8 answers

Grałem z wcześniej oferowanym rozwiązaniem, ale nadal miałem problemy. Oto co wymyśliłem zamiast tego:

    - (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/doraprojects.net/template/agent.layouts/content.php on line 54
2012-08-16 15:36:46

Z dokumentacji dla UIKeyboardBoundsUserInfoKey:

Klawisz dla obiektu NSValue zawierającego CGRect, który identyfikuje prostokąt obwiedni klawiatury we współrzędnych okna. Wartość ta jest wystarczająca do uzyskania rozmiaru klawiatury. Jeśli chcesz uzyskać pochodzenie klawiatury na ekranie (przed lub po animacji), użyj wartości uzyskanych ze słownika informacji użytkownika za pomocą stałych UIKeyboardCenterBeginUserInfoKey lub uikeyboardcenterenduserinfokey. zamiast tego użyj klucza UIKeyboardFrameBeginUserInfoKey lub uikeyboardframeenduserinfokey.

[[4]} Apple zaleca wdrożenie wygodnej procedury, takiej jak ta (która może być zaimplementowana jako dodatek do kategoriiUIScreen):
+ (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];
}

Aby odzyskać dopasowane do okna właściwości rozmiaru ramki klawiatury.

Przyjęłam inne podejście, które polega na sprawdzeniu orientacji urządzenia:

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/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-02 20:45:58

Wystarczy użyć tego kodu:

//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/doraprojects.net/template/agent.layouts/content.php on line 54
2011-01-05 06:45:17

Poniższy kod rozwiązuje problem w Jay ' s answer, który zakłada, że UIKeyboardWillShowNotification nie uruchomi się ponownie, gdy klawiatura jest już obecna.

[20]}podczas pisania z klawiatury japońskiej/chińskiej, iOS uruchamia dodatkowy UIKeyboardWillShowNotification z nową ramką klawiatury, nawet jeśli klawiatura jest już obecna, co prowadzi do zmniejszenia wysokości self.textView po raz drugi w oryginalnym kodzie.

To redukuje self.textView do prawie niczego. Wtedy staje się niemożliwe do odzyskania z tego problem, ponieważ będziemy oczekiwać tylko jednego UIKeyboardWillHideNotification następnym razem, gdy klawiatura zostanie odrzucona.

Zamiast odejmować / dodawać wysokość do self.textView w zależności od tego, czy klawiatura jest pokazana/ukryta jak w oryginalnym kodzie, poniższy kod oblicza maksymalną możliwą wysokość dla self.textView po odjęciu wysokości klawiatury na ekranie.

Zakłada się, że self.textView ma wypełnić cały widok kontrolera widoku i nie ma innego podglądu, który musi być widoczne.

- (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];
    }

}

Nie zapomnij również zarejestrować powiadomień klawiatury w 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];
}

O podzieleniu kodu zmiany rozmiaru na dwie części

Powodem, dla którego kod zmiany rozmiaru textView jest podzielony na dwie części (resizeTextViewWithKeyboardNotification: i resizeViewToAccommodateKeyboardFrame:withAnimationDuration:animationCurve:), jest naprawienie innego problemu, gdy klawiatura pozostaje wciśnięta z jednego kontrolera widoku do drugiego (Zobacz Jak wykryć klawiaturę iOS, gdy pozostaje między kontrolerami?).

Ponieważ klawiatura jest system iOS nie generuje żadnych dodatkowych powiadomień z klawiatury, a tym samym nie ma możliwości zmiany rozmiaru textView na podstawie tych powiadomień z klawiatury.

Powyższy kod (jak również oryginalny kod), który zmienia rozmiar self.textView będzie działać tylko wtedy, gdy klawiatura zostanie pokazana Po załadowaniu widoku.

Moim rozwiązaniem jest utworzenie singletonu, który przechowuje Ostatnie współrzędne klawiatury, a na - viewDidAppear: viewController, wywołanie:

- (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 jest tu mój singleton. Idealnie powinniśmy to wywołać w - viewWillAppear:, jednak z mojego doświadczenia (przynajmniej na iOS 6), metoda convertRect:fromView:, którą musimy użyć w resizeViewToAccommodateKeyboardFrame:withAnimationDuration:animationCurve:, nie konwertuje poprawnie ramki klawiatury na współrzędne widoku, zanim widok będzie w pełni widoczny.

 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/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 10:27:45

Po prostu użyj klucza UIKeyboardFrameBeginUserInfoKey LUB UIKeyboardFrameEndUserInfoKey zamiast 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/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-05 07:49:41

@Jason, kodujesz jeśli dobrze, z wyjątkiem jednego punktu.

W tej chwili nic nie animujesz, a Widok po prostu " pop " do nowego rozmiaru.wzrost.

Należy określić stan, z którego ma być animowany. Animacja to coś w rodzaju(od stanu)->(do stanu).

Na szczęście istnieje bardzo wygodna metoda określania bieżącego stanu widoku jako stanu (from).

[UIView setAnimationBeginsFromCurrentState:YES];

Jeśli dodasz tę linię zaraz po beginAnimations: context: Twój kod działa idealnie.

 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/doraprojects.net/template/agent.layouts/content.php on line 54
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/doraprojects.net/template/agent.layouts/content.php on line 54
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/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-18 11:47:22