Android compose气泡升起和水滴下坠动画实现示例
作者:AiLo 发布时间:2023-04-09 01:52:22
摘要
今天用compose来构建一个气泡上升粘连动画和水滴下坠动画,Github源码点击这里
知识点
compose动画
贝塞尔曲线
缓动函数
compose canvas
解析
compose动画使用updateTransition
,理由是:
updateTransition
可以管理多个动画作为子项,并且可以在多个状态间同时运行这个动画恰巧需要维护两个状态,自定义状态数据Circle和Bubble
贝塞尔曲线,两个动画球之前的粘连效果使用贝塞尔曲线达成,目前android提供了二阶和三阶的贝塞尔曲线,在此处作动画够用了
==缓动函数==
动画当然是越接近现实中的物理规则越好看
++缓动函数++自定义参数随时间变化的规律,特定的缓动函数有助于动画的良好构建
compose中提供了Easing来做差值器,常见的有:compose内置的EaseIN
所有效果都由canvas画出,就是一些主要的canvas的api的熟练度问题
代码实现
其实这种动画在工程实装的时候,比较麻烦的一个点就是状态的管理,可能会写不少的代码用来维护以及表示当前动画的状态。 使用updateTransition
这个api的好处就是可以借用它的参数targetState来帮我们管理维护当前动画的状态。
val transition = updateTransition(targetState = currentState, label = "Water")
val durationMillis = 1111
val progress by transition.animateFloat(label = "Water", transitionSpec = {
when {
WaterState.Circle isTransitioningTo WaterState.Bubble ->
TweenSpec(durationMillis = durationMillis, easing = EaseOutBounce)
else -> TweenSpec(durationMillis = durationMillis, easing = EaseOutExpo)
}
}) {
when (it) {
WaterState.Bubble -> 1f
WaterState.Circle -> -0.2f
}
}
在这段代码里我们维护了两个状态,并且在不同的状态切换间使用了不同的transitionSpec
动画绘制
结构
两种状态下的动画结构都是一致的,跟qq的粘连小球动画结构一样,两个圆形以及中间联结的两段贝塞尔曲线
circle to bubble
val fixCircleCenterX = centerX
val fixCircleCenterY = centerY
val currentCircleRadius = pointRadius * (1f - linearProgress)
drawCircle(
color = pointColor,
radius = currentCircleRadius,
center = Offset(x = fixCircleCenterX, y = fixCircleCenterY)
)
val bubbleCenterX = centerX
val currentDist = gap * linearProgress * 1.25f
val bubbleCenterY = fixCircleCenterY - currentDist
val linearChangeBubbleCenterY = fixCircleCenterY - gap * linearProgress * 1.25f
val iAnchorX = bubbleCenterX
val iAnchorY = (fixCircleCenterY + linearChangeBubbleCenterY) * 0.5f
val linearChangedBubbleRadius = pointRadius + (bubbleRadius - pointRadius) * linearProgress
val currentBubbleRadius = pointRadius + (bubbleRadius - pointRadius) * progress
val angel = 30.0
val iBubStartX = bubbleCenterX + currentBubbleRadius * cos(angel * Math.PI / 180).toFloat()
val iBubStartY = bubbleCenterY + currentBubbleRadius * sin(angel * Math.PI / 180).toFloat()
val iBubEndX = bubbleCenterX + currentBubbleRadius * cos((180 - angel) * Math.PI / 180).toFloat()
val iBubEndY = bubbleCenterY + currentBubbleRadius * sin((180 - angel) * Math.PI / 180).toFloat()
val circleAngel = -angel
val iFixCircleStartX = fixCircleCenterX + currentCircleRadius * cos(circleAngel * Math.PI / 180).toFloat()
val iFixCircleStartY = fixCircleCenterY + currentCircleRadius * sin(circleAngel * Math.PI / 180).toFloat()
val iFixCircleEndX = fixCircleCenterX + currentCircleRadius * cos((180 - circleAngel) * Math.PI / 180).toFloat()
val iFixCircleEndY = fixCircleCenterY + currentCircleRadius * sin((180 - circleAngel) * Math.PI / 180).toFloat()
path.reset()
path.moveTo(iBubStartX, iBubStartY)
path.quadraticBezierTo(iAnchorX, iAnchorY, iFixCircleStartX, iFixCircleStartY)
path.lineTo(iFixCircleEndX, iFixCircleEndY)
path.quadraticBezierTo(iAnchorX, iAnchorY, iBubEndX, iBubEndY)
path.close()
drawPath(path = path, color = pointColor)
drawOval(
color = pointColor, topLeft = Offset(bubbleCenterX - linearChangedBubbleRadius, linearChangeBubbleCenterY - linearChangedBubbleRadius),
size = Size(linearChangedBubbleRadius * 2, currentBubbleRadius * 2)
)
用drawOval
画椭圆的api来画圆形,主要是为了实现动画末端圆形在y轴上的形变,剩下的bubble to circle的动画与上面类似。
源代码链接
来源:https://juejin.cn/post/7189829932950749240


猜你喜欢
- 前段时间摸索了java调用matlab东西,不说学的有多深,也算有结果了,达到目的了。也即用java程序可以调用matlab中函数了。&nb
- 1.通过无参构造函数创建(默认)2.通过有参构造创建1.constructor 的index赋值<bean id="user
- 本文实例为大家分享了Android实现界面跳转的具体代码,供大家参考,具体内容如下布局<?xml version="1.0&
- 在实际项目中,在处理较大的文件时,常常将文件拆分为多个子文件进行处理,最后再合并这些子文件。下面就为各位介绍下Java中合并多个文件的方法。
- 本文实例讲述了Java擦除和转换。分享给大家供大家参考,具体如下:一 点睛在严格的泛型代码里,带泛型声明的类总应该带着类型参数。
- Android Studio第一次启动的Fetching android sdk component information的问题1)进入刚
- 引言异步蓝图节点:在蓝图节点的右上角有时钟图标。注意:异步节点可以在EventGraph/Macros中使用,但是无法在蓝图函数中使用。AI
- RTF文档即富文本格式(Rich Text Format)的文档。我们在处理文件时,遇到需要对文档格式进行转换时,可以将RTF转为其他格式,
- 我们经常会希望在程序中写入一些配置信息,例如版本号,以及数据库的连接字符串等。你可能知道在WinForm应用程序中可以利用Propertie
- 1.static静态变量1.静态变量被同一个类的所有对象共享2.static类变量在类加载的时候就生成使用static保存在class实例的
- 本文实例为大家分享了Java实现通讯录管理系统的具体代码,供大家参考,具体内容如下一、前言我们学了这么久的知识了,光学知识不会用是一件很悲伤
- 模式介绍桥接模式(Bridge模式)是指:将实现与抽象放在两个不同的类层次中,使两个层次可以独立改变。是一种结构型设计模式。Bridge模式
- 一、需求有时候应用需要在内部切换语言但又不影响系统的语言,比如是应用现在是中文的,系统语言也是中文的,我把应用的切换成英文显示后系统语言还是
- Settings -> Editor -> General -> Use soft wraps in editor&nbs
- 在开发中我们经常需要把我们的应用设置为全屏,有两种方法,一中是在代码中设置,另一种方法是在配置文件里改!一、在代码中设置:package c
- webflux介绍Spring Boot 2.0spring.io 官网有句醒目的话是:BUILD ANYTHING WITH SPRING
- 1.实例1(主要看到[2])1.1.系统功能: 开发一个计算器服务CalculateService,这个服务包含加(plus)、减(minu
- 最近在研究断点下载(下载续传)的功能,此功能需要服务端和客户端进行对接编写,本篇也是记录一下关于贴上关于实现服务端(Spring Boot)
- 一、前言代码死循环这个话题,个人觉得还是挺有趣的。因为只要是开发人员,必定会踩过这个坑。如果真的没踩过,只能说明你代码写少了,或者是真正的大
- 1、java中启动exe程序 ,并添加传参String[] cmd = {"hh.exe","12315&qu