Jetpack Compose 动画Modifier.animateContentSize()

在 Jetpack Compose 中,Modifier.animateContentSize() 是一个非常实用且优雅的修饰符,专门用来为组件尺寸的变化添加平滑的过渡动画。

一、 animateContentSize 的核心作用

在默认情况下,如果一个 Composable 的内容发生改变导致其尺寸(宽度或高度)发生变化(例如:展开折叠面板、文字由短变长、动态加载出图片等),UI 会瞬间"闪现"到新的大小。

而 Modifier.animateContentSize() 的作用是:

  1. 自动捕获尺寸变化:当子组件的测量尺寸发生变化时,它会自动介入。

  2. 平滑过渡动画:它会在旧尺寸和新尺寸之间自动插值,产生平滑的过渡动画(默认使用弹簧动画 spring),避免突兀的跳变。

二、 完整代码例子

下面的例子展示了一个常见的可折叠卡片(Expandable Card)场景。当点击卡片时,文字内容展开或收起,卡片的高度会平滑地拉伸或收缩:

复制代码
@Composable
fun ExpandableCardExample() {
    // 记录卡片是否展开的状态
    var expanded by remember { mutableStateOf(false) }

    Card(
        modifier = Modifier
            .fillMaxWidth()
            .padding(16.dp)
            // 点击整张卡片切换展开/收起状态
            .clickable { expanded = !expanded }
    ) {
        Column(
            modifier = Modifier
                .fillMaxWidth()
                // 【关键点】:在这里调用 animateContentSize()
                // 当 Column 内部高度因文字增减而变化时,高度变化会产生平滑动画
                .animateContentSize(
                    animationSpec = spring(
                        dampingRatio = Spring.DampingRatioMediumBouncy,
                        stiffness = Spring.StiffnessLow
                    )
                )
                .padding(16.dp)
        ) {
            Text(
                text = "点击这里可以展开/收起内容",
                style = MaterialTheme.typography.titleMedium
            )

            // 当 expanded 为 true 时显示详细内容,为 false 时不显示
            if (expanded) {
                Spacer(modifier = Modifier.height(8.dp))
                Text(
                    text = "这是隐藏的详细内容。当状态改变时,由于外层容器应用了 " +
                            "animateContentSize(),卡片的高度会自动且平滑地伸展出来," +
                            "而不是瞬间闪现,给用户极佳的视觉体验。",
                    style = MaterialTheme.typography.bodyMedium
                )
            }
        }
    }
}

三、 使用时的关键细节(注意事项)

  1. 链式调用的顺序非常重要:
  • 如果你希望内边距(padding)也参与动画,将 animateContentSize() 放在 .padding() 之前。
  • 如果你希望内边距保持固定,只有内部文本/子组件区域参与动画,将它放在 .padding() 之后。
  1. 它和 AnimatedVisibility 的区别:
  • animateContentSize 适合同一个容器内由于内容增减导致整体尺寸变化的场景(比如变长文本、动态增减列表项高度)。
  • AnimatedVisibility 更适合专门控制某个独立子组件的淡入淡出、展开/折叠显示。
相关推荐
事圆则缓1 小时前
Android 版本号、API Level 和 JDK 版本有什么关系?
android
zhangguojia71 小时前
Android Activity 生命周期结束流程:从 finish() 到 onDestroy() 的跨进程状态调度
android
Jewel1052 小时前
文字为什么总是不居中!记录一个bug
android·flutter·ios
mmsx2 小时前
Android 并发考古:newThread 与 RxJava 共存,以及 GlobalScope 的三宗罪
android·echarts·rxjava
骑着蜗牛撵大象3272 小时前
大模型 SDK 编译就崩?用 CMakeLists 把 httplib、JSON 与 OpenSSL 装配成可复用的 ChatServer
android·java·c++·http·json·cmake·大模型sdk
海水冷却12 小时前
Android 群组聊天怎么实现:基于 ZIM 的完整落地指南(附可运行 Demo)
android
三少爷的鞋14 小时前
现代 Android 架构指南:不要再主动设计 Callback 接口
android
TimeFine20 小时前
AI 编码工作流的设计
android·ai编程
骑着蜗牛撵大象32721 小时前
C++20 协程 × 屏障:手写一个 co_await 版 Barrier,让等待不再钉死线程
android·c++20·协程·并发编程·co_await·屏障同步