Android 属性动画(四)使用动画插值器

一、插值器简介

    属性动画的插值器,它是用来计算动画的。插值器会接收来自 Animator 一个表示动画 已播放时间分数,然后根据这个已播放时间分数计算出 插值分数,评估程序根据插值分数再计算出当前属性的值。 已播放时间分数插值分数 之间有什么差别呢?在动画播放过程中,对于时间而言,是以恒定速度变化,动画已播放的时间和总时间的比,就是 已播放时间分数。但是在固定的时间段内,动画的播放的比例可能是不同的,已播放完成的动画跟总动画的比,就叫做 插值分数。如果为 ValueAnimator 添加 ValueAnimator.AnimatorUpdateListener,可以在更新回调中打印相关信息进行分析,以下就是一份 AccelerateDecelerateInterpolator 插值器的数据分析:

  • AccelerateDecelerateInterpolator 插值器数据变化分析
2020-11-05 15:17:24.924 15898-15898/com.owen.demo.android I/AnimatorUpdate: currentPlayTime = 0 --> animatedFraction = 0.0, animatedValue = PointF(1.0, 1.0)
2020-11-05 15:17:24.929 15898-15898/com.owen.demo.android I/AnimatorUpdate: currentPlayTime = 9 --> animatedFraction = 0.0, animatedValue = PointF(1.0, 1.0)
2020-11-05 15:17:24.944 15898-15898/com.owen.demo.android I/AnimatorUpdate: currentPlayTime = 17 --> animatedFraction = 7.1290135E-4, animatedValue = PointF(1.0003564, 1.0007129)
2020-11-05 15:17:24.966 15898-15898/com.owen.demo.android I/AnimatorUpdate: currentPlayTime = 34 --> animatedFraction = 0.0028496087, animatedValue = PointF(1.0014248, 1.0028496)
2020-11-05 15:17:24.979 15898-15898/com.owen.demo.android I/AnimatorUpdate: currentPlayTime = 50 --> animatedFraction = 0.0061558187, animatedValue = PointF(1.0030779, 1.0061558)
2020-11-05 15:17:24.997 15898-15898/com.owen.demo.android I/AnimatorUpdate: currentPlayTime = 66 --> animatedFraction = 0.010709554, animatedValue = PointF(1.0053548, 1.0107095)
2020-11-05 15:17:25.014 15898-15898/com.owen.demo.android I/AnimatorUpdate: currentPlayTime = 83 --> animatedFraction = 0.01690182, animatedValue = PointF(1.0084509, 1.0169019)
2020-11-05 15:17:25.031 15898-15898/com.owen.demo.android I/AnimatorUpdate: currentPlayTime = 100 --> animatedFraction = 0.02447176, animatedValue = PointF(1.0122359, 1.0244718)
2020-11-05 15:17:25.051 15898-15898/com.owen.demo.android I/AnimatorUpdate: currentPlayTime = 116 --> animatedFraction = 0.032835484, animatedValue = PointF(1.0164177, 1.0328355)
2020-11-05 15:17:25.070 15898-15898/com.owen.demo.android I/AnimatorUpdate: currentPlayTime = 149 --> animatedFraction = 0.05378583, animatedValue = PointF(1.0268929, 1.0537858)
2020-11-05 15:17:25.087 15898-15898/com.owen.demo.android I/AnimatorUpdate: currentPlayTime = 166 --> animatedFraction = 0.06646466, animatedValue = PointF(1.0332323, 1.0664647)
2020-11-05 15:17:25.104 15898-15898/com.owen.demo.android I/AnimatorUpdate: currentPlayTime = 183 --> animatedFraction = 0.080379754, animatedValue = PointF(1.0401899, 1.0803797)
2020-11-05 15:17:25.119 15898-15898/com.owen.demo.android I/AnimatorUpdate: currentPlayTime = 199 --> animatedFraction = 0.09457022, animatedValue = PointF(1.0472851, 1.0945702)
2020-11-05 15:17:25.136 15898-15898/com.owen.demo.android I/AnimatorUpdate: currentPlayTime = 216 --> animatedFraction = 0.110768825, animatedValue = PointF(1.0553844, 1.1107688)
2020-11-05 15:17:25.153 15898-15898/com.owen.demo.android I/AnimatorUpdate: currentPlayTime = 233 --> animatedFraction = 0.12807748, animatedValue = PointF(1.0640388, 1.1280775)
2020-11-05 15:17:25.169 15898-15898/com.owen.demo.android I/AnimatorUpdate: currentPlayTime = 249 --> animatedFraction = 0.14533758, animatedValue = PointF(1.0726688, 1.1453376)
2020-11-05 15:17:25.187 15898-15898/com.owen.demo.android I/AnimatorUpdate: currentPlayTime = 266 --> animatedFraction = 0.16465724, animatedValue = PointF(1.0823286, 1.1646572)
2020-11-05 15:17:25.203 15898-15898/com.owen.demo.android I/AnimatorUpdate: currentPlayTime = 283 --> animatedFraction = 0.18493307, animatedValue = PointF(1.0924666, 1.1849331)
2020-11-05 15:17:25.220 15898-15898/com.owen.demo.android I/AnimatorUpdate: currentPlayTime = 299 --> animatedFraction = 0.20483807, animatedValue = PointF(1.102419, 1.204838)
2020-11-05 15:17:25.235 15898-15898/com.owen.demo.android I/AnimatorUpdate: currentPlayTime = 316 --> animatedFraction = 0.2268028, animatedValue = PointF(1.1134014, 1.2268028)
2020-11-05 15:17:25.252 15898-15898/com.owen.demo.android I/AnimatorUpdate: currentPlayTime = 333 --> animatedFraction = 0.24954662, animatedValue = PointF(1.1247733, 1.2495466)
2020-11-05 15:17:25.269 15898-15898/com.owen.demo.android I/AnimatorUpdate: currentPlayTime = 349 --> animatedFraction = 0.27160627, animatedValue = PointF(1.1358031, 1.2716062)
2020-11-05 15:17:25.286 15898-15898/com.owen.demo.android I/AnimatorUpdate: currentPlayTime = 366 --> animatedFraction = 0.29567537, animatedValue = PointF(1.1478376, 1.2956754)
2020-11-05 15:17:25.302 15898-15898/com.owen.demo.android I/AnimatorUpdate: currentPlayTime = 383 --> animatedFraction = 0.32032734, animatedValue = PointF(1.1601636, 1.3203273)
2020-11-05 15:17:25.320 15898-15898/com.owen.demo.android I/AnimatorUpdate: currentPlayTime = 399 --> animatedFraction = 0.34399825, animatedValue = PointF(1.1719991, 1.3439982)
2020-11-05 15:17:25.337 15898-15898/com.owen.demo.android I/AnimatorUpdate: currentPlayTime = 416 --> animatedFraction = 0.36957926, animatedValue = PointF(1.1847897, 1.3695793)
2020-11-05 15:17:25.353 15898-15898/com.owen.demo.android I/AnimatorUpdate: currentPlayTime = 433 --> animatedFraction = 0.395532, animatedValue = PointF(1.1977661, 1.395532)
2020-11-05 15:17:25.370 15898-15898/com.owen.demo.android I/AnimatorUpdate: currentPlayTime = 450 --> animatedFraction = 0.42178285, animatedValue = PointF(1.2108915, 1.4217829)
2020-11-05 15:17:25.388 15898-15898/com.owen.demo.android I/AnimatorUpdate: currentPlayTime = 466 --> animatedFraction = 0.44669437, animatedValue = PointF(1.2233472, 1.4466944)
2020-11-05 15:17:25.404 15898-15898/com.owen.demo.android I/AnimatorUpdate: currentPlayTime = 483 --> animatedFraction = 0.47330922, animatedValue = PointF(1.2366546, 1.4733093)
2020-11-05 15:17:25.420 15898-15898/com.owen.demo.android I/AnimatorUpdate: currentPlayTime = 500 --> animatedFraction = 0.5, animatedValue = PointF(1.25, 1.5)
2020-11-05 15:17:25.437 15898-15898/com.owen.demo.android I/AnimatorUpdate: currentPlayTime = 516 --> animatedFraction = 0.5251222, animatedValue = PointF(1.2625611, 1.5251222)
2020-11-05 15:17:25.454 15898-15898/com.owen.demo.android I/AnimatorUpdate: currentPlayTime = 533 --> animatedFraction = 0.55174345, animatedValue = PointF(1.2758718, 1.5517435)
2020-11-05 15:17:25.470 15898-15898/com.owen.demo.android I/AnimatorUpdate: currentPlayTime = 550 --> animatedFraction = 0.57821715, animatedValue = PointF(1.2891085, 1.5782171)
2020-11-05 15:17:25.487 15898-15898/com.owen.demo.android I/AnimatorUpdate: currentPlayTime = 567 --> animatedFraction = 0.6044678, animatedValue = PointF(1.3022339, 1.6044679)
2020-11-05 15:17:25.503 15898-15898/com.owen.demo.android I/AnimatorUpdate: currentPlayTime = 583 --> animatedFraction = 0.6289036, animatedValue = PointF(1.3144518, 1.6289036)
2020-11-05 15:17:25.519 15898-15898/com.owen.demo.android I/AnimatorUpdate: currentPlayTime = 600 --> animatedFraction = 0.65450853, animatedValue = PointF(1.3272543, 1.6545086)
2020-11-05 15:17:25.536 15898-15898/com.owen.demo.android I/AnimatorUpdate: currentPlayTime = 617 --> animatedFraction = 0.67967266, animatedValue = PointF(1.3398364, 1.6796727)
2020-11-05 15:17:25.553 15898-15898/com.owen.demo.android I/AnimatorUpdate: currentPlayTime = 633 --> animatedFraction = 0.7028899, animatedValue = PointF(1.351445, 1.7028899)
2020-11-05 15:17:25.570 15898-15898/com.owen.demo.android I/AnimatorUpdate: currentPlayTime = 650 --> animatedFraction = 0.7269952, animatedValue = PointF(1.3634976, 1.7269952)
2020-11-05 15:17:25.586 15898-15898/com.owen.demo.android I/AnimatorUpdate: currentPlayTime = 667 --> animatedFraction = 0.75045335, animatedValue = PointF(1.3752267, 1.7504534)
2020-11-05 15:17:25.604 15898-15898/com.owen.demo.android I/AnimatorUpdate: currentPlayTime = 683 --> animatedFraction = 0.7718804, animatedValue = PointF(1.3859402, 1.7718804)
2020-11-05 15:17:25.620 15898-15898/com.owen.demo.android I/AnimatorUpdate: currentPlayTime = 700 --> animatedFraction = 0.7938927, animatedValue = PointF(1.3969463, 1.7938926)
2020-11-05 15:17:25.637 15898-15898/com.owen.demo.android I/AnimatorUpdate: currentPlayTime = 717 --> animatedFraction = 0.81506693, animatedValue = PointF(1.4075334, 1.8150669)
2020-11-05 15:17:25.653 15898-15898/com.owen.demo.android I/AnimatorUpdate: currentPlayTime = 733 --> animatedFraction = 0.83417606, animatedValue = PointF(1.417088, 1.8341761)
2020-11-05 15:17:25.670 15898-15898/com.owen.demo.android I/AnimatorUpdate: currentPlayTime = 750 --> animatedFraction = 0.8535534, animatedValue = PointF(1.4267766, 1.8535534)
2020-11-05 15:17:25.687 15898-15898/com.owen.demo.android I/AnimatorUpdate: currentPlayTime = 767 --> animatedFraction = 0.8719225, animatedValue = PointF(1.4359612, 1.8719225)
2020-11-05 15:17:25.703 15898-15898/com.owen.demo.android I/AnimatorUpdate: currentPlayTime = 783 --> animatedFraction = 0.88824326, animatedValue = PointF(1.4441216, 1.8882432)
2020-11-05 15:17:25.720 15898-15898/com.owen.demo.android I/AnimatorUpdate: currentPlayTime = 800 --> animatedFraction = 0.9045085, animatedValue = PointF(1.4522543, 1.9045085)
2020-11-05 15:17:25.737 15898-15898/com.owen.demo.android I/AnimatorUpdate: currentPlayTime = 817 --> animatedFraction = 0.91962016, animatedValue = PointF(1.45981, 1.9196202)
2020-11-05 15:17:25.753 15898-15898/com.owen.demo.android I/AnimatorUpdate: currentPlayTime = 834 --> animatedFraction = 0.93353534, animatedValue = PointF(1.4667677, 1.9335353)
2020-11-05 15:17:25.770 15898-15898/com.owen.demo.android I/AnimatorUpdate: currentPlayTime = 850 --> animatedFraction = 0.94550323, animatedValue = PointF(1.4727516, 1.9455032)
2020-11-05 15:17:25.787 15898-15898/com.owen.demo.android I/AnimatorUpdate: currentPlayTime = 867 --> animatedFraction = 0.9569855, animatedValue = PointF(1.4784927, 1.9569855)
2020-11-05 15:17:25.804 15898-15898/com.owen.demo.android I/AnimatorUpdate: currentPlayTime = 884 --> animatedFraction = 0.9671645, animatedValue = PointF(1.4835823, 1.9671645)
2020-11-05 15:17:25.821 15898-15898/com.owen.demo.android I/AnimatorUpdate: currentPlayTime = 900 --> animatedFraction = 0.97552824, animatedValue = PointF(1.4877641, 1.9755282)
2020-11-05 15:17:25.837 15898-15898/com.owen.demo.android I/AnimatorUpdate: currentPlayTime = 917 --> animatedFraction = 0.98309815, animatedValue = PointF(1.491549, 1.9830981)
2020-11-05 15:17:25.853 15898-15898/com.owen.demo.android I/AnimatorUpdate: currentPlayTime = 933 --> animatedFraction = 0.9889647, animatedValue = PointF(1.4944823, 1.9889647)
2020-11-05 15:17:25.871 15898-15898/com.owen.demo.android I/AnimatorUpdate: currentPlayTime = 950 --> animatedFraction = 0.99384415, animatedValue = PointF(1.496922, 1.9938442)
2020-11-05 15:17:25.886 15898-15898/com.owen.demo.android I/AnimatorUpdate: currentPlayTime = 966 --> animatedFraction = 0.9971504, animatedValue = PointF(1.4985752, 1.9971504)
2020-11-05 15:17:25.902 15898-15898/com.owen.demo.android I/AnimatorUpdate: currentPlayTime = 983 --> animatedFraction = 0.9992871, animatedValue = PointF(1.4996436, 1.9992871)
2020-11-05 15:17:25.919 15898-15898/com.owen.demo.android I/AnimatorUpdate: currentPlayTime = 1000 --> animatedFraction = 1.0, animatedValue = PointF(1.5, 2.0)

上面的 currentPlayTime 是当前动画时间, animatedFraction 是当前动画插值, animatedValue 是当前属性值。大家可以使用不同的插值器分析一下,有助于对插值器的理解。

二、自定义插值器

    系统定义了一些插值器,开发者可以直接使用,系统常用的插值器在 android.view.animation 包下定义,有以下几个:

  • AccelerateDecelerateInterpolator:该插值器的变化率在开始和结束时缓慢但在中间会加快。
  • AccelerateInterpolator:该插值器的变化率在开始时较为缓慢,然后会加快。
  • AnticipateInterpolator:该插值器先反向变化,然后再急速正向变化。
  • AnticipateOvershootInterpolator:该插值器先反向变化,再急速正向变化,然后超过定位值,最后返回到最终值。
  • BounceInterpolator:该插值器的变化会跳过结尾处。
  • CycleInterpolator:该插值器的动画会在指定数量的周期内重复。
  • DecelerateInterpolator:该插值器的变化率开始很快,然后减速。
  • LinearInterpolator:该插值器的变化率是恒定不变。
  • OvershootInterpolator:该插值器会急速正向变化,再超出最终值,然后返回。

说明:这里列举的不一定完整,随着版本升级可能会新增一些插值器,请以官方文档为准:android.view.animation

    如果系统定义的插值器无法满足需求,开发者可以定义自己的插值器,自定义插值器需要实现 TimeInterpolator 接口,该接口只有一个方法需要实现,那就是 float getInterpolation(float input),该方法的输入参数是已播放时间分数,返回值是插值分数。但是必须注意的是,插值分数初始值必须是0,最终值必须是1。首先,让我们来看看最简单的插值器 LinearInterpolator 的实现:

  • LinearInterpolator 实现代码
public class LinearInterpolator extends BaseInterpolator implements NativeInterpolatorFactory {

    public LinearInterpolator() {
    }

    public LinearInterpolator(Context context, AttributeSet attrs) {
    }

    public float getInterpolation(float input) {
        return input;
    }

    /** @hide */
    @Override
    public long createNativeInterpolator() {
        return NativeInterpolatorFactoryHelper.createLinearInterpolator();
    }
}

LinearInterpolator 的实现非常简单,直接将完成时间分数返回,这也正说明了线性插值器,动画完成比例是跟已播时间比例是一样的。

    接下来,我们自己定义一个插值器,一个正弦模式的减速插值器 SinInterpolator.

  • SinInterpolator
class SinInterpolator : TimeInterpolator {
    override fun getInterpolation(input: Float): Float {
        // 这里需要注意的是,三角函数sin()的参数的角度单位是弧度
        return sin((Math.PI / 2.0f) * input).toFloat()
    }
}
  • 为动画设置定义的插值器
val anim = ValueAnimator.ofObject(XYEvaluate(), PointF(1.0f, 1.0f), PointF(1.5f, 2.0f)).apply {
    duration = 1000
    interpolator = SinInterpolator()
    addUpdateListener {
        val value = it.animatedValue as PointF
        imageView.scaleX = value.x
        imageView.scaleY = value.y
    }
    start()
}
  • 实现效果
    正弦减速的插值器效果

注意事项:在定义插值器时,请确保初始值是0,最终值是1,才能保证动画以初始状态执行到最终效果,中间值可以超出这两个值的范围。另外,如果计算插值的函数如果是不连续的,将会导致动画不连贯。


上一篇:Android 属性动画(三)使用类型评估程序–TypeEvaluate
下一篇:Android 属性动画(五)为 ViewGroup 布局更改添加动画效果

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android属性动画是一种用于在Android应用程序中创建动画效果的框架。它允许您对任意对象的属性进行动画处理,而不仅仅是视图对象。使用属性动画,您可以平滑地改变对象的属性,如位置、大小、颜色等,从而创建流畅的动画效果。 属性动画的基本概念是通过改变对象的属性来实现动画效果,而不是通过改变视图的位置或绘制来实现。这使得属性动画比传统的补间动画更加灵活和强大。 要使用属性动画,您需要创建一个Animator对象,并指定要动画化的目标对象和属性。然后,您可以定义动画的持续时间、和监听属性。最后,启动动画并观察目标对象的属性的平滑变化。 以下是一个简单的示例,演示如何使用属性动画来平滑地改变视图对象的透明度: ```java // 创建一个属性动画对象,指定要改变的属性为视图对象的透明度 ObjectAnimator animator = ObjectAnimator.ofFloat(view, "alpha",***.setDuration(1000); // 设置,控制动画的变化速率 animator.setInterpolator(new AccelerateDecelerateInterpolator()); // 启动动画 animator.start(); ``` 在上面的示例中,我们创建了一个ObjectAnimator对象,指定要改变的属性为视图对象的透明度。然后,我们设置了动*** 除了ObjectAnimator,Android还提供了一些其他类型的属性动画,如ValueAnimator和AnimatorSet。这些类可用于更复杂的动画效果,如同时播放多个动画或在动画中修改多个属性。 希望这个简介能帮助您理解Android属性动画的基本概念和用法。如果您有更多问题,请随时提问!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值