Node:本文基于Jetpack Compose 1.0.0-beta01

Animation是由state驱动的


Compose的核心思想状态驱动UI刷新,这一思想同样体现在动画上。

Compose动画主要是通过不断计算最新的state值来刷新UI,这类似于传统的ValueAnimator,根据动画的插值器和估值器计算当前value,在映射到View的对应属性。Compose天然是基于state驱动的,相关API变得更加简单、合理。

AnimateAsState:属性动画


AnimateAsState提供了传统的属性动画的能力。

例如如下代码中,点击Button可以改变Box的颜色

@Preview
@Composable
fun AnimateAsStateDemo() {var blue by remember { mutableStateOf(true) }val color = if (blue) Blue else Red,Column(Modifier.padding(16.dp)) {Text("AnimateAsStateDemo")Spacer(Modifier.height(16.dp))Button(onClick = { blue = !blue }) {Text("Change Color")}Spacer(Modifier.height(16.dp))Box(Modifier.preferredSize(128.dp).background(color))}
}

如果想让Color以动画的方式切换,可以借助用animateColorAsState

@Composable
fun AnimateAsStateDemo() {var blue by remember { mutableStateOf(true) }val color by animateColorAsState(if (blue) Blue else Red,animationSpec = spring(Spring.StiffnessVeryLow))//...
}

animateColorAsState将Color的变化过程转换为一个可订阅的state;animationSpec用来进行动画配置,比如例子总配置了一个弹簧动画效果

监听回调

animationSped还可以监听动画结束的回调

val color by animateColorAsState(if (blue) Blue else Red,animationSpec = spring(stiffness = Spring.StiffnessVeryLow),finishedListener = {blue = !blue}
)

如上,可以实现折返动画的效果

除了AnimateColorAsState以外,还支持其他各类型的动画:

updateTransition:多个动画同步


如果想同时进行多个属性的动画,并保持同步,需要使用updateTransition,类似使用AnimationSet组合多个动画


private sealed class BoxState(val color: Color, val size: Dp) {operator fun not() = if (this is Small) Large else Smallobject Small : BoxState(Blue, 64.dp)object Large : BoxState(Red, 128.dp)
}@Composable
fun UpdateTransitionDemo() {var boxState: BoxState by remember { mutableStateOf(BoxState.Small) }val transition = updateTransition(targetState = boxState)Column(Modifier.padding(16.dp)) {Text("UpdateTransitionDemo")Spacer(Modifier.height(16.dp))val color by transition.animateColor {boxState.color}val size by transition.animateDp(transitionSpec = {if (targetState == BoxState.Large) {spring(stiffness = Spring.StiffnessVeryLow)} else {spring(stiffness = Spring.StiffnessHigh)}}) {boxState.size}Button(onClick = { boxState = !boxState }) {Text("Change Color and size")}Spacer(Modifier.height(16.dp))Box(Modifier.preferredSize(size).background(color))}
}

updateTransition根据targetState创建一个Transition,然后通过Transition的扩展函数可以创建各种属性动画所需的state。

需要注意,Transition的codename容易跟传统的位移动画混淆,其实完全没有关系,这里的Transition是用来同步多个动画的工具。

transitionSpec可以进行动画配置,上面例子中,在Box放大和缩小过程中,分别设置不同的弹性动画效果。

同样,Transition根据属性类型的不同,有多种扩展函数

AnimateVisibility:可见性动画


在View的可见性发生变化时做动画是一个常见需求。传统的View体系中,一般使用alpha值变化实现fadeIn/fadeOut,或者通过transitionX/Y的变化,实现slideIn/slideOut

Compose中则使用AnimatedVisibility

@OptIn(ExperimentalAnimationApi::class)
@Composable
fun AnimateVisibilityDemo() {var visible by remember { mutableStateOf(true) }Column(Modifier.padding(16.dp)) {Text("AnimateVisibilityDemo")Spacer(Modifier.height(16.dp))Button(onClick = { visible = !visible }) {Text(text = if (visible) "Hide" else "Show")}Spacer(Modifier.height(16.dp))AnimatedVisibility(visible) {Box(Modifier.preferredSize(128.dp).background(Blue))}}
}

如上,默认的可见性动画效果是淡入/淡出 + 收缩/放大:

AnimateContentSize : 布局大小动画

animateContentSizeModifier的扩展方法,添加这个方法的Composable,会监听子Composable大小的变化,并以动画方式作成相应调整

@Composable
fun AnimateContentSizeDemo() {var expend by remember { mutableStateOf(false) }Column(Modifier.padding(16.dp)) {Text("AnimateContentSizeDemo")Spacer(Modifier.height(16.dp))Button(onClick = { expend = !expend }) {Text(if (expend) "Shrink" else "Expand")}Spacer(Modifier.height(16.dp))Box(Modifier.background(Color.LightGray).animateContentSize()) {Text(text = "animateContentSize() animates its own size when its child modifier (or the child composable if it is already at the tail of the chain) changes size. " +"This allows the parent modifier to observe a smooth size change, resulting in an overall continuous visual change.",fontSize = 16.sp,textAlign = TextAlign.Justify,modifier = Modifier.padding(16.dp),maxLines = if (expend) Int.MAX_VALUE else 2)}}
}

animateContentSize同样可以配置animSpec以及endListener

Crossfade : 布局切换动画


Crossfade 本身是一个Composable,其内部的子布局发生切换时,可以添加淡入淡出效果:

@Composable
fun CrossfadeDemo() {var scene by remember { mutableStateOf(DemoScene.Text) }Column(Modifier.padding(16.dp)) {Text("AnimateVisibilityDemo")Spacer(Modifier.height(16.dp))Button(onClick = {scene = when (scene) {DemoScene.Text -> DemoScene.IconDemoScene.Icon -> DemoScene.Text}}) {Text("toggle")}Spacer(Modifier.height(16.dp))Crossfade(current = scene,animation = tween(durationMillis = 1000)) {when (scene) {DemoScene.Text ->Text(text = "Phone", fontSize = 32.sp)DemoScene.Icon ->Icon(imageVector = Icons.Default.Phone,null,modifier = Modifier.preferredSize(48.dp))}}}
}

参考


Sample Code

Jetpack Compose Animations 超简单教程相关推荐

  1. 【微信小程序系列】微信小程序超简单教程,基本语法,获取用户基本数据信息,实现对云数据库的增删改查及小程序外部api的引用示例(附源码)

    [微信小程序系列]微信小程序超简单教程 小程序项目结构 静态页面的构成 HTML:结构 css:样式 js:行为 小程序 页面全部存放在pages, 而且pages目录只能存放页面 页面包括4个文件, ...

  2. 苹果,U盘越狱iPhone绕ID最新教程及各种坑解决,吐血之作(超详细超简单教程)-balenaEtcher-Checkm8-bootra1n

    U盘越狱iPhone绕ID最新教程及各种坑解决,吐血之作(超详细超简单教程)-balenaEtcher-Checkm8-bootra1n 这是安装多个苹果版本及虚拟机版本后成功的教程,由于资源上传到百 ...

  3. 宝塔linux输入bt,Linux宝塔面板如何挂载硬盘?BT宝塔面板磁盘挂载超简单教程来了!...

    Linux宝塔面板如何挂载硬盘?BT宝塔面板磁盘挂载超简单教程来了! 为解决这个问题,我们制作了磁盘自动挂载工具,支持Centos.Ubuntu.Debian.Fedora说明: 1:本工具默认将数据 ...

  4. 网页添加Live 2D看板娘超简单教程——伸手即可带走

    什么是看板娘?移目至左下角,这就是看板娘! 什么?没出来?鼠标放上去只有文字?那是因为源代码放在GitHub上,GitHub国外的网站,国内加载的慢啊,稍稍等一下啦,客官也可以亲自去GitHub拉源代 ...

  5. 搭建React项目,超简单教程

    步骤 前言 一.安装create-react-app 二.使用步骤 1.创建项目 2.运行项目 3.文件目录 总结 前言 最近公司闲的无聊,刚好之前学的React,至今还未搭建过一个React项目,借 ...

  6. 一加3t刷机后还卡_一加8T/8/8Pro 氢OS11刷入面具magisk完美root权限超简单教程

    本教程仅在一加氢OS11系统上测试通过,目前已知支持一加8/8Pro/8T等全部版本,也是目前安卓11平台最稳妥的刷机root方法,推荐使用最新版本面具,旧版本面具将不再支持教程适用于动手能力很强的小 ...

  7. C语言链表超简单教程

    笔者作为一名C语言的初学者,在刚接触链表时,几乎找不到教程能用很通俗易懂的语言去讲解链表.大多数时候找到的关于链表的教程,或许是生硬的塞给读者一大段代码,或许是使用了一些过于专业的词汇,对于萌新非常地 ...

  8. 博客园随机切换背景图,超简单教程

    目录 一.前言 二.准备工作 三.实现代码 四.结尾 一.前言 博客园做的还是挺强大的,很多东西都支持自定义,比较适合喜欢瞎捣鼓的小伙伴.之前写过一篇博客园看板娘的教程,有兴趣的小伙伴可以看一下:ht ...

  9. 没有光驱 u盘 重装linux系统盘,没有U盘、光驱,如何重装系统?超简单教程!

    一说到重装系统,我们首先想到的就是用U盘或者使用光驱加上系统光盘,但是很多时候,由于条件的限制,没有U盘或者光驱,那么问题就来了,这时我要如何重装系统呢?今天小编就来教大家如何在不使用U盘和光驱的情况 ...

最新文章

  1. QIIME 2教程. 27语义类型Semantic(2020.11)
  2. AndoridSQLite数据库开发基础教程(8)
  3. C#压缩解压zip 文件
  4. 那些常见的Web前端学习误区分享
  5. php如何在mysql数据库里创建表_php创建mysql数据库以及数据表
  6. 数据 格式化 format
  7. leetcode62. 不同路径
  8. ZOJ 3826 Hierarchical Notation 模拟
  9. 管理感悟:忙的真正含义是没心思
  10. \n \r \r\n
  11. 高斯过程回归matlab,高斯过程回归及其应用.PDF
  12. python窗口居中_Tkinter窗口在屏幕居中的问题
  13. 链表节点被删除时的资源释放
  14. springBoot发送邮件附件名称乱码的解决
  15. 拓嘉启远电商:如何搭建拼多多的私域流量池
  16. Unity 3D之实现鱼竿模拟
  17. 登录网站空间无法连接服务器,网站空间打不开的处理办法
  18. 现在转行做程序员还有必要吗,培训班有必要去吗?
  19. 基于GUI的学生成绩管理系统
  20. 2014-04-25

热门文章

  1. Autosar MCAL-ADC详解(二)-基于Tc27x的cfg软件
  2. Win10在桌面上怎么添加此电脑、网络图标、回收站等图标?
  3. 将Excel表格中的文本格式存储的数字批量转换为数字
  4. TCP/IP协议十二:关于MAC地址和IP地址在传输过程中变与不变的问题
  5. java毕业设计车辆违规信息管理系统Mybatis+系统+数据库+调试部署
  6. 计算机乘法原理 移位,原码乘法,原码乘法原理详解
  7. 整合百度AI实现手机拍照识别车牌号
  8. ObjectArx自定义实体入门(C++)及注意事项
  9. 【数模系列】02_三大相关系数+Python代码
  10. 网站使用CDN加速的5个优势