前言
本节课学习 AnimatedVisibility 显隐动画组件。实现组件出现与消失时的淡入淡出、滑动进出过渡;结合状态控制动画,复习Scaffold、Button、Card。
知识点清单
- AnimatedVisibility 的基础作用:基于布尔状态控制组件显示、隐藏并附带过渡动画
- enter 入场动画(淡入、向下滑入)
- exit 退场动画(淡出、向上滑出)
- 默认动画与自定义入场退场参数
- 业务实战:点击按钮控制一块卡片区域带动画显示与消失
完整示例源码
@ComposablefunAnimatedVisibilityDemoPage(){varshowPanelbyremember{mutableStateOf(false)}Scaffold(topBar={TopAppBar(title={Text("AnimatedVisibility动画演示")})}){innerPadding->Column(modifier=Modifier.fillMaxSize().padding(innerPadding).padding(20.dp),verticalArrangement=Arrangement.spacedBy(16.dp)){Button(onClick={showPanel=!showPanel}){Text(if(showPanel)"隐藏面板"else"显示面板")}AnimatedVisibility(visible=showPanel,enter=fadeIn()+slideInVertically(initialOffsetY={-40}),exit=fadeOut()+slideOutVertically(targetOffsetY={40})){Card(modifier=Modifier.fillMaxWidth(),elevation=CardDefaults.cardElevation(6.dp)){Column(modifier=Modifier.padding(20.dp)){Text(text="通知提示面板",fontSize=20.sp,fontWeight=FontWeight.Bold)Text(text="这一块内容的出现和消失带有组合动画效果。",fontSize=16.sp)}}}}}}逐行解读
- AnimatedVisibility核心参数 visible
visible: Boolean ;布尔状态控制是否显示内部内容。当 visible 从false变为true,执行enter入场动画;true变为false,执行exit退场动画。 - 动画组合 fadeIn() + slideInVertically()
可以使用 + 把多个入场动画叠加在一起;同时执行淡入 + 垂直滑动入场。
- slideInVertically(initialOffsetY = {‑40}) :入场的时候起始位置向上偏移‑40px,然后向下滑入正常位置;
- slideOutVertically(targetOffsetY = {40}) :消失的时候向下偏移滑出去;
注意这里单位是像素px,不是dp,lambda返回整数。
- 默认动画
如果不写enter、exit,AnimatedVisibility自带默认淡入淡出动画。 - 状态驱动动画逻辑
点击按钮反转 showPanel 布尔值;状态变更触发重组,组件自动执行入场或者退场动画。
AnimatedVisibility是Compose声明式动画;不需要调用start()、stop()命令式启动动画,修改状态就自动播放动画。
容易踩坑
- ❌ 不要使用if直接包裹Card做显示隐藏;if是瞬间直接移除组件,没有过渡动画。
- ❌ slide偏移里面是px,不是dp;不要直接写dp数值。
- ❌ AnimatedVisibility里面放置复杂布局(LazyColumn等)也可以;但是不要在动画过程中频繁修改内部大量数据。
- ✅ enter和exit成对定义;入场和退场尽量视觉上保持方向呼应,用户体验更好。
多元化习题(每道题后紧跟答案+解读)
习题1【基础‑改错题】
题目:下面代码直接if判断,没有动画效果,请改成带动画显隐。
varshowBoxbyremember{mutableStateOf(false)}if(showBox){Card(){Text("测试内容")}}答案:
varshowBoxbyremember{mutableStateOf(false)}AnimatedVisibility(visible=showBox){Card(){Text("测试内容")}}解读:
普通if条件,满足就渲染,不满足直接移除,瞬间消失;AnimatedVisibility在状态切换的时候,先播放过渡动画,动画结束之后才完成组件挂载或者卸载,实现平滑过渡。
习题2【基础‑代码修改题】
题目:修改本课示例,把入场动画修改为从右侧滑入,退场从左侧滑出;依然叠加淡入淡出。
答案:
AnimatedVisibility(visible=showPanel,enter=fadeIn()+slideInHorizontally(initialOffsetX={200}),exit=fadeOut()+slideOutHorizontally(targetOffsetX={-200})){Card(modifier=Modifier.fillMaxWidth(),elevation=CardDefaults.cardElevation(6.dp)){Column(modifier=Modifier.padding(20.dp)){Text(text="通知提示面板",fontSize=20.sp,fontWeight=FontWeight.Bold)Text(text="这一块内容的出现和消失带有组合动画效果。",fontSize=16.sp)}}}解读:
横向滑动使用 slideInHorizontally / slideOutHorizontally ;initialOffsetX是入场起始横向偏移px;targetOffsetX是退场结束位置;正数代表向右,负数代表向左;叠加fadeIn/fadeOut保留透明度渐变。
习题3【进阶‑补充代码题】
题目:新增一个布尔状态 showTip ;当点击悬浮按钮之后 showTip=true ,显示一行提示文本,2秒之后自动隐藏提示。(提示使用LaunchedEffect延时修改状态)补充LaunchedEffect延时逻辑片段。
答案:
varshowTipbyremember{mutableStateOf(false)}LaunchedEffect(showTip){if(showTip){delay(2000L)showTip=false}}AnimatedVisibility(visible=showTip){Text(text="操作成功!",modifier=Modifier.padding(12.dp))}解读:
LaunchedEffect 开启协程;delay(2000L)延时2000毫秒;延时结束之后把showTip置false;提示文本自动带着退场动画消失;注意delay是挂起函数,只能写在协程作用域内,不能直接写在可组合函数顶层。
习题4【综合‑逻辑应用题】
题目:业务需求:有两个面板panelA、panelB;同一时刻只能显示其中一块;点击切换按钮,在两块卡片之间带动画切换显示。写出核心状态以及AnimatedVisibility片段。
答案:
varselectPanelAbyremember{mutableStateOf(true)}Button(onClick={selectPanelA=!selectPanelA}){Text("切换面板")}AnimatedVisibility(visible=selectPanelA){Card(modifier=Modifier.fillMaxWidth()){Text("面板A内容",modifier=Modifier.padding(16.dp))}}AnimatedVisibility(visible=!selectPanelA){Card(modifier=Modifier.fillMaxWidth()){Text("面板B内容",modifier=Modifier.padding(16.dp))}}解读:
使用同一个布尔状态,分别取正和取反作为两个AnimatedVisibility的visible条件;点击按钮翻转布尔值;一块执行退场动画消失,另一块执行入场动画出现;完成两块面板切换。
习题5【概念简答题】
题目:普通if条件渲染组件 和 AnimatedVisibility 的区别是什么?
答案:
if条件:条件成立直接渲染组件,不成立立刻移除组件,没有过渡动画。
AnimatedVisibility:基于visible布尔值;状态改变时先播放入场或者退场过渡动画;动画执行完毕之后才完成组件挂载或者销毁,实现平滑过渡。
解读:
AnimatedVisibility依然属于声明式动画,依靠状态驱动,不需要手动调用动画播放方法;适合弹窗、提示面板、折叠区域的显隐效果。
本节课知识点总结
- AnimatedVisibility(visible = 布尔值) 用来做组件的显示隐藏过渡动画。
- enter定义入场动画,exit定义退场动画;支持使用 + 叠加多种动画(透明度fade、横向/纵向slide滑动);slide里面偏移单位是px。
- 不要用普通if来实现需要过渡的显隐业务。
- 配合LaunchedEffect+delay协程延时,可以实现自动消失的提示消息。
- 同一页面多块面板切换,可以利用同一个状态变量控制多个AnimatedVisibility的visible属性,完成面板切换动画。
下一课预告:第18课 项目综合小实战:简易待办Todo清单(整合前面全部知识点)