动画添加高度约束到键盘扩展视图

Animate adding height constraint to keyboard extension view

在我的键盘扩展中,有一个特殊的 viewController 我想让键盘增加高度。在呈现此 viewController 之前,主 UIInputViewController 会自行调用此方法,并传递值 400.0:

- (void)setKeyboardHeight:(CGFloat)height {
    if (self.heightConstraint) {
        [self.view removeConstraint:self.heightConstraint];
        self.heightConstraint = nil;
   }

    self.heightConstraint = [NSLayoutConstraint constraintWithItem:self.view attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:height];

    [self.view addConstraint:self.heightConstraint];

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

键盘的高度确实更改为指定值,但不是动画。这是不可能完成的,还是我只是在键盘扩展中使用了错误的方法?

这是我提出的一种解决方案。调用animateKeyboardHeightTo: speed:,传入你希望键盘变化的高度为targetHeight,每毫秒的点数为speed,键盘会增加或减少到指定的高度。我尝试使用持续时间而不是速度,每次迭代增加一个点并计算 dispatch_after 的持续时间,以便整个动画将在指定的持续时间内发生,但我无法让 dispatch_after 执行足够快。我不知道它是否不够精确,或者它是否不能以小于 1 秒的间隔执行,但这是我能想到的唯一解决方案。

如果你想在大小之间切换,你可以在对 animateKeyboardHeightTo: speed: 进行初始调用之前将 self.view.frame.size.height 存储在 属性 中,然后再次调用此方法并传入存储高度以将键盘恢复到其初始高度。

- (void)animateKeyboardHeightTo:(CGFloat)targetHeight speed:(CGFloat)speed {
    CGFloat initialHeight = self.view.frame.size.height;

    if (targetHeight < initialHeight) {
        speed = -speed;
    }
    [self setKeyboardHeight:initialHeight];
    [self increaseKeyboardHeightToTargetHeight:targetHeight speed:speed];
}

- (void)increaseKeyboardHeightToTargetHeight:(CGFloat)targetHeight speed:(CGFloat)speed {
    CGFloat currentHeight = self.heightConstraint.constant;
    CGFloat nextHeight = currentHeight + speed;
    if ((speed > 0 && nextHeight > targetHeight) || (speed < 0 && nextHeight < targetHeight)) {
        nextHeight = targetHeight;
    }
    [self setKeyboardHeight:nextHeight];

    if ((speed > 0 && nextHeight < targetHeight) || (speed < 0 && nextHeight > targetHeight)) {
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_MSEC)), dispatch_get_main_queue(), ^{
            [self increaseKeyboardHeightToTargetHeight:targetHeight speed:speed];
        });
    }
}

- (void)setKeyboardHeight:(CGFloat)height {
    [self removeHeightConstraint];
    [self addHeightConstraintWithHeight:height];
}

- (void)removeHeightConstraint {
    if (self.heightConstraint) {
        [self.view removeConstraint:self.heightConstraint];
        self.heightConstraint = nil;
    }
}

- (void)addHeightConstraintWithHeight:(CGFloat)height {
    self.heightConstraint = [NSLayoutConstraint constraintWithItem:self.view attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:height];

    [self.view addConstraint:self.heightConstraint];
}