Compose笔记(二十一)--AnimationVisibility

        这一节主要了解一下Compose的AnimationVisibility,AnimatedVisibility 是 Jetpack Compose 里用于实现组件可见性动画效果的组件,借助它能让组件在显示和隐藏时带有平滑的过渡动画,从而提升用户体验。现总结如下:

API
1. visible
含义:这是一个布尔类型的参数,用于控制组件的可见性。当 visible为true时,组件会显示;当visible为false时,组件会隐藏。
作用:它是控制组件显示与隐藏的核心参数,配合动画效果可以实现平滑的过渡。
2. enter
含义:指定组件进入(显示)时的动画效果。enter参数接收一个EnterTransition类型的值,Compose提供了多种内置的进入动画,如fadeIn()、slideInHorizontally()等,也可以自定义进入动画。
作用:让组件在显示时带有动画效果,增强界面的动态感和视觉效果。
3. exit
含义:指定组件退出(隐藏)时的动画效果。exit参数接收一个ExitTransition 类型的值,Compose提供了多种内置的退出动画,如fadeOut()、slideOutHorizontally()等,也可以自定义退出动画。
作用:让组件在隐藏时带有动画效果,使界面的变化更加平滑自然。
4. initiallyVisible
含义:这是一个布尔类型的可选参数,用于设置组件的初始可见性。默认值为true,即组件在初始状态下是可见的。
作用:方便在组件首次显示时就设置其可见性,结合动画效果可以实现更丰富的界面展示。
5. content
含义:它是一个@Composable函数,用于定义要显示或隐藏的组件内容。
作用:将需要进行可见性动画的组件包裹在content函数中,以便应用动画效果。

常见动画类型:
1. 淡入动画(fadeIn)
 让组件在显示时从透明逐渐变为不透明,实现淡入效果。
2 淡出动画(fadeOut)
 让组件在隐藏时从不透明逐渐变为透明,实现淡出效果。
3 滑入动画(slideIn)
 slideInHorizontally:使组件从水平方向滑入屏幕。
4 滑出动画(slideOut)
slideOutHorizontally:使组件从水平方向滑出屏幕。
5. 缩放进入动画(scaleIn)
 让组件在显示时从较小的尺寸逐渐放大到正常尺寸。
6. 缩放退出动画(scaleOut)
让组件在隐藏时从正常尺寸逐渐缩小。

栗子:

import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.core.tween
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.slideInHorizontally
import androidx.compose.animation.slideOutHorizontally
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Button
import androidx.compose.material3.Card
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp@Composable
fun TestAnimatedVisibilityOne() {var isCardVisible by remember { mutableStateOf(false) }var isTextVisible by remember { mutableStateOf(false) }Column(modifier = Modifier.fillMaxSize(),verticalArrangement = Arrangement.Center,horizontalAlignment = Alignment.CenterHorizontally) {Row(modifier = Modifier.fillMaxWidth(),horizontalArrangement = Arrangement.SpaceEvenly) {Button(onClick = { isCardVisible = !isCardVisible }) {Text(text = if (isCardVisible) "隐藏卡片" else "显示卡片")}Button(onClick = { isTextVisible = !isTextVisible }) {Text(text = if (isTextVisible) "隐藏文本" else "显示文本")}}Spacer(modifier = Modifier.height(20.dp))AnimatedVisibility(visible = isCardVisible,enter = slideInHorizontally(initialOffsetX = { -it },animationSpec = tween(durationMillis = 500)) + fadeIn(animationSpec = tween(durationMillis = 500)),exit = slideOutHorizontally(targetOffsetX = { -it },animationSpec = tween(durationMillis = 500)) + fadeOut(animationSpec = tween(durationMillis = 500))) {Card(modifier = Modifier.fillMaxWidth().padding(16.dp)) {Text(text = "这是一个卡片组件",modifier = Modifier.padding(16.dp))}}Spacer(modifier = Modifier.height(20.dp))AnimatedVisibility(visible = isTextVisible,enter = slideInHorizontally(initialOffsetX = { it },animationSpec = tween(durationMillis = 500)) + fadeIn(animationSpec = tween(durationMillis = 500)),exit = slideOutHorizontally(targetOffsetX = { it },animationSpec = tween(durationMillis = 500)) + fadeOut(animationSpec = tween(durationMillis = 500))) {Box(modifier = Modifier.fillMaxWidth().padding(16.dp),contentAlignment = Alignment.Center) {Text(text = "这是一个文本组件")}}}
}

分析:主要演示当点击按钮时,卡片和文本会以不同的动画效果显示或隐藏。

import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.expandVertically
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.shrinkVertically
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.material3.Button
import androidx.compose.material3.Card
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp@Composable
fun TestAnimatedVisibility() {val items = remember {mutableStateListOf("Item 1", "Item 2", "Item 3", "Item 4", "Item 5")}val expandedIndices = remember { mutableStateListOf<Int>() }LazyColumn(modifier = Modifier.fillMaxSize(),verticalArrangement = Arrangement.spacedBy(16.dp),contentPadding = androidx.compose.foundation.layout.PaddingValues(16.dp)) {itemsIndexed(items) { index, item ->Card(modifier = Modifier.fillMaxWidth()) {Column(modifier = Modifier.padding(16.dp)) {Button(onClick = {if (expandedIndices.contains(index)) {expandedIndices.remove(index)} else {expandedIndices.add(index)}},modifier = Modifier.fillMaxWidth()) {Text(text = item)}AnimatedVisibility(visible = expandedIndices.contains(index),enter = expandVertically(expandFrom = Alignment.Top) + fadeIn(initialAlpha = 0.3f),exit = shrinkVertically() + fadeOut()) {Text(text = "这是 $item 的详细信息",modifier = Modifier.padding(top = 8.dp))}}}}}
}

分析: AnimatedVisibility 与列表结合使用。当点击列表项时,该项的详细信息会以动画形式展开或收缩。

注意:
1 状态管理不当引发的问题,如果没有正确管理 AnimatedVisibility 的可见性状态,可能会出现动画不按预期执行,或者在重组时状态丢失的情况。
2 动画配置冲突 当组合多个动画时,如果动画的配置相互冲突,可能会导致动画效果不符合预期,甚至出现卡顿现象。
3 动画完成回调缺失,AnimatedVisibility 本身没有直接提供动画完成的回调,若需要在动画完成后执行特定操作,会比较麻烦,可以借助 LaunchedEffect 和 AnimatedVisibilityState 来监听动画的完成状态。

源码:

@Composable
fun AnimatedVisibility(visible: Boolean,modifier: Modifier = Modifier,enter: EnterTransition = fadeIn() + expandVertically(),exit: ExitTransition = shrinkVertically() + fadeOut(),initiallyVisible: Boolean = true,content: @Composable () -> Unit
) {// 管理可见性状态val visibilityState = rememberAnimatedVisibilityState(initiallyVisible = initiallyVisible,visible = visible)// 应用动画AnimatedVisibilityImpl(visibilityState = visibilityState,modifier = modifier,enter = enter,exit = exit,content = content)
}

分析:
visible:控制组件的可见性。
enter和exit:分别指定进入和退出动画。
initiallyVisible:设置组件的初始可见性。
content:要显示或隐藏的组件内容。
调用rememberAnimatedVisibilityState函数创建并管理可见性状态。
调用AnimatedVisibilityImpl 函数应用动画。

@Composable
fun rememberAnimatedVisibilityState(initiallyVisible: Boolean,visible: Boolean
): AnimatedVisibilityState {val state = remember { AnimatedVisibilityState(initiallyVisible) }LaunchedEffect(visible) {if (visible) {state.show()} else {state.hide()}}return state
}

分析:
使用 remember 函数创建并存储 AnimatedVisibilityState 实例。
通过 LaunchedEffect监听visible参数的变化,当visible改变时,调用state.show()或state.hide()方法触发动画。

class AnimatedVisibilityState(initiallyVisible: Boolean) {var targetVisibility by mutableStateOf(initiallyVisible)var isVisible: Booleanget() = targetVisibility || isAnimationRunningprivate set(_) {}var isAnimationRunning by mutableStateOf(false)suspend fun show() {if (targetVisibility) returntargetVisibility = trueisAnimationRunning = truetry {// 执行进入动画// 这里会根据具体的 EnterTransition 执行动画逻辑} finally {isAnimationRunning = false}}suspend fun hide() {if (!targetVisibility) returntargetVisibility = falseisAnimationRunning = truetry {// 执行退出动画// 这里会根据具体的 ExitTransition 执行动画逻辑} finally {isAnimationRunning = false}}
}

分析:
targetVisibility:存储目标可见性状态。
isVisible:表示组件当前是否可见,考虑了动画执行状态。
isAnimationRunning:记录动画是否正在执行。
show()和hide()方法:分别触发进入和退出动画,在动画执行期间将isAnimationRunning设置为true,动画结束后设置为false。

AnimatedVisibilityImpl 函数

@Composable
private fun AnimatedVisibilityImpl(visibilityState: AnimatedVisibilityState,modifier: Modifier,enter: EnterTransition,exit: ExitTransition,content: @Composable () -> Unit
) {if (visibilityState.isVisible) {// 根据动画状态应用过渡效果val transition = updateTransition(visibilityState.targetVisibility, label = "AnimatedVisibility")val enterFraction = transition.animateFloat(transitionSpec = { enter.animationSpec },label = "EnterFraction") { targetVisible ->if (targetVisible) 1f else 0f}.valueval exitFraction = transition.animateFloat(transitionSpec = { exit.animationSpec },label = "ExitFraction") { targetVisible ->if (targetVisible) 0f else 1f}.value// 根据动画进度应用修饰符val animatedModifier = modifier.then(enter.createModifier(enterFraction)).then(exit.createModifier(exitFraction))// 显示组件内容Box(animatedModifier) {content()}}
}

分析:
若visibilityState.isVisible为true,则创建 updateTransition来管理动画过渡。
分别计算进入和退出动画的进度enterFraction和exitFraction。
根据动画进度应用enter和 exit 动画的修饰符。
使用Box组件包裹content,并应用动画修饰符。
        简而言之,AnimatedVisibility 的源码核心在于状态管理和动画调度。通过 AnimatedVisibilityState管理可见性状态和动画执行状态,利用updateTransition实现动画过渡,最终根据动画进度动态调整组件的属性,实现平滑的可见性动画效果。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/903623.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于 HT 构建 2D 智慧仓储可视化系统的技术解析

在当今数字化时代&#xff0c;仓储管理对于企业的运营效率和成本控制愈发关键。图扑软件&#xff08;Hightopo&#xff09;凭借其强大的 HT for Web 产品&#xff0c;打造出 2D 智慧仓储可视化平台&#xff0c;为仓储管理带来了全新的技术解决方案。 HT 是一款基于 WebGL、can…

HTML ASCII 编码详解

HTML ASCII 编码详解 引言 HTML&#xff08;HyperText Markup Language&#xff09;是一种用于创建网页的标准标记语言。在HTML中&#xff0c;字符的表示方式非常重要&#xff0c;因为它直接影响到网页内容的显示效果。ASCII编码作为一种基本的字符编码方式&#xff0c;在HTM…

pinia-plugin-persistedstate的使用

pinia持久化存储的使用 安装 npm install pinia-plugin-persistedstate 注册 import { createPinia } from pinia import piniaPluginPersistedstate from pinia-plugin-persistedstateconst pinia createPinia() pinia.use(piniaPluginPersistedstate)export default pinia …

Vue:el-table-tree懒加载数据

目录 一、出现场景二、具体使用三、修改时重新加载树节点四、新增、删除重新加载树节点 一、出现场景 在项目的开发过程中&#xff0c;我们经常会使用到表格树的格式&#xff0c;但是犹豫数据较多&#xff0c;使用分页又不符合项目需求时&#xff0c;就需要对树进行懒加载的操…

ChipCN IDE KF32 导入工程后,无法编译的问题

使用ChipON IDE for KungFu32 导入已有的工程是时&#xff0c;发现能够编译&#xff0c;但是点击&#xff0c;同时选择硬件调试时 没有任何响应。查看工程调试配置时&#xff0c;发现如下问题&#xff1a; 没有看到添加有启动配置&#xff0c;说明就是这里的问题了(应该是IDE的…

前端笔记-Element-Plus

结束了vue的基础学习&#xff0c;现在进一步学习组件 Element-Plus部分学习目标&#xff1a; Element Plus1、查阅官方文档指南2、学习常用组件的使用方法3、Table、Pagination、Form4、Input、Input Number、Switch、Select、Date Picker、Button5、Message、MessageBox、N…

C++入门小馆: 模板

嘿&#xff0c;各位技术潮人&#xff01;好久不见甚是想念。生活就像一场奇妙冒险&#xff0c;而编程就是那把超酷的万能钥匙。此刻&#xff0c;阳光洒在键盘上&#xff0c;灵感在指尖跳跃&#xff0c;让我们抛开一切束缚&#xff0c;给平淡日子加点料&#xff0c;注入满满的pa…

强化学习之基于无模型的算法之基于值函数的深度强化学习算法

3、基于值函数的深度强化学习算法 1&#xff09;深度Q网络&#xff08;DQN&#xff09; 核心思想 DQN是一种将Q学习与深度神经网络结合的方法&#xff0c;用于解决高维状态空间的问题。 它以环境的状态作为输入&#xff0c;通过神经网络输出每个动作的 Q 值&#xff0c;智能体…

网络规划和设计

1.结构化综合布线系统包括建筑物综合布线系统PDS&#xff0c;智能大夏布线系统IBS和工业布线系统IDS 2.GB 50311-2016综合布线系统工程设计规范 GB/T 50312-2016综合布线系统工程验收规范 3.结构化布线系统分为6个子系统&#xff1a; 工作区子系统&#xff1b;水平布线子系…

软件设计师-错题笔记-计算机硬件和体系

1. 解析&#xff1a;循环冗余校验码也叫CRC校验码&#xff0c;其中运算包括了模2&#xff08;异或&#xff09;来构造校验位。别的三种没有用到模2的方法。 2. 解析&#xff1a;如果是正数&#xff0c;则是首位为0&#xff0c;其余位全为1&#xff0c;这时最大数(2^(n-1))-1…

OpenCV 4.7企业级开发实战:从图像处理到目标检测的全方位指南

简介 OpenCV作为工业级计算机视觉开发的核心工具库,其4.7版本在图像处理、视频分析和深度学习模型推理方面实现了显著优化。 本文将从零开始,系统讲解OpenCV 4.7的核心特性和功能更新,同时结合企业级应用场景,提供详细代码示例和实战项目,帮助读者掌握从基础图像处理到复…

LeetCode算法题 (除自身以外数组的乘积)Day14!!!C/C++

https://leetcode.cn/problems/product-of-array-except-self/description/ 一、题目分析 给你一个整数数组 nums&#xff0c;返回 数组 answer &#xff0c;其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀…

如何写好Verilog状态机

还记得之前软件的同事说过的一句话。怎么凸显自己的工作量&#xff0c;就是自己给自己写BUG。 看过夏宇闻老师书的都知道&#xff0c;verilog的FSM有moore和mealy,然后有一段&#xff0c;二段&#xff0c;三段式。记得我还是学生的时候&#xff0c;看到这里的时候&#xff0c;感…

晶振频率/稳定度/精度/温度特性的深度解析与测量技巧

在电子设备的精密世界里&#xff0c;晶振如同跳动的心脏&#xff0c;为各类系统提供稳定的时钟信号。晶振的频率、稳定度、精度以及温度特性&#xff0c;这些关键参数不仅决定了设备的性能&#xff0c;更在不同的应用场景中发挥着至关重要的作用。 一、频率选择的本质&#xff…

Kafka-可视化工具-Offset Explorer

安装&#xff1a; 下载地址&#xff1a;Offset Explorer 安装好后如图&#xff1a; 1、下载安装完毕&#xff0c;进行新增连接&#xff0c;启动offsetexplorer.exe&#xff0c;在Add Cluster窗口Properties 选项下填写Cluster name 和 kafka Cluster Version Cluster name (集…

LabVIEW模板之温度监测应用

这是一个温度监测应用程序&#xff0c;基于 Continuous Measurement and Logging 示例项目构建&#xff0c;用于读取模拟温度值&#xff0c;当温度超出给定范围时发出警报 。 这个。 详细说明 运行操作&#xff1a;直接运行该 VI 程序。点击 “Start” 按钮&#xff0c;即可开…

后端[特殊字符][特殊字符]看前端之Row与Col

是的&#xff0c;在 Ant Design 的栅格布局系统中&#xff0c;每个 <Row> 组件确实对应页面上的一个独立行。以下是更详细的解释&#xff1a; 核心概念 组件作用类比现实场景<Row>横向容器&#xff0c;定义一行内容类似 Excel 表格中的一行<Col>纵向分割&am…

[特殊字符] SpringCloud项目中使用OpenFeign进行微服务远程调用详解(含连接池与日志配置)

&#x1f4da; 目录 为什么要用OpenFeign&#xff1f; 在cart-service中整合OpenFeign 2.1 引入依赖 2.2 启用OpenFeign 2.3 编写Feign客户端 2.4 调用Feign接口 开启连接池&#xff0c;优化Feign性能 3.1 引入OkHttp 3.2 配置启用OkHttp连接池 3.3 验证连接池生效 Feign最佳…

VARIAN安捷伦真空泵维修清洁保养操作SOP换油操作流程内部转子图文并茂内部培训手侧

VARIAN安捷伦真空泵维修清洁保养操作SOP换油操作流程内部转子图文并茂内部培训手侧