UIKeyboardBoundsUserInfoKey устарел, что использовать вместо этого?

Я работаю над iPad-приложением, использующим 3.2 sdk. Я имею дело с получением размера клавиатуры, чтобы мои текстовые поля не скрывались за ним.

Я получаю предупреждение в Xcode → UIKeyboardBoundsUserInfoKey устарел, что использовать вместо этого, чтобы не получить это предупреждение?

Ответ 1

Я играл с ранее предложенным решением, но все еще имел проблемы. Вот что я придумал вместо этого:

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

Ответ 2

Из documentation для UIKeyboardBoundsUserInfoKey:

Ключ для объекта NSValue, содержащий CGRect, который идентифицирует прямоугольник границ клавиатуры в координатах окна. Этого значения достаточно для получения размера клавиатуры. Если вы хотите получить начало клавиатуры на экране (до или после анимации), используйте значения, полученные из словаря пользовательской информации, через константы UIKeyboardCenterBeginUserInfoKey или UIKeyboardCenterEndUserInfoKey. Вместо этого используйте ключ UIKeyboardFrameBeginUserInfoKey или UIKeyboardFrameEndUserInfoKey.

Apple рекомендует внедрить такую ​​удобную процедуру (которая может быть реализована как дополнение категории к UIScreen):

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

чтобы восстановить свойства размера рамки клавиатуры, скорректированные под окном.

Я использовал другой подход, который включает в себя проверку ориентации устройства:

CGRect _keyboardEndFrame;
[[notification.userInfo valueForKey:UIKeyboardFrameEndUserInfoKey] getValue:&_keyboardEndFrame];
CGFloat _keyboardHeight = ([[UIDevice currentDevice] orientation] == UIDeviceOrientationPortrait || [[UIDevice currentDevice] orientation] == UIDeviceOrientationPortraitUpsideDown) ? _keyboardEndFrame.size.height : _keyboardEndFrame.size.width;

Ответ 3

Вы просто используете этот код:

//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];

Ответ 4

Следующий код исправляет проблему в Jay answer, которая предполагает, что UIKeyboardWillShowNotification не будет запускаться снова, когда клавиатура уже присутствует.

При наборе текста с японской/китайской клавиатурой iOS запускает дополнительный UIKeyboardWillShowNotification с новой рамкой клавиатуры, даже если клавиатура уже присутствует, что приводит к тому, что высота self.textView сокращается во второй раз в исходном коде.

Это уменьшает self.textView почти до нуля. После этого становится невозможным восстановить эту проблему, так как мы ожидаем только один UIKeyboardWillHideNotification при следующей увольнении клавиатуры.

Вместо вычитания/добавления высоты в self.textView в зависимости от того, отображается или скрывается клавиатура, как в исходном коде, следующий код просто вычисляет максимально возможную высоту для self.textView после вычитания высоты клавиатуры на экране.

Предполагается, что self.textView должен заполнить весь вид контроллера представления, и нет другого подсмотра, который должен быть видимым.

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

}

Кроме того, не забудьте зарегистрировать уведомления клавиатуры в 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];
}

О разделении кода изменения размера на две части

Причина, по которой код изменения размера textView разделяется на две части (resizeTextViewWithKeyboardNotification:и resizeViewToAccommodateKeyboardFrame:withAnimationDuration:animationCurve:), заключается в том, чтобы исправить еще одну проблему, когда клавиатура сохраняется через нажатие с одного контроллера представления на другой (см. Как определить клавиатуру iOS, когда она остается между контроллерами?).

Поскольку клавиатура уже присутствует перед нажатием контроллера вида, никаких дополнительных уведомлений клавиатуры, генерируемых iOS, и, следовательно, нет способа изменить размер textView на основе этих уведомлений клавиатуры.

Приведенный выше код (а также исходный код), который изменяет размер self.textView, будет работать только тогда, когда клавиатура будет отображаться после, изображение было загружено.

Мое решение состоит в том, чтобы создать синглтон, который хранит последние координаты клавиатуры, и в - viewDidAppear: viewController вызовет:

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

    // Resize the view if there 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 - мой синглтон. В идеале мы должны назвать это в - viewWillAppear:, однако, по моему опыту (по крайней мере, на iOS 6), метод convertRect:fromView:, который нам нужно использовать в resizeViewToAccommodateKeyboardFrame:withAnimationDuration:animationCurve:, неправильно преобразовывает рамку клавиатуры в координаты вида перед представлением полностью виден.

Ответ 5

Просто используйте клавиши UIKeyboardFrameBeginUserInfoKey или UIKeyboardFrameEndUserInfoKey вместо UIKeyboardBoundsUserInfoKey

Ответ 6

@Jason, вы кодируете, если штраф, за исключением одной точки.

В настоящий момент вы на самом деле ничего не оживляете, и представление просто "поп" на новый размер. высота.

Вы должны указать состояние, из которого следует анимировать. Анимация - это своего рода (из состояния) → (чтобы заявить) вещь.

К счастью, существует очень удобный способ указать текущее состояние представления как (из состояния).

[UIView setAnimationBeginsFromCurrentState:YES];

Если вы добавите эту строку сразу после beginAnimations: context: ваш код работает отлично.

Ответ 7

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