用途
该技能用于排查和修复 Jetpack Compose 中 Crossfade 的一个隐蔽布局问题:当淡入淡出的两个子项尺寸不同时,容器会在过渡结束后发生尺寸变化,导致画面出现几像素的位移或跳动。它面向使用 Compose 动画、且在不同状态间切换不同尺寸内容的开发者。
主要能力
- 解释
Crossfade的测量行为:它在运行期间同时组合两个子项,容器是一个使用默认对齐的普通Box,即尺寸等于当前屏幕上最大的子项,位置为 top-start。 - 描述症状:淡入淡出结束后,较矮的子项从容器顶部“落回”父级居中位置,表现为布局故障,而问题往往不在 Crossfade 本身。
- 给出修复思路:不要通过给 Crossfade 自己的 Box 传
Alignment.Center来修(那只会让下沉变小),而是给 Crossfade 一个固定高度的父容器,并让每个分支填满它,使容器在所有状态下测量一致。 - 提醒相关陷阱:不要用 Crossfade 叠加两个测量方式不同的渲染器(如进度指示器与滑块,二者轨道长度会不一致);不要对用户正在触摸的控件做淡入淡出,因为淡出中的旧副本仍可命中测试,且若进入的分支是交互控件,整个过渡期间控件不可用;相同尺寸的子项是安全场景,绝大多数 Crossfade 属于此类,应按尺寸差异而非数量来审查。
- 说明动画键:Crossfade 默认以状态值本身为键,若分支由其他条件(捕获的标志、尺寸类别)决定,需把该条件作为状态传入,否则动画不会运行。
- 说明生命周期:过渡期间两个分支都存活,副作用(如
LaunchedEffect、请求)会继续运行并可能重复执行,昂贵工作应上移到 Crossfade 之上。 - 说明视觉对齐:把两个分支框进同一框架可让宽度与圆角一致,避免看起来像两个不同控件在切换。
使用方式
技能以文字说明与代码示例呈现。示例中,父级 Box 固定高度并设置 contentAlignment = Alignment.Center,Crossfade 的每个分支再用 Box(Modifier.fillMaxSize(), contentAlignment = Alignment.Center) 填满并居中,从而让 Crossfade 自身的 Box 尺寸恒定。
验证步骤包括:
- 从 Gradle 缓存中定位 animation-desktop 的 jar,用
javap查看androidx.compose.animation.CrossfadeKt的字节码,确认出现Alignment$Companion.getTopStart与maybeCachedBoxMeasurePolicy。 - 统计代码库中所有
Crossfade(出现次数。 - 统计其中对分支做了框架约束(
fillMaxSize()或contentAlignment)的数量。 - 手动验证:把控件切到子项较矮的状态,观察过渡结束时刻而非开始时刻;若淡入淡出完成后有沉降、跳动或几像素垂直移动,即为该问题;在小窗口尺寸下再测一次。
适用场景
- 在 Compose 中于不同状态间切换高度不同的内容(如细进度条与带滑块的控件)。
- 审查大量 Crossfade 使用点,找出真正需要固定框架的少数分支。
- 排查被误判为布局故障的过渡后位移问题。
限制
资料未提供该技能的安装命令、依赖版本、支持的平台范围或收费信息。文中给出的代码为适配示例,具体数值(如 16.dp、trackHeight、RoundedCornerShape(8.dp))需按实际项目调整。