Подтвердить что ты не робот

IOS 7 - анимация клавиатуры

Я пытаюсь понять новую анимацию клавиатуры в iOS 7.0 на симуляторе iPhone 5. Я хочу изменить размер UITableView при появлении клавиатуры, но я не могу получить нужные детали анимации.
Я использую информацию из объекта NSNotification, когда клавиатура появляется или исчезает.

Вот мой журнал:

Move keyboard from {{0, 920}, {320, 216}} to {{0, 352}, {320, 216}}
 with duration: 0.400000
 and animation curve: 7

UIViewAnimationCurveEaseInOut = 0
UIViewAnimationCurveEaseIn = 1
UIViewAnimationCurveEaseOut = 2
UIViewAnimationCurveLinear = 3

Кривая анимации - неизвестное значение, что мне делать?

4b9b3361

Ответ 1

Теперь я нашел решение. Анимация начинается с точки {0, 920} до {0, 352}. Проблема заключалась в том, что объект UITableView начинался с размера {160, 568}, поэтому я изменил размер UITableView на {160, 920} до начала анимации.

Относительно неизвестной кривой анимации я просто установил параметр animationCurve << 16, чтобы преобразовать его из кривой анимации вида в параметр анимации просмотра.
Значение не равно линейности, легкости, легкости и легкости в анимационной кривой.

Вот мой код:

[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(_keyboardWillShow:)
                                             name:UIKeyboardWillShowNotification
                                           object:nil];

и

- (void)keyboardWillShow:(NSNotification *)aNotification {
    NSDictionary *userInfo = aNotification.userInfo;

    //
    // Get keyboard size.

    NSValue *beginFrameValue = userInfo[UIKeyboardFrameBeginUserInfoKey];
    CGRect keyboardBeginFrame = [self.view convertRect:beginFrameValue.CGRectValue fromView:nil];

    NSValue *endFrameValue = userInfo[UIKeyboardFrameEndUserInfoKey];
    CGRect keyboardEndFrame = [self.view convertRect:endFrameValue.CGRectValue fromView:nil];

    //
    // Get keyboard animation.

    NSNumber *durationValue = userInfo[UIKeyboardAnimationDurationUserInfoKey];
    NSTimeInterval animationDuration = durationValue.doubleValue;

    NSNumber *curveValue = userInfo[UIKeyboardAnimationCurveUserInfoKey];
    UIViewAnimationCurve animationCurve = curveValue.intValue;

    //
    // Create animation.

    CGRect tableViewFrame = self.tableView.frame;
    bTableViewFrame.size.height = (keyboardBeginFrame.origin.y - tableViewFrame.origin.y);
    self.tableView.frame = tableViewFrame;

    void (^animations)() = ^() {
        CGRect tableViewFrame = self.tableView.frame;
        tableViewFrame.size.height = (keyboardEndFrame.origin.y - tableViewFrame.origin.y);
        self.tableView.frame = tableViewFrame;
    };

    //
    // Begin animation.

    [UIView animateWithDuration:animationDuration
                          delay:0.0
                        options:(animationCurve << 16)
                     animations:animations
                     completion:nil];
}

Ответ 2

В iOS 7 клавиатура использует новую, недокументированную анимационную кривую. Хотя некоторые отметили, что использование недокументированного значения для опции анимации, я предпочитаю использовать следующее:

[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:[notification.userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue]];
[UIView setAnimationCurve:[notification.userInfo[UIKeyboardAnimationCurveUserInfoKey] integerValue]];
[UIView setAnimationBeginsFromCurrentState:YES];

// work

[UIView commitAnimations];

В то время как анимация на основе блоков является рекомендацией, кривая анимации, возвращаемая с уведомлением о клавиатуре, является UIViewAnimationCurve, тогда как параметр, который вам нужно передать на анимацию на основе блоков, - это UIViewAnimationOptions. Использование традиционных методов анимации UIView позволяет напрямую передавать значение. Самое главное, что это будет использовать новую кривую бездокументальной анимации (целочисленное значение 7) и заставить анимацию соответствовать клавиатуре. И он будет работать так же хорошо на iOS 6 и 7.

Ответ 3

Вы можете использовать блок animateWithDuration и задать внутри него кривую. Он чист и работает хорошо.

UIViewAnimationCurve curve = [[notification.userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] integerValue];
double duration = [[notification.userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];

[UIView animateWithDuration:duration
                    delay:0
                  options:UIViewAnimationOptionBeginFromCurrentState 
               animations:^{
                 [UIView setAnimationCurve:curve];
                 /* ANIMATION HERE */
                 // don't forget layoutIfNeeded if you use autolayout
               }
               completion:nil];

Счастливое кодирование!

UPDATE

Вы можете использовать простую категорию UIViewController, написанную мной https://github.com/Just-/UIViewController-KeyboardAnimation

Ответ 4

Используйте UIKeyboardWillChangeFrameNotification вместо этого, потому что некоторые международные клавиатуры, такие как китайская клавиатура, меняют высоту во время использования. Также этот код дает правильную высоту для клавиатуры, даже в ландшафтном режиме. (Примечание: код ниже для Автоотключение)

//set your observer, in a method like viewDidLoad
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillChange:) name:UIKeyboardWillChangeFrameNotification object:nil];

- (void)keyboardWillChange:(NSNotification *)notification {
    CGRect initialRect = [notification.userInfo[UIKeyboardFrameBeginUserInfoKey] CGRectValue];
    CGFloat initialHeight = self.view.frame.size.height - [self.view convertRect:initialRect fromView:nil].origin.y;
    CGRect keyboardRect = [notification.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
    CGFloat newHeight = self.view.frame.size.height - [self.view convertRect:keyboardRect fromView:nil].origin.y;
    //set your constraints here, based on initialHeight and newHeight, which are the heights of the keyboard before & after animation.
    [self.contentView setNeedsUpdateConstraints];
    [UIView beginAnimations:nil context:nil];
    [UIView setAnimationDuration:[notification.userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue]];
    [UIView setAnimationCurve:[notification.userInfo[UIKeyboardAnimationCurveUserInfoKey] integerValue]];
    [UIView setAnimationBeginsFromCurrentState:YES];
    [self.contentView layoutIfNeeded];
    [UIView commitAnimations];
}

Ответ 5

Чтобы использовать ту же анимацию, что и клавиатура, вам нужно использовать недокументированную опцию Curve.

- (void)keyboardWillHide:(NSNotification *)notification {
    NSDictionary *userInfo = [notification userInfo];

    CGRect rect = [userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
    NSTimeInterval animationDuration = [[userInfo valueForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
    NSInteger curve = [[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue] << 16;

    [UIView animateWithDuration:animationDuration delay:0.0 options:curve animations:^{

    } completion:nil];
}

Я обнаружил, что на самом деле метод animateWithDuration:delay:usingSpringWithDamping:initialSpringVelocity:options:animations:completion: - это новый способ, который все анимации выполняются в iOS7 и iOS8. Вы просто делаете правильную продолжительность, демпфирование и скорость, и вы получите тот же эффект, но даже вы можете изменить скорость/время.

Ответ 6

Зарегистрируйтесь для уведомления:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];

Отвечайте путем анимации изменения в frame.origin.y представления.

- (void)keyboardWillShow:(NSNotification *)aNotification {

    NSDictionary *userInfo = aNotification.userInfo;
    NSValue *endFrameValue = userInfo[UIKeyboardFrameEndUserInfoKey];
    CGRect keyboardEndFrame = [self.view convertRect:endFrameValue.CGRectValue fromView:nil];

    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:[aNotification.userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue]];
    [UIView setAnimationCurve:[aNotification.userInfo[UIKeyboardAnimationCurveUserInfoKey] integerValue]];
    [UIView setAnimationBeginsFromCurrentState:YES];

    CGRect searchButtonFrame = self.searchButton.frame;
    searchButtonFrame.origin.y = (keyboardEndFrame.origin.y - searchButtonFrame.size.height);
    self.searchButton.frame = searchButtonFrame;

    [UIView commitAnimations];
}