Ограничение автоопределения - Клавиатура

Я застрял, пытаясь анимировать табличный вид гладко, у которого есть автоопределение. У меня есть ссылка на ограничение "keyboardHeight" в моем .h и связали это с IB. Все, что я хочу сделать, - это оживить табличный вид с клавиатурой, когда она появится. Вот мой код:

- (void)keyboardWillShow:(NSNotification *)notification
{
    NSDictionary *info = [notification userInfo];
    NSValue *kbFrame = [info objectForKey:UIKeyboardFrameEndUserInfoKey];
    NSTimeInterval animationDuration = [[info objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
    CGRect keyboardFrame = [kbFrame CGRectValue];
    CGFloat height = keyboardFrame.size.height;

    [UIView animateWithDuration:animationDuration animations:^{
        self.keyboardHeight.constant = -height;
        [self.view setNeedsLayout];
    }];
}

Дело в том, что блок анимации мгновен, и я вижу, что пробел появляется до того, как клавиатура закончила свою анимацию. Поэтому в основном я вижу белый фон представления, когда клавиатура оживляет. Я не могу сделать анимацию последней до тех пор, пока клавиатура оживляет.

Я подхожу к этому неправильно? Спасибо заранее!

Ответ 1

Попробуйте так:

self.keyboardHeight.constant = -height;
[self.view setNeedsUpdateConstraints];

[UIView animateWithDuration:animationDuration animations:^{
   [self.view layoutIfNeeded];
}];

Помните этот шаблон, потому что это должен быть правильный способ обновления макетов на основе ограничений (согласно WWDC). Вы также можете добавить или удалить NSLayoutConstraint, пока вы вызываете setNeedsUpdateConstraints после.

Ответ 2

Если вы используете UITableViewController, размер клавиатуры должен автоматически устанавливаться iOS для настройки содержимогоInsets. Но если ваш tableView находится внутри UIViewController, вы, вероятно, захотите использовать это:

KeyboardLayoutConstraint в Spring framework, Самое простое решение, которое я нашел до сих пор. KeyboardLayoutConstraint

Ответ 3

Попробуйте следующий код. В этом случае табличный вид располагается в нижнем краю экрана.

- (void)keyboardWillShow:(NSNotification *)notification { // UIKeyboardWillShowNotification

    NSDictionary *info = [notification userInfo];
    NSValue *keyboardFrameValue = [info objectForKey:UIKeyboardFrameEndUserInfoKey];
    NSTimeInterval animationDuration = [[info objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
    CGRect keyboardFrame = [keyboardFrameValue CGRectValue];

    BOOL isPortrait = UIDeviceOrientationIsPortrait([UIApplication sharedApplication].statusBarOrientation);
    CGFloat keyboardHeight = isPortrait ? keyboardFrame.size.height : keyboardFrame.size.width;

    // constrBottom is a constraint defining distance between bottom edge of tableView and bottom edge of its superview
    constrBottom.constant = keyboardHeight; 
    // or constrBottom.constant = -keyboardHeight - in case if you create constrBottom in code (NSLayoutConstraint constraintWithItem:...:toItem:...) and set views in inverted order

    [UIView animateWithDuration:animationDuration animations:^{
        [tableView layoutIfNeeded];
    }];
}


- (void)keyboardWillHide:(NSNotification *)notification { // UIKeyboardWillHideNotification

    NSDictionary *info = [notification userInfo];
    NSTimeInterval animationDuration = [[info objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];

    constrBottom.constant = 0;
    [UIView animateWithDuration:animationDuration animations:^{
        [tableView layoutIfNeeded];
    }];
}

Ответ 4

Подход, который я принял, - это добавить представление, которое следует за размером клавиатуры. Добавьте его под своим табличным представлением или текстовым вводом или что-то еще, и оно подтолкнет вас, когда появится клавиатура.

Вот как я установил иерархию представлений:

NSDictionary *views = @{@"chats": self.chatsListView, @"reply": self.replyBarView, @"fakeKeyboard":self.fakeKeyboardView};
[self.view addVisualConstraints:@"V:|-30-[chats][reply][fakeKeyboard]|" views:views];

И тогда ключевые биты представления размера клавиатуры выглядят следующим образом:

- (void)keyboardWillShow:(NSNotification *)notification
{
    // Save the height of keyboard and animation duration
    NSDictionary *userInfo = [notification userInfo];
    CGRect keyboardRect = [userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
    self.desiredHeight = CGRectGetHeight(keyboardRect);
    self.duration = [userInfo[UIKeyboardAnimationDurationUserInfoKey] floatValue];

    [self animateSizeChange];
}

- (void)keyboardWillHide:(NSNotification *)notification
{
    self.desiredHeight = 0.0f;

    [self animateSizeChange];
}

- (CGSize)intrinsicContentSize
{
    return CGSizeMake(UIViewNoIntrinsicMetric, self.desiredHeight);
}

- (void)animateSizeChange
{
    [self invalidateIntrinsicContentSize];

    // Animate transition
    [UIView animateWithDuration:self.duration animations:^{
        [self.superview layoutIfNeeded];
    }];
}

Самое приятное в том, что позволить этому конкретному виду обработать его изменение размера - это то, что вы можете позволить контроллеру представления игнорировать его, и вы также можете повторно использовать это представление в любом месте приложения, которое хотите переместить все.

Полный файл находится здесь: https://gist.github.com/shepting/6025439