UITextView动画异常:高度瞬变仅位置动,如何实现同步平滑动画?
解决UITextView展开/收起时高度与位置同步动画的问题
嘿,我来帮你搞定这个UITextView动画的坑!你遇到的问题很常见——直接修改frame的时候高度突然跳变、只有位置动,大概率是Auto Layout的干扰,或者动画的姿势不对。下面给你两种靠谱的解决方案:
方案1:用Auto Layout约束动画(推荐)
如果你的界面用了Auto Layout(现在几乎都是这种情况),直接改frame会被系统的布局引擎覆盖,导致高度没法平滑动画。正确的姿势是给UITextView的高度约束做动画:
- 先在Storyboard/Xib里给UITextView添加高度约束,并且把这个约束拖成IBOutlet,比如命名为
captionHeightConstraint。 - 计算好收起/展开时的目标高度(比如截断后的高度可以用
sizeThatFits结合字体行高计算)。 - 在动画块里修改约束的
constant值,然后触发布局更新:
// 示例:计算截断到2行的高度 CGFloat lineHeight = self->_caption.font.lineHeight; CGFloat targetHeight = lineHeight * 2; // 修改高度约束的constant值 self->_captionHeightConstraint.constant = targetHeight; // 执行动画,关键是调用layoutIfNeeded触发布局更新 [UIView animateWithDuration:kCaptionAnimationDuration * 10 animations:^{ [self.view layoutIfNeeded]; } completion:^(BOOL finished) { self->_displayingFullCaption = NO; }];
这种约束驱动的动画会让高度和位置同步平滑变化,完全符合你的预期。
方案2:纯Frame模式(无Auto Layout时用)
如果你的界面没开启Auto Layout,那要确保动画前后的frame参数都是正确计算的,并且动画前让UITextView先完成布局:
- 先计算好收起状态的完整frame(包括正确的origin和size):
CGRect originalFrame = self->_caption.frame; // 计算内容适配后的完整高度 CGSize fittingSize = [self->_caption sizeThatFits:CGSizeMake(originalFrame.size.width, CGFLOAT_MAX)]; // 假设最多显示2行,设置截断高度 CGFloat truncatedHeight = fittingSize.height > (lineHeight * 2) ? (lineHeight * 2) : fittingSize.height; // 构建目标frame:调整高度的同时,同步修改位置(比如从底部往上收,origin.y要加上高度差) CGRect truncatedFrame = originalFrame; truncatedFrame.size.height = truncatedHeight; truncatedFrame.origin.y = originalFrame.origin.y + (originalFrame.size.height - truncatedHeight);
- 动画前强制更新布局,再执行动画:
// 先让UITextView完成内容渲染和布局 [self->_caption layoutIfNeeded]; [UIView animateWithDuration:kCaptionAnimationDuration * 10 animations:^{ self->_caption.frame = truncatedFrame; // 同步更新contentSize,避免内容滚动异常 self->_caption.contentSize = CGSizeMake(truncatedFrame.size.width, truncatedHeight); } completion:^(BOOL finished) { self->_displayingFullCaption = NO; }];
关键注意点
- 不管用哪种方式,都要确保目标高度是准确计算的,别用固定死的数值,不然不同字体/内容下会出问题。
- 如果用Auto Layout,一定要避免同时存在冲突的约束(比如既设置高度约束又设置bottom+top约束),否则动画会失效。
内容的提问来源于stack exchange,提问作者MichaelGofron
相关产品推荐
相关产品推荐

