当前位置: 首页 > news >正文

手把手教你写 Compose 动画 -- 过渡动画 API:Transition

📓 Transition


updateTransiton 是 Compose 中实现过渡动画的关键 API 。所谓过渡动画,即当依赖的某个状态发生改变时连锁发生的一系列动画效果。前面我们所提到的 Animate*AsState 与 Animatable 都是针对一个属性进行变换的,而 updateTransition 允许开发者将多个属性数值绑定到一个状态,当这个状态发生改变时,多个属性同时进行变换。

探索新技术的最佳方式是尝试它们,我们先构建一个简单场景:

class MainActivity : ComponentActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContent {Column (modifier = Modifier.fillMaxWidth(),verticalArrangement = Arrangement.Center,horizontalAlignment = Alignment.CenterHorizontally) {Spacer(modifier = Modifier.height(20.dp))Image(painter = painterResource(R.drawable.pingtouge),contentDescription = null,modifier = Modifier.size(90.dp).clip(shape = CircleShape).border(color = Color.Red, shape = CircleShape, width = 3.dp))Button(onClick = {}) {Text(text = "切换")}}}}
}

这段代码不难理解,效果如下:

在这里插入图片描述

现在我们假设一个需求场景:

  1. 图片大小 size 需要变化:小图片(90dp)、大图片(130dp)
  2. 图片边框颜色 color 需要变化:绿色、红色
  3. 对应关系:小图片绿色边框,大图片红色边框

现在我们开始讲解如何用 Transition 实现这个动画效果。

  1. 对于 updateTransition,状态可以是任何数据类型。我们自定义一个枚举类型:
private enum class ImageState {Small, Large
}
  1. 创建一个处理状态的变量:
var imageState by remember { mutableStateOf(ImageState.Small) }
  1. 创建 Transition 对象

我们先看下 updateTransition() 函数:

@Composable
fun <T> updateTransition(targetState: T,label: String? = null
): Transition<T>

它需要两个参数:

⇒ targetState:状态变量,当它被更改时,动画会进行。

⇒ label:动画的标签。

这里的状态就是我们之前定义的:imageState,所以我们可以像下面这样写:

val transition = updateTransition(targetState = imageState, label = "ImageState Transition")

updateTransition() 会返回一个 Transition 对象。

现在,我们可以使用 transition 对象来调用 animate* 函数。它们帮助我们为不同的 value 值制作动画。比如:
animateColor()、animateDp()、animateInt()、animateSize() 等。

  1. 定制边框颜色动画
val borderColor by transition.animateColor(label = "ImageState Color Transition") {when (it) {ImageState.Small -> Color.GreenImageState.Large -> Color.Magenta}
}
  1. 定制图片尺寸动画
val size by transition.animateDp(label = "ImageState Size Transition") {when (it) {ImageState.Small -> 90.dpImageState.Large -> 130.dp}
}

我们为每个属性状态(borderColor、size)声明了其在不同状态(ImageState.Small、ImageState.Large)时所对应的值,当过度动画所依赖状态(imageState)发生改变时,其中每个属性状态都会得到相应的更新。

  1. 应用到组件上(完整代码)

接下来,我们只需将创建的属性状态应用到我们的组件中即可:

private enum class ImageState {Small, Large
}class MainActivity : ComponentActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContent {var imageState by remember { mutableStateOf(ImageState.Small) }val transition = updateTransition(targetState = imageState, label = "ImageState Transition")val borderColor by transition.animateColor(label = "ImageState Color Transition") {when (it) {ImageState.Small -> Color.GreenImageState.Large -> Color.Magenta}}val size by transition.animateDp(label = "ImageState Size Transition") {when (it) {ImageState.Small -> 90.dpImageState.Large -> 130.dp}}Column (modifier = Modifier.fillMaxWidth(),verticalArrangement = Arrangement.Center,horizontalAlignment = Alignment.CenterHorizontally) {Spacer(modifier = Modifier.height(20.dp))Image(painter = painterResource(R.drawable.pingtouge),contentDescription = null,modifier = Modifier.size(size).clip(shape = CircleShape).border(color = borderColor, shape = CircleShape, width = 3.dp))Button(onClick = {imageState = if (imageState == ImageState.Small) {ImageState.Large} else {ImageState.Small}}) {Text(text = "切换")}}}}
}

效果如下:

在这里插入图片描述

相关文章:

  • 微信小程序 - PC端选择ZIP文件
  • 《Vue.js设计与实现》—Vue3响应系统的原理
  • 腾讯地图系列(二):微信小程序添加插件(三种方法)以及插件AppId获取
  • ArcGIS无法绘制一个或多个图层
  • 基于以太坊的智能合约开发Solidity(数组提升篇)
  • 智能时代:互联网+如何改变我们的生活与工作
  • STM32CubeIDE串口空闲中断实现不定长数据接收
  • 华为OD机试真题-智能成绩表-2023年OD统一考试(C卷)
  • 线性代数入门与学习笔记
  • ViT:视觉 Transformer
  • VS Code 上已达250万 Java 开发者!微软和红帽一起公布 VS Code Java 未来六个月路线图
  • 机器学习实验三:支持向量机模型
  • 连锁零售企业如何优化网络性能?
  • 【开源】基于Vue+SpringBoot的教学资源共享平台
  • Redis研学-三种特殊类型的常用命令
  • echarts的各种常用效果展示
  • ERLANG 网工修炼笔记 ---- UDP
  • JavaScript 基本功--面试宝典
  • magento2项目上线注意事项
  • python3 使用 asyncio 代替线程
  • rabbitmq延迟消息示例
  • 基于web的全景—— Pannellum小试
  • 将 Measurements 和 Units 应用到物理学
  • 入职第二天:使用koa搭建node server是种怎样的体验
  • 数据仓库的几种建模方法
  • 通过获取异步加载JS文件进度实现一个canvas环形loading图
  • 我的zsh配置, 2019最新方案
  • d²y/dx²; 偏导数问题 请问f1 f2是什么意思
  • #我与Java虚拟机的故事#连载01:人在JVM,身不由己
  • (ZT)薛涌:谈贫说富
  • (剑指Offer)面试题41:和为s的连续正数序列
  • (解决办法)ASP.NET导出Excel,打开时提示“您尝试打开文件'XXX.xls'的格式与文件扩展名指定文件不一致
  • (论文阅读笔记)Network planning with deep reinforcement learning
  • (学习日记)2024.01.09
  • (转)从零实现3D图像引擎:(8)参数化直线与3D平面函数库
  • .NET CF命令行调试器MDbg入门(一)
  • .net core控制台应用程序初识
  • .NET 除了用 Task 之外,如何自己写一个可以 await 的对象?
  • .NET 设计模式—简单工厂(Simple Factory Pattern)
  • .NET国产化改造探索(三)、银河麒麟安装.NET 8环境
  • .NET是什么
  • @data注解_SpringBoot 使用WebSocket打造在线聊天室(基于注解)
  • [AI]文心一言出圈的同时,NLP处理下的ChatGPT-4.5最新资讯
  • [bbk5179]第66集 第7章 - 数据库的维护 03
  • [BJDCTF2020]The mystery of ip
  • [C++] 统计程序耗时
  • [C++]unordered系列关联式容器
  • [G-CS-MR.PS02] 機巧之形2: Ruler Circle
  • [JDBC-1] JDBC Base Template
  • [oeasy]python0004_游乐场_和python一起玩耍_python解释器_数学运算
  • [office] 如何在Excel中拉动单元格时表头不变形- #学习方法#职场发展#经验分享
  • [python]使用pyqt5搭建yolov8 竹签计数一次性筷子计数系统
  • [SPOJ]COT2
  • [Unity3D]深度相机 Depth Camera
  • [Vue] TodoList 案例