动画添加高度约束到键盘扩展视图
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];
}
在我的键盘扩展中,有一个特殊的 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];
}