Jetpack Compose自定义动画与Animatable详解

目录
  • AnimationSpec
    • 1.spring
    • 2.tween
    • 3.keyframes
    • 4.repeatable
    • 5.snap
  • Animatable

本篇主要是自定义动画与Animatable

AnimationSpec

上一篇中,出现了多次animationSpec属性,它是用来自定义动画规范的。例如:

fun Modifier.animateContentSize(
    animationSpec: FiniteAnimationSpec<IntSize> = spring(),
    finishedListener: ((initialValue: IntSize, targetValue: IntSize) -> Unit)? = null
): Modifier

下面是几种自带的动画规范:

1.spring

我们上一篇也简单说到了,它是一种弹性动画。源码如下:

@Stable
fun <T> spring(
    dampingRatio: Float = Spring.DampingRatioNoBouncy,
    stiffness: Float = Spring.StiffnessMedium,
    visibilityThreshold: T? = null
): SpringSpec<T> = SpringSpec(dampingRatio, stiffness, visibilityThreshold)

dampingRatio: 定义弹簧的弹性,数值越小弹性越高。默认值DampingRatioNoBouncy为1f。下图为其他数值的效果:

  • stiffness: 定义弹簧向结束值移动的速度。默认值StiffnessMedium为1500f。
  • visibilityThreshold:可见临界值(动画停止的值)。比如目标150dp,此值设置10dp,那么回弹距离小于这个值时就会停止弹性效果。

2.tween

在指定的时间内使用缓和曲线在起始值和结束值之间添加动画效果。

@Stable
fun <T> tween(
    durationMillis: Int = DefaultDurationMillis,
    delayMillis: Int = 0,
    easing: Easing = FastOutSlowInEasing
): TweenSpec<T> = TweenSpec(durationMillis, delayMillis, easing)
val FastOutSlowInEasing: Easing = CubicBezierEasing(0.4f, 0.0f, 0.2f, 1.0f)
  • durationMillis:动画的持续时间,默认值300毫秒。
  • delayMillis:延迟动画开始的时间。
  • easing:两个值之间的插值曲线,类似Android中的Interpolator插值器。目前compose中提供了五种类型,这里就不一一说明了,实际使用时可以尝试一下。当然你也可以使用CubicBezierEasing甚至Easing自定义曲线。

3.keyframes

在动画时长内的不同时间戳中指定快照值,实现动画效果。在任何给定时间,动画值都将插值到两个关键帧值之间。对于其中每个关键帧,您都可以指定 Easing 来确定插值曲线。

@Stable
fun <T> keyframes(
    init: KeyframesSpec.KeyframesSpecConfig<T>.() -> Unit
): KeyframesSpec<T> {
    return KeyframesSpec(KeyframesSpec.KeyframesSpecConfig<T>().apply(init))
}

例子:

val value by animateFloatAsState(
    targetValue = 1f,
    animationSpec = keyframes {
        durationMillis = 375
        0.0f at 0 with LinearOutSlowInEasing // for 0-15 ms
        0.2f at 15 with FastOutLinearInEasing // for 15-75 ms
        0.4f at 75 // ms
        0.4f at 225 // ms
    }
)

解释一下上面的例子:整体起始值0和结束值1,动画时长375毫秒。

  • 从0开始到0.2结束,前15毫秒使用LinearOutSlowInEasing过渡。
  • 从0.2开始到0.4结束,15到75毫秒使用FastOutLinearInEasing过渡。
  • 从0.4开始到0.4结束,75到225毫秒匀速过渡。(静止效果)
  • 从0.4开始到1结束,225毫秒到结束匀速过渡。

效果图如下:

keyframes同样也可以设置delayMillis指定延时时间。

4.repeatable

重复运行基于时长的动画,直至达到指定的迭代计数。

@Stable
fun <T> repeatable(
    iterations: Int,
    animation: DurationBasedAnimationSpec<T>,
    repeatMode: RepeatMode = RepeatMode.Restart,
    initialStartOffset: StartOffset = StartOffset(0)
): RepeatableSpec<T> = RepeatableSpec(iterations, animation, repeatMode, initialStartOffset)
  • iterations,动画运行的次数。1表示不重复。建议使用infiniteRepeatable创建无限重复的动画。
  • animation,设置需要重复的动画。
  • repeatMode,重复模式。指定动画是从头开始 (RepeatMode.Restart) 还是从结尾开始 (RepeatMode.Reverse) 重复播放。
  • initialStartOffset,可用于延迟动画的开始或快进动画到给定的播放时间。如果设置StartOffset(1500)就是延迟动画。 设置StartOffset(1500, offsetType = StartOffsetType.FastForward)就是快进动画。默认情况下,延时时长为0。

如果需要动画重复无限次,可以使用infiniteRepeatable,用法与repeatable一致。

5.snap

snap是特殊的 AnimationSpec,它会立即将值切换到结束值。您可以指定 delayMillis 来延迟动画播放的开始时间。

@Stable
fun <T> snap(delayMillis: Int = 0) = SnapSpec<T>(delayMillis)

Animatable

Animatable 是一个值容器,它可以在通过 animateTo 更改值时为值添加动画效果。它可确保一致的连续性和互斥性,这意味着值变化始终是连续的,并且会取消任何正在播放的动画。

Animatable 的许多功能(包括 animateTo)以挂起函数的形式提供。这意味着,它们需要封装在适当的协程作用域内。例如,您可以使用 LaunchedEffect 可组合项针对指定键值的时长创建一个作用域。

// Start out gray and animate to green/red based on `ok`
val color = remember { Animatable(Color.Gray) }
LaunchedEffect(ok) {
    color.animateTo(if (ok) Color.Green else Color.Red)
}
Box(Modifier.fillMaxSize().background(color.value))

在上面的示例中,我们创建并记住了初始值为 Color.GrayAnimatable 实例。根据布尔标记 ok 的值,颜色将以动画形式呈现 Color.GreenColor.Red。对该布尔值的任何后续更改都会使动画开始使用另一种颜色。如果更改该值时有正在播放的动画,系统会取消该动画,并且新动画将以当前速度从当前快照值开始播放。

animate*AsState 相比,使用 Animatable 可以直接对以下几个方面进行更精细的控制。首先,Animatable 的初始值可以与第一个目标值不同。例如,上面的代码示例首先显示一个灰色框,然后立即开始通过动画呈现为绿色或红色。其次,Animatable 对内容值提供更多操作(即 snapToanimateDecay)。snapTo 可立即将当前值设为目标值。如果动画本身不是唯一的可信来源,且必须与其他状态(如触摸事件)同步,该函数就非常有用。animateDecay 用于启动播放从给定速度变慢的动画(衰减)。这有助于实现投掷行为。

下面看一个官方demo:

	Column(modifier = Modifier.fillMaxWidth()) {
        // Creates an `Animatable` to animate Offset and `remember` it.
        val animatedOffset = remember { Animatable(Offset(0f, 0f), Offset.VectorConverter) }
        Box(
            Modifier.fillMaxSize().background(Color(0xffb99aff)).pointerInput(Unit) {
                coroutineScope {
                    while (true) {
                        val offset = awaitPointerEventScope {
                            awaitFirstDown().position
                        }
                        // Launch a new coroutine for animation so the touch detection thread is not
                        // blocked.
                        launch {
                            // Animates to the pressed position, with the given animation spec.
                            animatedOffset.animateTo(
                                offset,
                                animationSpec = spring(stiffness = Spring.StiffnessLow)
                            )
                        }
                    }
                }
            }
        ) {
            Text("Tap anywhere", Modifier.align(Alignment.Center))
            Box(
                Modifier
                    .offset {
                        // Use the animated offset as the offset of the Box.
                        IntOffset(
                            animatedOffset.value.x.roundToInt(),
                            animatedOffset.value.y.roundToInt()
                        )
                    }
                    .size(40.dp)
                    .background(Color(0xff3c1361), CircleShape)
            )
        }
    }

效果图这里我就不放了。就是页面上有个40*40dp的圆形view,点击屏幕任意位置,他就会移动过去。这里核心靠的就是animateTo方法,而且无论我们中间如果快速点击不同位置,系统会取消上一个动画,接着当前位置移动到目标位置。

从上面这张图可以看出各个API之间的关系。所有这些 API 都基于更基础的 Animation API。虽然大多数应用不会直接使用 Animation ,但 Animation 的某些自定义功能可以通过更高级别的 API 获得。

到此,Compose的动画部分大体结束。

参考

Compose官方文档

Compose官方文档 – Animatable

到此这篇关于Jetpack Compose自定义动画与Animatable详解的文章就介绍到这了,更多相关Jetpack Compose自定义动画内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Jetpack Compose 双指拖拽实现详解

    目录 Modifier.offset graphicsLayer Modifier.pointerInput PointerInputScope.detectTransformGestures 逻辑解释 定义4个变量 传入graphicsLayer里面 监听手势 完整代码 效果图 Modifier.offset Compose遇到一个浏览图片的功能,双指放大和缩小 Modifier的offset可以偏移内容.偏移量可以是正的,也可以是非正的.应用偏移只会更改内容的位置,而不会影响其大小测量. o

  • Jetpack Compose DropdownMenu手指跟随点击显示

    目录 引言 效果图 实现方法 1使用DropdownMenu的offset参数 2Modifier.offset 获取到点击的位置 Box创建用于监听点击事件修饰符 DropdownMenu外层的Box()设置偏移量 完整代码 使用方法 引言 DropdownMenu显示时默认会避开点击的view 通常默认显示在左下方 本篇文章教你实现跟随手指按下位置显示 效果图 实现方法 首先要获取到点击的位置之后计算偏移量 先分析两种offset参数 1使用DropdownMenu的offset参数 获取到

  • Jetpack Compose惯性衰减动画AnimateDecay详解

    目录 什么是惯性衰减动画 惯性衰减动画 使用要点 block 监听 什么是惯性衰减动画 比如说我们玩微信的时候 手指一拉,微信的列表就会惯性滑动 ,这个滑动的速率当然是越来越慢的,最终停止, 这个其实就是惯性衰减动画的典型例子 那这个例子和animateTo 有啥区别呢? 一个速率变慢的动画 ,听起来似乎 我们用animateTo 设置一些参数也可以实现 其实这里最大的区别就是 animateTo 你是需要设置目标值的,也就是动画结束的那一刻 某个view属性的值 你必须明确指定 而所谓的惯性衰

  • Jetpack Compose重写TopAppBar实现标题多行折叠详解

    目录 前言 MediumTopAppBar 阅读源码 核心 解决方法 重写TopAppBarLayout 完整代码 前言 想用composes实现类似掘金的文章详细页面的标题栏 上滑隐藏标题后标题栏显示标题 compose.material3下的TopAppBar不能嵌套滚动 MediumTopAppBar 便使用了MediumTopAppBar一开始用着没什么问题,但是标题字数多了,MediumTopAppBar就不支持了,最多就两行,进入源码一看就明白了 @ExperimentalMater

  • Jetpack Compose 分步指南教程详解

    目录 前言 可组合函数 显示简单文本 将样式应用于文本 使用 TextField 进行输入 在 Android Studio 中预览 预览参数 Column Scrollable Column Lazy Column Box Button Card Clickable Image Alert Dialog Material AppBar Material BottomNavigation Material Checkbox Material ProgressBar Material Slider

  • Android Jetpack Compose开发实用小技巧

    目录 前言 实用小技巧 如何移除View点击阴影 Text文本如何垂直居中 如何移除Button的点击阴影 Dialog宽度如何全屏 如何提升编码效率 前言 在Compose开发的过程中,我们会经常遇到一些看起来很简单却不知道如何处理的小问题,比如去除点击阴影.Dialog全屏等问题,本文记录了这些常见小问题的处理方式.如有更好方案欢迎大佬们交流探讨- 实用小技巧 如何移除View点击阴影 这里的View指的是除了Button系列的之外,如Button.TextButton等,也就是自身没有on

  • Jetpack Compose自定义动画与Animatable详解

    目录 AnimationSpec 1.spring 2.tween 3.keyframes 4.repeatable 5.snap Animatable 本篇主要是自定义动画与Animatable. AnimationSpec 上一篇中,出现了多次animationSpec属性,它是用来自定义动画规范的.例如: fun Modifier.animateContentSize( animationSpec: FiniteAnimationSpec<IntSize> = spring(), fin

  • jQuery自定义动画函数实例详解(附demo源码)

    本文实例讲述了jQuery自定义动画函数完整实现技巧.分享给大家供大家参考,具体如下: 运行效果截图如下: 在线演示地址如下: http://demo.jb51.net/js/2015/jquery-zdy-dh-move-style-demo/ 具体代码如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.d

  • Jetpack Compose实现动画效果的方法详解

    目录 概述 低级别动画API animate*AsState 使用Animatable实现颜色变化效果 使用updateTransition实现颜色和圆角动画 rememberInfiniteTransition TargetBasedAnimation 自定义动画 AnimationSpec Easing AnimationVector 高级动画 概述 compose 为支持动画提供了大量的 api,通过这些 api 我们可以轻松实现动画效果 ps:这些 api 的原理与 Flutter 很接

  • Android Compose状态改变动画animateXxxAsState使用详解

    目录 前言 animateXxxAsState 基础使用 动画监听 使用示例 animateFloatAsState animateIntAsState animateColorAsState animateSizeAsState/animateIntSizeAsState animateOffsetAsState/animateIntOffsetAsState animateRectAsState 实战 最后 前言 上一篇文章我们探索了 Compose 中属性动画的使用,发现属性动画确实是可以

  • pyqt5中动画的使用详解

    一.pyqt5中动画的继承关系图 二.关于QAbstractAnimation父类的认识 1.主要作用 继承此类, 实现一些自定义动画 所有动画共享的功能 2.功能作用 循环操作 setLoopCount(count):设置循环次数 currentLoop():当前循环 currentLoopTime():当前循环时间 时间操作 duration():单次时长 totalDuration():动画总时长 currentTime():当前时长 动画方向 setDirection(QAbstract

  • Android JetPack组件的支持库Databinding详解

    目录 简介 启用databinding 布局xml variable (变量标签) data (数据标签) @{}表达式 绑定普通数据 绑定可观察数据 对单个变量的绑定-fields 对集合的绑定-collections 绑定对象-objects 绑定LiveData 双向绑定 简介 DataBinding 是 Google 在 Jetpack 中推出的一款数据绑定的支持库,利用该库可以实现在页面组件中直接绑定应用程序的数据源.使其维护起来更加方便,架构更明确简介. DataBinding 唯一

  • Android TabLayout 自定义样式及使用详解

    目录 基本使用 XML静态设置TabItem 联动ViewPager2动态设置TabItem 1. Activity布局代码 2. 创建三个Fragment给ViewPager2设置 3. Fragment对应XML布局 4. 绑定起来 最终效果 根据数据源动态生成TabItem 1.Activity布局代码 2. Activity代码 最终效果 修改TabLayout背景颜色 修改indicator layer-list 制作圆形的indicator 制作圆角矩形indicator 修改边距

  • Android自定义LocationMarker的实现详解

    目录 自定义View LocationMarker 应用自定义View到AMapView中 今天讲一个比较简单的东西自定义绘制Marker 其实就是自定义view, 跟轨迹没太多关联,还有轨迹源码在文末分享出来,对您有帮助的话给个star呗. 如下面的gif中的轨迹中的LocationMarker 自定义View LocationMarker 主要包括绘制水滴状,绘制圆.绘制文字,绘制底部椭圆阴影,主要是绘制水滴状,这里用的贝塞尔三阶绘制,首先直接看代码: public class Locati

  • WPF实现在控件上显示Loading等待动画的方法详解

    WPF 如何在控件上显示 Loading 等待动画 框架使用.NET40: Visual Studio 2022; 使用方式需引入命名空间后设置控件的附加属性 wd:Loading.IsShow="true",即可显示默认等待动画效果如下: 如需自定义 Loading 一定要 先设置 wd:Loading.Child 在设置 IsShow="true" . 显示不同 Loading 内容需 wd:Loading.Child ={x:Static wd:NormalL

随机推荐