ExpandableTextView 平滑动画原理深剖:自定义 Animation 高度插值的本质

📅 2026/8/24 10:07:10
ExpandableTextView 平滑动画原理深剖:自定义 Animation 高度插值的本质
ExpandableTextView 平滑动画原理深剖自定义 Animation 高度插值的本质【免费下载链接】ExpandableTextViewAndroid TextView that can expand and collapse.项目地址: https://gitcode.com/gh_mirrors/expand/ExpandableTextViewExpandableTextView 是一个为 Android 提供可展开文本视图的轻量库文本超出限制时显示截断预览和“展开”按钮点击后视图会平滑地展开或收起。它的展开/收起动画正是通过自定义 Animation 对视图高度做逐帧插值实现的。本文拆解这套平滑动画的原理新手也能一次看懂。上图为该库的实际效果上方为截断状态点击“展开/更多”按钮后文本区域会带着流畅动画缓缓撑开。1. 为什么可展开文本视图需要平滑动画 展示长文本时有两个常见痛点全量展示把页面撑得很长阅读体验差硬截断 瞬间展开点击前后高度突变视觉非常生硬。ExpandableTextView 的思路是在动画过程中每一帧都对视图高度做插值让内容区域像呼吸一样逐渐撑开或收拢——这就是“平滑”的来源。2. 核心原理一行公式完成高度插值Android 传统Animation体系是为平移、缩放这类视觉变换设计的并不能直接改视图大小。ExpandableTextView 的技巧是继承Animation在applyTransformation()里用插值进度反推出当前高度再强制重新布局。核心代码只有 4 行见 ExpandableTextView.javafinal int newHeight (int) ((mEndHeight - mStartHeight) * interpolatedTime mStartHeight); mTv.setMaxHeight(newHeight - mMarginBetweenTxtAndBottom); mTargetView.getLayoutParams().height newHeight; mTargetView.requestLayout();2.1 插值进度 interpolatedTime 的本质 interpolatedTime是系统每帧传入的插值后的进度值0~1不是原始流逝时间默认时间插值器是先加速后减速曲线使动画头尾慢、中间快这正是“顺滑感”的物理来源公式startHeight (endHeight - startHeight) × 进度就是标准的线性高度插值。关键点在最后一行requestLayout()它让高度变化真实生效重新测量与布局而不是视觉假象——这才是“插值”与“错觉”的本质区别。3. 起止高度是如何测量出来的动画需要两个关键数值起始高度与目标高度它们来自onMeasure()里的两次测量ExpandableTextView.java先让文本不限行数完整测量得到全文高度mTextHeightWithMaxLines若行数未超过折叠限制直接返回不显示按钮若超出将行数限制为maxCollapsedLines默认 8 行再测量一次得到折叠高度mCollapsedHeight。点击按钮时ExpandableTextView.java按方向计算动画目标收起当前高度 →mCollapsedHeight展开当前高度 → 完整高度当前高度 全文高度 − 截断文本高度4. 让动画更顺滑稳当的 4 个细节 ⚡除了插值公式库中还埋了几处保证体验的细节细节作用setFillAfter(true)动画结束后保持最后一帧防止高度回跳闪一下动画结束时clearAnimation()清除动画引用避免applyTransformation()被重复调用onInterceptTouchEvent()在动画中拦截触摸#L193-L197防止快速连点导致展开/收起状态错乱mMarginBetweenTxtAndBottom#L106-L111预留“展开”按钮的底部边距让每帧maxHeight计算精确另外willChangeBounds()返回true是告诉动画系统这个动画会改变视图边界让框架按布局动画而非纯视觉动画来处理。5. 如何调整动画时长与折叠行数动画参数在布局 XML 中即可配置全部属性定义在 attrs.xmlme.chensir.expandabletextview.ExpandableTextView android:layout_widthmatch_parent android:layout_heightwrap_content app:maxCollapsedLines4 app:animDuration300/属性默认值说明maxCollapsedLines8折叠时最多显示的行数animDuration300ms展开/收起动画时长contentTextSize/contentTextColor16px / 黑色正文文字样式expandText/collapseText展开 / 收起展开按钮文案contentLineSpacingMultiplier1.0正文行距倍率完整用法可参考示例模块 MainActivity.java其界面效果即开头的演示动图。6. 总结一张图看懂整套机制 ✅ExpandableTextView 的平滑动画来自一个非常优雅的组合拳onMeasure两次测量拿到动画的起始/目标高度自定义Animation在applyTransformation()中用interpolatedTime对高度做逐帧插值requestLayout()让每帧插值真实生效触摸拦截 FillAfter 结束清场消除闪跳与连点错乱。理解这套“高度插值”技巧后你完全可以把它迁移到自己的场景里比如列表项的平滑展开收起、详情面板的渐显撑开等。【免费下载链接】ExpandableTextViewAndroid TextView that can expand and collapse.项目地址: https://gitcode.com/gh_mirrors/expand/ExpandableTextView创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考