Compose 动画艺术探索之 Easing

简介: Compose 动画艺术探索之 Easing

本篇文章是此专栏的第六篇文章,前几篇文章大概将 Compose 中的动画都简单过了一遍,如果想阅读前几篇文章的话可以点击下方链接:

Compose 动画艺术探索之瞅下 Compose 的动画

Compose 动画艺术探索之可见性动画

Compose 动画艺术探索之属性动画

Compose 动画艺术探索之动画规格

Compose 动画艺术探索之灵动岛

Compose 动画艺术探索之 AnimationVector

什么是 Easing?

  • 基于时长的 AnimationSpec 操作(如 tween 或 keyframes)使用 Easing 来调整动画的小数值。这样可让动画值加速和减速,而不是以恒定的速率移动。小数是介于 0(起始值)和 1.0(结束值)之间的值,表示动画中的当前点。

Easing 实际上是一个函数,它取一个介于 0 和 1.0 之间的小数值并返回一个浮点数。返回的值可能位于边界之外,表示过冲或下冲。

上面这两段关于什么是 Easing 是官方文档中的描述,是不是看的云里雾里!哈哈哈,第一次看的时候都是,但在介绍 Easing 的最后加了一个注意,一起来看下:

  • 注意:Easing 对象的运行方式与平台中 Interpolator 类的实例相同。不过,它采用的不是 getInterpolation() 方法,而是 transform() 方法。

奥,原来 Easing 就相当于咱们之前使用的插值器(Interpolator)啊!这么说就好理解一些了。

如何使用 Easing?

其实在之前文章 Compose 动画艺术探索之动画规格 中已经简单介绍过 Easing ,在里面大概介绍了常用的几种 Easing :

  • FastOutSlowInEasing
  • LinearOutSlowInEasing
  • FastOutLinearEasing
  • LinearEasing
  • CubicBezierEasing

其中 CubicBezierEasing 是剩下四种的父类,这几种 Easing 的具体用法在 Compose 动画艺术探索之动画规格 中已经介绍过,这里将就不再赘述,如果想看这几种 Easing 的动画效果可以先移步去看下。

下面来看下 Easing 的使用方法:

val value1 by animateFloatAsState(
    targetValue = 1f,
    animationSpec = tween(
        durationMillis = 300,
        delayMillis = 50,
        easing = LinearOutSlowInEasing // 使用 Easing
    )
)

使用方法其实很简单,关键是要选对 Easing 才能实现动画交互想要实现的效果。

还有哪些 Easing?

其实 Compose 中为我们提供的 Easing 远远不止上面说的这几种,还有很多,先来张图感受下有多少吧!


小小提示,并没有截完。。。下面还有,这里就不放那么多截图了。每一种 Easing 都对应着一种动画效果,大家可以去 看每一种 Easing 对应的动画效果样例。下面是官方文档地址:

https://developer.android.google.cn/reference/kotlin/androidx/compose/animation/core/package-summary#Ease()

如何自定义 Easing?

刚才的截图种可以看到,里面的 Easing 和最初说的那几种都继承的是 CubicBezierEasing ,那咱们就来看下 CubicBezierEasing !

@Immutable
class CubicBezierEasing(
    private val a: Float,
    private val b: Float,
    private val c: Float,
    private val d: Float
) : Easing {
    ......
    private fun evaluateCubic(a: Float, b: Float, m: Float): Float {
        return 3 * a * (1 - m) * (1 - m) * m +
            3 * b * (1 - m) *  m * m +
            m * m * m
    }
    override fun transform(fraction: Float): Float {
        if (fraction > 0f && fraction < 1f) {
            var start = 0.0f
            var end = 1.0f
            while (true) {
                val midpoint = (start + end) / 2
                val estimate = evaluateCubic(a, c, midpoint)
                if ((fraction - estimate).absoluteValue < CubicErrorBound)
                    return evaluateCubic(b, d, midpoint)
                if (estimate < fraction)
                    start = midpoint
                else
                    end = midpoint
            }
        } else {
            return fraction
        }
    }
    ......
}

嗯,CubicBezierEasing 实现了 Easing 接口,然后 Easing 中有一个方法 transform ,CubicBezierEasing 类实现了三阶贝塞尔曲线,这相当于原生的 PathInterpolator 。可以看到 CubicBezierEasing 构造方法中接受四个参数,类型都是 Float。

  • a:第一个控制点的x坐标。经过点(0,0)和第一个控制点的直线与点(0,0)处的缓动相切
  • b:第一个控制点的y坐标。经过点(0,0)和第一个控制点的直线与点(0,0)处的缓动相切
  • c:第二个控制点的x坐标。经过点(1,1)和第二个控制点的直线与点(1,1)处的缓动相切
  • d:第二个控制点的y坐标。经过点(1,1)和第二个控制点的直线与点(1,1)处的缓动相切。

CubicBezierEasing 是比较复杂的 Easing ,但也是一个通用的,所以有很多 Easing 都继承自它,咱们自定义的时候也可以继承 CubicBezierEasing ,通过传入不同的控制点坐标来实现想要的动画效果。

当然,也可以直接实现 Easing 接口来实现动画效果,比如 LinearEasing :

val LinearEasing: Easing = Easing { fraction -> fraction }

由于默认就是线性的,所以直接返回未修改的分数就是线性的动画效果。

接下来咱们来自定义一个 Easing !

val CustomLinearEasing: Easing = Easing { fraction -> fraction / 2 }

代码很简单,直接实现 Easing 接口,然后将分数除以二并返回,再来写个 Demo !

var small by remember { mutableStateOf(true) }
val size by animateDpAsState(
    targetValue = if (small) 50.dp else 100.dp,
    animationSpec = tween(
        durationMillis = 3000,
        delayMillis = 50,
        easing = CustomLinearEasing  // 使用上面自定义的 Easing
    )
)
Column {
    Button(onClick = { small = !small }) {
        Text("修改大小")
    }
    Box(
        modifier = Modifier.size(size)
    )
}

代码很简单,在之前的几篇文章中都使用过,这块也就不再赘述,唯一不同的就是这块使用了上面咱们自定义的 Easing ,接下来运行看下效果!

37892762eb5e65cd931cb30c9ee56cf0.gif

动画执行时间一共是三秒钟,但是三秒钟全部执行在了缩小的前半段,后半段在最后一瞬间完成。这是因为咱们将 Easing 的分数返回值修改为了之前的一半而导致的。

刚才的分数只是除以了二,这回咱们直接改为负数看看!

val CustomLinearEasing: Easing = Easing { fraction -> -fraction / 2 }

别的都没动,只是加了个负号,来运行看下效果!

2704421d6f8ef829e53956c211f15611.gif

可以看到动画效果正好和刚才是相反的方向!

接下来再玩一下,刚才是除以二,这回咱们来乘二看下效果!

val CustomLinearEasing: Easing = Easing { fraction -> fraction * 2 }

运行看下效果!

72ca7949b9b80948a2ff8f5c2f636b57.gif

可以看到,动画效果执行到目标值还在方法或缩小,最后返回到既定值。

总结

如果想玩好 Compose 中的动画,Easing 是必不可少的一环,其实官方给实现的 Easing 基本都能满足咱们的日程开发需求,如果实现需要自定义那就只能自定义搞一搞了,不过在自定义前可以思考下是直接实现 Easing 接口还是继承 CubicBezierEasing 。


目录
相关文章
|
Prometheus 监控 Cloud Native
如何推广你的开源项目?
如何推广你的开源项目?
458 0
|
Linux
Linux清理磁盘空间常用命令
Linux清理磁盘空间常用命令
1356 0
Linux清理磁盘空间常用命令
|
存储 数据库 Android开发
安卓Jetpack Compose+Kotlin,支持从本地添加音频文件到播放列表,支持删除,使用ExoPlayer播放音乐
为了在UI界面添加用于添加和删除本地音乐文件的按钮,以及相关的播放功能,你需要实现以下几个步骤: 1. **集成用户选择本地音乐**:允许用户从设备中选择音乐文件。 2. **创建UI按钮**:在界面中创建添加和删除按钮。 3. **数据库功能**:使用Room数据库来存储音频文件信息。 4. **更新ViewModel**:处理添加、删除和播放音频文件的逻辑。 5. **UI实现**:在UI层支持添加、删除音乐以及播放功能。
|
存储 Android开发
安卓app,MediaPlayer播放本地音频 | 按钮控制播放和停止
在Jetpack Compose中,不直接操作原生Android组件如`Button`和`MediaPlayer`,而是使用Compose UI构建器定义界面并结合ViewModel管理音频播放逻辑。以下示例展示如何播放本地音频并用按钮控制播放/停止:创建一个`AudioPlayerViewModel`管理`MediaPlayer`实例和播放状态,然后在Compose UI中使用`Button`根据`isPlaying`状态控制播放。记得在`MainActivity`设置Compose UI,并处理相关依赖和权限。
|
自然语言处理 资源调度 前端开发
前端大模型入门(四):不同文本分割器对比和效果展示-教你如何根据场景选择合适的长文本分割方式
本文详细介绍了五种Langchain文本分割器:`CharacterTextSplitter`、`RecursiveCharacterTextSplitter`、`TokenTextSplitter`、`MarkdownTextSplitter` 和 `LatexTextSplitter`,从原理、优缺点及适用场景等方面进行了对比分析,旨在帮助开发者选择最适合当前需求的文本分割工具,提高大模型应用的处理效率和效果。
2746 1
|
域名解析 缓存 网络协议
计算机网络——ping命令过程的详解、原理
计算机网络——ping命令过程的详解、原理
|
测试技术 Python
解释Python中的装饰器链(Decorator Chaining)。
解释Python中的装饰器链(Decorator Chaining)。
137 6
|
存储 缓存 网络协议
CDNJS/UNPKG/JSDelivr 太慢用不了,换成这些国内高速镜像
npm cdn, cdnjs, unpkg, jsdelivr, zstatic, zstatic.net, s4.zstatic.net
19860 4
|
存储 IDE Java
java基础教程(2)-Java基本数据类型
【4月更文挑战第2天】这段内容介绍了Java程序的基础和基本数据类型。一个简单的Java程序由`public class`定义,包含`main`方法,用于控制台输出。程序中类名、文件名需一致,注释有三种形式。Java有8种基本数据类型:4种整型(byte, short, int, long),2种浮点型(float, double),1种字符型(char)和1种布尔型(boolean)。整型的范围由字节数决定,浮点型如float和double的范围与其位数布局相关。char类型用于Unicode字符,boolean表示真或假。
206 0
|
前端开发 Java Windows
JDK1.8下载、安装和环境配置教程(详细)
JDK1.8下载、安装和环境配置教程(详细)
34897 1
JDK1.8下载、安装和环境配置教程(详细)