android分层动画

本文介绍了如何在Android中实现分层动画,特别是当需要一个正方形逆时针旋转,而外层正方形顺时针旋转时的解决方案。讨论了简单使用ImageView、使用GIF图和帧动画的局限性,并提出了利用layer-list和 AnimatedRotateDrawable来实现更灵活的动画效果,详细解析了源码和最终实现的效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

废话不说,先上图


这样一个图如果需要让中间的正方形逆时针转,外层正方形顺时针转,你会怎么做?

1.简单,弄两个ImageView然后让他们转起来就好了。

貌似这样做确实比较简单,但如果正方形数量比较多的时候就尴尬了,或者我要让这个动画当某段文字的背景,这种做法就比较麻烦了

2.用gif图实现

gif图较大,且拉伸容易失真

3.帧动画

将动画拆分成n个图片,顺序播放。对于一些简单动画没必要这样做,如旋转放大这些,我们只要一张图片然后自己加动画就可以实现了。

接下来说说我的做法:

layer-list这个标签相信大家都不陌生,他可以实现将多个drawable嵌套在一起

<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/ic_action_big"/>

<item android:drawable="@drawable/ic_action_small"/>

</layer-list>
像这样,上面那个图就做出来了,那如何在这基础上增加动画呢?

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <animated-rotate
            android:drawable="@drawable/ic_action_big"
            android:pivotX="50%"
            android:pivotY="50%"/>
    </item>

    <item>
        <animated-rotate
            android:drawable="@drawable/ic_action_small"
            android:pivotX="50%"
            android:pivotY="50%"/>
    </item>

</layer-list>
google也提供了一些简单的动画让我们选,如旋转
当然代码里还要手动让动画跑起来

	View view = findViewById(R.id.vp);
        LayerDrawable drawable = (LayerDrawable) view.getBackground();
        Animatable a = (Animatable) drawable.getDrawable(0);
        Animatable b = (Animatable) drawable.getDrawable(1);
        a.start();
        b.start();
轻松转起来,效果如下:


说好的一个顺时针一个逆时针呢?

由于animated-rotate封装的比较严,没有更多的属性可以设置。先翻翻源码看看吧!

实现类是AnimatedRotateDrawable

    private final Runnable mNextFrame = new Runnable() {
        @Override
        public void run() {
            // TODO: This should be computed in draw(Canvas), based on the amount
            // of time since the last frame drawn
            mCurrentDegrees += mIncrement;
            if (mCurrentDegrees > (360.0f - mIncrement)) {
                mCurrentDegrees = 0.0f;
            }
            invalidateSelf();
            nextFrame();
        }
    };
这段代码我们可以知道是mIncrement变量控制动画每一次刷新旋转的角度和方向,由于这个类是@hide注释的,我们无法直接获得,所以通过反射来设置

	View view = findViewById(R.id.vp);
        LayerDrawable drawable = (LayerDrawable) view.getBackground();
        Animatable a = (Animatable) drawable.getDrawable(0);
        Animatable b = (Animatable) drawable.getDrawable(1);
        try {
            a.getClass().getDeclaredMethod("setFramesCount",int.class).invoke(b,-12);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
        a.start();
        b.start();
设置为负数就是逆时针旋转了,但需要注意的是源码里每转一圈就会将mCurrentDegrees置零,所以可以无限转圈,设置为负数后这个重置就无效了,经计算,按1.8s旋转一圈的速度大约经过11小时后就会爆掉float上限,不过几乎不会一直让他播放11个小时,哈哈!

最后附上效果图:







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值