changebounds动画未生效最常见的原因是目标视图在动画开始前未完成布局测量,导致起始rect为(0,0,0,0);需确保在view重绘完成后(如post()或ongloballayout回调中)再调用begindelayedtransition()。

changeBounds 动画为什么没生效?
最常见原因是目标视图在动画开始前没完成布局测量,ChangeBounds 依赖视图的「起始」和「结束」Rect 做插值,如果调用 transitionManager.beginDelayedTransition() 时视图还没走完 onLayout(),它就只能拿到 (0,0,0,0) —— 动画自然不动。
- 确保在数据更新后、视图重绘完成再触发过渡:比如在
RecyclerView.Adapter.notifyItemChanged()后加post()或监听ViewTreeObserver.onGlobalLayout() - 别在
onCreate()里直接调用,此时 ViewGroup 还没 measure;改用onWindowFocusChanged(true)或postOnAnimation() - XML 中设了
android:layout_width="wrap_content"但内容为空?那初始宽高是 0,动画从 0→非0 会卡顿或不可见,建议显式设最小尺寸或用占位
XML 里怎么写 changeBounds 才不被忽略?
Android 只认 TransitionSet 或具体过渡类名,单独写 changeBounds 标签无效。系统不会自动解析名字去匹配类,必须用完整类路径。
- 正确写法:
<changeBounds xmlns:android="http://schemas.android.com/apk/res/android" />
(注意是小写开头,不是ChangeBounds) - 如果混用多个过渡,包在
TransitionSet里,并设android:ordering="together"避免默认串行导致尺寸变化被其他动画挤压 - 别在
transition文件夹下放错文件类型:必须是res/transition/change_bounds.xml,扩展名和目录名都不能错,否则TransitionInflater.from(ctx).inflateTransition(R.transition.change_bounds)会抛Resources$NotFoundException
changeBounds 和 layoutChanges 的区别在哪?
changeBounds 是 Transition 框架的一部分,只响应 beginDelayedTransition() 触发的布局变更;而 layoutChanges 是 View 自身属性,开启后任何 requestLayout() 都可能触发动画,但不经过 TransitionManager 调度,也不支持共享元素或过渡监听。
- 用
changeBounds:需要精确控制时机(比如列表项展开/收起)、要和其他过渡(如changeClipBounds)组合、需监听TransitionListener - 用
android:animateLayoutChanges="true":简单场景下快速启用父容器子 View 尺寸变化动画,但无法干预起始/结束状态,且对嵌套层级深的布局性能较差 - 两者同时开?会冲突。系统优先走
animateLayoutChanges的默认动画,ChangeBounds直接被跳过
为什么 changeBounds 在 ConstraintLayout 里缩放失真?
ConstraintLayout 的尺寸变化常由约束变动(ConstraintSet)驱动,而 changeBounds 只捕获最终 View.getTop()/getLeft()/getWidth()/getHeight(),不感知约束逻辑。当约束改变导致视图先平移再缩放,changeBounds 会把整个位移+尺寸变化揉成一个矩形插值,看起来像拉伸变形。
- 解法一:改用
TransitionManager.beginDelayedTransition(container, new ChangeBounds().setPathMotion(new ArcMotion()))加弧线路径缓解生硬感 - 解法二:不用
changeBounds,改用TransitionSet组合ChangeTransform(处理缩放) +ChangeBounds(处理位置),并设android:duration="300"统一时长 - 关键点:如果用了
ConstraintSet.clone()+applyTo(),务必在applyTo()前调用beginDelayedTransition(),顺序反了就捕获不到变化
ViewRootImpl 的 performTraversals 调用频次,而不是堆 transition。










