Android 左右抖动动画

目标效果

触发后,金币左右抖动多次,向上移动并消失,文字向下移动显示

实现方式似乎很简单,依次实现上述三个动画即可

而本文主要展示我在第一个动画的探索过程

版本1

我们需要保持动画结束时的状态,故采用属性动画。

    ObjectAnimator.ofFloat(iv_coin, "translationX",  -100f,  100f).apply {
        duration = 1000
        repeatCount = 2
        repeatMode = ValueAnimator.REVERSE
    }.start()   

存在问题,动画播放开始时,金币直接跳到左边,而非缓慢移动到左边,导致动画开始时和结束时很突兀。

版本2

针对发现的原因,我们把中点到左边的过程也纳入动画中,
改变如下

原本: left -> right
现在: mid -> left -> mid -> right -> mid

同时,重复模式也要改成RESTART, 原因,动画重复时,当前定义的路径是不能翻转的。

    ObjectAnimator.ofFloat(iv_coin, "translationX",  0f, -100f, 0f, 100f, 0f).apply {
        duration = 1000
        repeatCount = 2
        repeatMode = ValueAnimator.RESTART
    }.start()   

存在问题,重复播放到中点时,金币摆动的速度会变得很慢,后才逐渐加快

版本3

一直误以为插值器是匀速线性,即LinearInterpolator,导致的这个错误认知的原因应该来源于这个方法。
当设的值为空时,便设为LinearInterpolator

    @Override
    public void setInterpolator(TimeInterpolator value) {
        if (value != null) {
            mInterpolator = value;
        } else {
            mInterpolator = new LinearInterpolator();
        }
    }

而实际上默认的插值器是非线性的,即AccelerateDecelerateInterpolator,先加速后减速。仔细想想使用这个插值器更加合理,更加接近自然效果。
生活中,当我们用力推动一个小球一段时间,加速到减速的过程更加符合实际。

而这里,我们尝试将插值器改为线性的。

    ObjectAnimator.ofFloat(iv_coin, "translationX",  0f, -100f, 0f, 100f, 0f).apply {
        duration = 1000
        repeatCount = 2
        interpolator=LinearInterpolator()
        repeatMode = ValueAnimator.RESTART
    }.start()   

存在问题,摆动的整个过程很僵硬,不符合自然效果。

版本4

为了让金币摆动自然,我的方案是将金币摆动的过程分为三个动画实现,每个动画使用默认的插值器。

动画1:mid -> left
动画2:left -> right
动画3:right -> mid

注意duration时间的分配

            AnimatorSet().apply {

                val xDuration = 1000L
                val xOffset = 100f

                playSequentially(
                    ObjectAnimator.ofFloat(iv_coin, "translationX", -xOffset)
                        .setDuration((xDuration / 2)),
                    ObjectAnimator.ofFloat(iv_coin, "translationX", -xOffset, xOffset).apply {
                        duration = xDuration
                        repeatMode = ValueAnimator.REVERSE
                        repeatCount = 2
                    },
                    ObjectAnimator.ofFloat(iv_coin, "translationX", 0f).setDuration((xDuration / 2))
                )
            }.start

效果已经符合我的需求,不知道有没有更好的实现方式?

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值