Android之动画(Java代码实现)1

知识点:
1. XML中自定义补间动画文件;
2. Java代码中实现补间动画效果;
3. Java实现帧动画;
4. 新名词记录{AlphaAnimation:透明动画;ScaleAnimation:缩放动画;TranslateAnimation:平移动画;RotateAnimation:旋转动画}


概述

Android给我们提供了逐帧动画(frame-by-frame animation)和补间动画(tweened animation)。帧动画就是将动画分成每一帧,一个一个的播放。补间动画有四种,包括淡入淡出,平移,缩放和旋转四种。

下面分别讲每一个补间动画,最后再来一个帧动画的使用。


利用XML文件进行动画

最常的是利用XML中直接自定义一个动画文件,使用像下面那样子,这里比较简单,我就不多讲了。

在res目录下面建一个anim文件夹,专门用来放置自定义的动画文件。这个貌似是必须的,因为在drawable文件夹下面建立一个XML文件,然后将根节点改成,IDE会提示我需要建立anim文件夹,将此类文件放置到新建的文件夹下面,否则编译不给通过的说。

R.anim.dialog_enter.xml文件

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate
        android:duration="2000"
        android:fromXDelta="0%p"
        android:fromYDelta="0%p"
        android:toXDelta="100%p"
        android:toYDelta="100%p" />
    <!--注意:100是绝对数值-->
    <!--100%是相对于自身-->
    <!--100%p是相对于父控件-->
    <alpha
        android:duration="2000"
        android:fromAlpha="1.0"
        android:toAlpha="0.0" />

    <scale
        android:duration="2000"
        android:fromXScale="0"
        android:fromYScale="0"
        android:toXScale="1"
        android:toYScale="1" />

    <rotate/>
</set>

上面我只是写了动画的节点名和部分参数设置,并没有详细的说明。

然后需要在activity里头调用此文件,关键代码如下:

//使用AnimationUtils类的静态方法loadAnimation()来加载XML中的动画XML文件
        //参数2:自定义的动画的名称
        Animation animator = AnimationUtils.loadAnimation(this, R.anim.dialog_enter);
        //我们也可以利用加载出来的动画,重新设置例如是否动画之后固定在最后的位置和动画时间等等参数,可以自己去试一下,不难
//        animator.setFillAfter(true);
//        animator.setDuration(3000);
        imgV_animator2.setAnimation(animator);
        animator.start();

上面我们主要用到了AnimationUtils.loadAnimation进行加载XML动画布局然后再给一个ImageView加上动画,最后不要忘记了要调用动画的start()方法,动画才能够真正的动起来。


动画的代码实现方式

话说我们可以用XML来进行设置动画,那么也一定可以使用代码的方式来实现,Google一定是给我提供了API来做动画滴。而且个人觉得,利用代码来实现感觉更好“玩”,毕竟最后都是要写代码的,那么就全部用代码来实现呗,不是“省时省力”,看起来还统一,而且不用谢N多个文件,乱得要死。

XML声明动画
alpha   渐变透明度动画效果
scale   渐变尺寸伸缩动画效果
translate   画面转换位置移动动画效果
rotate  画面转移旋转动画效果

Java代码对应动画了
AlphaAnimation  渐变透明度动画效果
ScaleAnimation  渐变尺寸伸缩动画效果
TranslateAnimation  画面转换位置移动动画效果
RotateAnimation 画面转移旋转动画效果

动画类,都是继承了基类:Animation类。

下面我们来看一下动画是如何用代码来实现的。这里会针对每一个动画来讲解。

AlphaAnimation透明度动画
void alphaAnimation() {
        AlphaAnimation alphaAnimation = new AlphaAnimation(0, 1);
        alphaAnimation.setDuration(3000);
        //实践证明:重复3次的意思是:这个动画首次出现完全后,再重复3次,所以我们会看到有4次
        alphaAnimation.setRepeatCount(3);
        alphaAnimation.setRepeatMode(INFINITE);
        alphaAnimation.setFillAfter(true);
        //设置速率
//        alphaAnimation.setInterpolator();
        //设置开始时时间的偏移量,用在动画集合上面比较多
//        alphaAnimation.setStartOffset();
        alphaAnimation.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {

            }

            @Override
            public void onAnimationEnd(Animation animation) {
                rotateAnimation();
            }

            @Override
            public void onAnimationRepeat(Animation animation) {

            }
        });
        imgV_animator2.setAnimation(alphaAnimation);
        alphaAnimation.start();
    }

可以看到上面,可以设置动画的参数,比如监听动画开始结束等。大伙自己去体会吧。


TranslateAnimation平移动画

TranslateAnimation类是对应XML中的translate节点的。

void translateAnimation() {
        /**
         * 此方法默认的都是使用绝对布局Animation.ABSOLUTE的
         */
        TranslateAnimation translateAnimation = new TranslateAnimation(0, 300, 0, 300);

        /**
         * 下面构造方法是可以指定开始位置和结束位置依赖于哪一个布局参数来测量移动的
         * 一下是各个参数的解释:
         *Animation.ABSOLUTE:绝对位置,即距离屏幕远点(左上角)的位置
         *Animation.RELATIVE_TO_SELF:相对于自身的距离
         *Animation.RELATIVE_TO_PARENT:现对于控件父布局的距离
         */
        TranslateAnimation translateAnimation1 = new TranslateAnimation(
                Animation.RELATIVE_TO_SELF, 0,
                Animation.RELATIVE_TO_PARENT, 300,
                Animation.RELATIVE_TO_SELF, 0,
                Animation.RELATIVE_TO_PARENT, 300);

        translateAnimation.setDuration(3000); //动画持续时间
        translateAnimation.setFillAfter(true); //动画之后,停留在最后面
        translateAnimation.setRepeatMode(0);
        imgV_animator2.setAnimation(translateAnimation);
        //设置动画的监听
        translateAnimation.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {
            }

            @Override
            public void onAnimationEnd(Animation animation) {
                alphaAnimation();//动画完成之后,再调用另外一个方法,继续透明度的动画
            }

            @Override
            public void onAnimationRepeat(Animation animation) {

            }
        });
        translateAnimation.start();
    }

平移动画最重要的是要理解:移动的距离相对于那一个元素进行移动理解了这一点,剩下的其它参数和前面的差不多的。


RotateAnimation旋转动画

对应XML下的rotate节点。

void rotateAnimation() {
        RotateAnimation rotateAnimation = new RotateAnimation(0, 360, RELATIVE_TO_PARENT, 0.2F, RELATIVE_TO_PARENT, 0.2F);
        rotateAnimation.setFillAfter(true);
        rotateAnimation.setDuration(2000);
        rotateAnimation.setRepeatMode(0);
        rotateAnimation.setDetachWallpaper(true);
        rotateAnimation.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {

            }

            @Override
            public void onAnimationEnd(Animation animation) {
                translateAnimation();
            }

            @Override
            public void onAnimationRepeat(Animation animation) {

            }
        });
        imgV_animator2.setAnimation(rotateAnimation);
        rotateAnimation.start();
    }

注意:同理,这里也是要关注旋转中心相对于哪一个距离参数来作为旋转


ScaleAnimation旋转动画

ScaleAnimation对应XML文件里面的scale节点。

void scaleAnimationTest() {
        ScaleAnimation scaleAnimation = new ScaleAnimation(0f, 1f, 0f, 1f, Animation.ABSOLUTE, 0.5f, ABSOLUTE, 0.5f);
        scaleAnimation.setDuration(2000); //动画持续时间
        scaleAnimation.setInterpolator(new AccelerateInterpolator()); //设置为加速
        scaleAnimation.setFillAfter(true); //结束动画之后,是否停留在最后
        scaleAnimation.setRepeatCount(7); //重复的次数
        imgV_animator2.setAnimation(scaleAnimation);
        scaleAnimation.start();
    }

注意:这里同样要考虑旋转的中心点取值问题,相对于自身/父布局或者是整个屏幕


AnimationDrawable帧动画

最后来一个大招:播放图片动画。我们可以再XML文件里头,为设置循环播放的图片以及为每一帧动画设置展示时间,然后直接调用就可以了。

但是,我很懒啊,不想这么来搞,我希望可以统一加载进来,然后进行动画。下面就是一次从资源文件里头加载图片,并且直接给imageview设置动画的代码。代码里面很详细了,不多讲了。

void drawableAnimationTest() {
        AnimationDrawable animationDrawable = new AnimationDrawable();
        Drawable drawable = null;
        for (int i = 0; i < 5; i++) {
            /**
             * getIdentifier():获各应用包下的指定资源ID
             * 参数说明
             * 参数1:图片的名称,或者是全限定名(格式:package:type/entry)
             * 参数2:文件夹的名称,或者如果参数1设定为全限定名,可以为null
             * 参数3:应用包名
             * 返参:如果没有找到,则返回0。0是不可用的资源id。
             */
            /**
             * 说了那么多没用,直接看代码
             */
            int resId = getResources().getIdentifier("start_play", "drawable", this.getPackageName());
            CommonLog.logInfo("resId1:" + resId);

            //路径可能不对
            int resId2 = getResources().getIdentifier("com.yaojt.Banana.main.src.drawable.start_play", "null", "null");
            CommonLog.logInfo("resId2:" + resId2);

            if (resId > 0) {
                drawable = getResources().getDrawable(resId);
                animationDrawable.addFrame(drawable, 500);
            }


            String path = "com/yaojt/Banana/imageName.png";
            //根据路径,拿到URL,再以数据流的形式读入内存中。
            InputStream is = getClassLoader().getResourceAsStream(path);
            Drawable drawable1 = Drawable.createFromStream(is, "src");

        }
        animationDrawable.setOneShot(false);
        imgV_animator2.setBackground(animationDrawable);
    }

总结

动画的内容还是不少的,理解起来不会难,难的是我们要将各个动画效果组合起来。我这里都是分开来展示的,希望将知识点化作最小的颗粒,可以更好地理解和吸收。每一块砖都知道怎么用了,盖一个大楼不就是分分钟的事了嘛。

如有任何问题,请及时与我联系,谢谢!