CheckBox/RadioButton切换动效实现

背景

因为项目需求要为CheckBox和RadioButton添加切换动画,以达到个性化的UI组件效果,具体来说项目需要的切换动画为复杂动画,即无法通过简单的平移,旋转,缩放等基本图形变换来模拟。经过查找资料,发现有如下几种实现动效的方式:

  1. ObjectAnimator,用来实现如平移,旋转,缩放等最基本的动效,无法满足项目要求。
  2. 自定义View专门来实现动画,这种成本很高,另外完全自定义也无法直接使用CheckBox的各项功能。
  3. VectorAnimatorDrawable,看起来很靠谱,能够实现很复杂的动画。但最大的难题是UI无法直接输出对应的资源,UI同学一般提供的动效资源是动效json,GIF,视频等资源,想要将其转化为VectorAnimatorDrawable资源非常困难,复杂一点的动效,要想完全还原设计稿基本不可能。
  4. Lottie动画,这也是Android开发领域较为主流的实现复杂动画的手段,这也是我最终采用的方案。但一般Lottie动画都是直接通过的LottieAnimationView(继承自ImageView)来使用的,如何将其与CheckBox进行结合是需要考虑的问题,下边也将详细描述Lottie动画如何结合CheckBox来完成切换动效功能。

分析&实现

首先上边的介绍都是关于CheckBox如何进行动画的,但对于RadioButton其实没提到。这是因为CheckBox和RadioButton本质上是同一类切换按钮,他们实现动效的思路也基本一致。另外从Android实现的角度来说他们也都是继承自CompoundButton的,该组件的特点是有选中和未选中两种状态,会根据点击事件切换状态。后边我们也将仅介绍基于CheckBox的动效实现,RadioButton基本可以复用该实现。

问题1. CheckBox动画该如何做,切状态的时机是在播动画前还是后。(借鉴Switch组件实现)

首先CheckBox切换动画为setChecked(),该方法直接在其父类CompundButton中定义

    @Override
    public void setChecked(boolean checked) {
        if (mChecked != checked) {
            mCheckedFromResource = false;
            mChecked = checked;
            refreshDrawableState();

            // ... 省略部分无关代码

        }
    }

该方法直接修改了mChecked状态,并没有提供任何关于动画播放的hook点。

一个小插曲,由于此次需求中还有Switch组件动效的开发,于是通过对Switch组件的研究,找到了播放动画的切入点。Switch组件通过重写setChecked()实现了动画播放(文章最后有展开介绍,实际是在SwitchCompat类中)。

    @Override
    public void setChecked(boolean checked) {
        super.setChecked(checked);

        // Calling the super method may result in setChecked() getting called
        // recursively with a different value, so load the REAL value...
        checked = isChecked();

        if (checked) {
            setOnStateDescriptionOnRAndAbove();
        } else {
            setOffStateDescriptionOnRAndAbove();
        }

        // 如果View仍然在View树上,则播动画;否则不播,直接切换状态
        if (getWindowToken() != null && ViewCompat.isLaidOut(this)) {
            animateThumbToCheckedState(checked);
        } else {
            // Immediately move the thumb to the new position.
            cancelPositionAnimator();
            setThumbPosition(checked ? 1 : 0);
        }
    }

在Switch组件中我们找到了动画播放的方式:先切换check状态,再播动画(animateThumbToCheckedState),于是现在我们可以得出CheckBox的动画播放框架(重写setChecked())

    @Override
    public void setChecked(boolean checked) {
        super.setChecked(checked);

        checked = isChecked();

        // 如果View仍然在View树上,则播动画;否则不播,直接切换状态
        if (getWindowToken() != null && ViewCompat.isLaidOut(this)) {
            animateThumbToCheckedState(checked);
        } else {
            cancelAnimator();
        }
    }

剩下的工作就是填充下面两个方法,整体来说就是处理具体动画该怎么播

  1. animateThumbToCheckedState(checked)
  2. cancelAnimator()

问题2:动画该怎么播

经过前边的分析,我们已经选定了Lottie动画作为播放动画的方案。并且预期的CheckBox切换流程为(以uncheck -> checked为例

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值