Android动画机制-传统动画


概述

Android动画机制-传统动画是指在Android3.0之前存在的两种动画机制,一种是逐帧动画,也就是号首先人工画出来每一个时间点的视图效果,然后一张图片一张图片的播放形成动画效果;

另一种就是补间动画,就是开发人员指定开始与结束的情况,然后系统自动生成中间的图形,不断播放,形成动画效果。

逐帧动画

要开发逐帧动画首先要画出每一个时间点的图形效果,也就是每一个帧,而且Android自身的解耦机制推荐我们应该在res中的anim(所有动画公共的文件夹)新建xml来设计动画。但还是在Java中使用代码也可以

简单使用

和其他动画不同的是,代表逐帧动画的根节点animation-list应该放在drawable文件夹中(Eclipse可以放在anim文件夹中)

在drwable中新建zhu_zhen.xml:

<animation-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/fat_po_f01" android:duration="60"/>
    <item android:drawable="@drawable/fat_po_f02" android:duration="60"/>
    <item android:drawable="@drawable/fat_po_f03" android:duration="60"/>
</animation-list>

在layout中使用,既然是在drawable文件夹中,那么在@引用的时候就应该使用drawable,这里是把动画设置为ImageView的背景:

    <ImageView
        android:id="@+id/iv"
        android:layout_width="100dp" android:layout_height="100dp"
        android:background="@drawable/zhu_zhen"
        android:scaleType="center"/>
<!--并且两个按钮分别控制开关-->
    <LinearLayout android:layout_width="match_parent" android:layout_height="40dp"
                  android:orientation="horizontal">
        <Button android:layout_width="0dp" android:layout_height="match_parent"
                android:layout_weight="1"
                android:onClick="start" android:text="start"/>
        <Button android:layout_width="0dp" android:layout_height="match_parent"
                android:layout_weight="1"
                android:onClick="stop" android:text="stop"/>
    </LinearLayout>

android动画机制201611091025

在Activity中使用:

    private AnimationDrawable mDrawable;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        init();
    }

    private void init() {
        ImageView imageView = (ImageView) findViewById(R.id.iv);
        //把Drawable强制转换成AnimationDrawable
        mDrawable = (AnimationDrawable) imageView.getBackground();
    }

    public void start(View view) {
        mDrawable.start();
    }

    public void stop(View view) {
        mDrawable.stop();
    }

最后效果就是上面的阿宝如上面所示,注意AnimationDrawable也是Drawable的子类:

sp161109_095811

注意事项

每一帧的图片格式一定要是png而且不要直接改后缀名应该用另存为

加入每一帧是其他格式比如gif那么就会报错:Cannot generate texture from bitmap,而且ImageView整个是黑色的,无法正常显示。

补间动画

有四种形式,分别是AlpahAnimation、ScaleAnimation、TranslateAnimation、RotateAnimation,分别代表透明度动画、缩放动画,位移动画、旋转动画。注意这里每一个都是以Animation结尾。

sp161109_103711

四种常见的动画都是继承自Animation,还有一个是AnimationSet代表的是动画集合,另外一个不常用。

在上面的逐帧动画中也可以使用Java代码控制(有点麻烦)但是在补间动画中两种方式都比较简单。

四种动画共有的属性:

  1. duration持续时间
  2. fillAfter在动画执行完是否保持最后一帧还是返回第一帧

AlphaAnimation

在xml中使用

对应xml的标签是alpha

快速建立动画的方法:在AS中不要在anim总创建,意思就是说不要点击anim文件夹右键,而是点击res右键,这样可以直接控制跟标签,而且AS会自动把文件转到相应的目录:

sp161109_104522

透明度动画的特有属性:开始和结束的透明度

<alpha xmlns:android="http://schemas.android.com/apk/res/android"
       android:fromAlpha="1.0"
       android:toAlpha="0">
</alpha>

在Activity中使用:

    private void init() {
        mImageView = (ImageView) findViewById(R.id.iv);
        mAlphaAnimation = (AlphaAnimation) AnimationUtils.loadAnimation(MainActivity.this, R.anim.tween_alpha);
    }

    public void start(View view) {
        mAlphaAnimation.setDuration(3000);
        mAlphaAnimation.setFillAfter(true);
        mImageView.startAnimation(mAlphaAnimation);
    }

注意这里加载动画使用的是AnimationUtils.loadAnimation

android动画机制tweenalpah2016

用Java代码实现

只要改写一句话即可:

//        mAlphaAnimation = (AlphaAnimation) AnimationUtils.loadAnimation(MainActivity.this, R.anim.tween_alpha);
        mAlphaAnimation = new AlphaAnimation(1, 0);

两个参数分别是开始和结束的透明度

ScaleAnimation

缩放动画也是两种实现方式一种是在xml,一个是在Java中,在xml对应的标签是scale。

特有属性:

  1. fromYScale和toYScale(Y可以换成X)开始和结束的比例

  2. pivotX和pivotY缩放的中心点

注意:一定要同时制定fromX和Y(两组四个属性)否则开始动画就会立即消失

没有指定缩放中心默认是以左上点作为中心

在xml中实现

<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
       android:fromXScale="1.0" android:pivotX="50%"
       android:pivotY="50%" android:toXScale="0.2"
       android:fromYScale="1.0" android:toYScale="0.2">
</scale>

Activity中的实现代码,基本没有变化:

    private void init() {
        mImageView = (ImageView) findViewById(R.id.iv);
        mScaleAnimation = (ScaleAnimation) AnimationUtils.loadAnimation(MainActivity.this, R.anim.tween_scale);
    }

    public void start(View view) {
        mScaleAnimation.setDuration(3000);
        mScaleAnimation.setFillAfter(true);
        mImageView.startAnimation(mScaleAnimation);
    }

android动画机制tweenscaleh2016

使用Java实现

//      mScaleAnimation = (ScaleAnimation) AnimationUtils.loadAnimation(MainActivity.this, R.anim.tween_scale);
        mScaleAnimation = new ScaleAnimation(1, 0.2f, 1, 0.2f);

但是这里指定缩放中心困难,指定缩放比例简单

TranslateAnimation

表示位置移动的动画,特有属性:fromXDelta(当然还有to,而且XY可以互换)

在xml中实现

<translate xmlns:android="http://schemas.android.com/apk/res/android" 
           android:fromXDelta="0" android:toXDelta="100">
</translate>

在Activity中引用,和上面的代码基本一样:

    private void init() {
        mImageView = (ImageView) findViewById(R.id.iv);
        mTranslateAnimation = (TranslateAnimation) AnimationUtils.loadAnimation(MainActivity.this, R.anim.tween_translate);
    }

    public void start(View view) {
        mTranslateAnimation.setDuration(3000);
        mTranslateAnimation.setFillAfter(true);
        mImageView.startAnimation(mTranslateAnimation);
    }

android动画机制tweentranslate2016

使用Java实现

依旧就是更改一句话,不过少创建一个文件:

//        mTranslateAnimation = (TranslateAnimation) AnimationUtils.loadAnimation(MainActivity.this, R.anim.tween_translate);
        mTranslateAnimation = new TranslateAnimation(0, 100, 0, 0);

效果和上面一样

RotateAnimation

表示旋转的动画,特有属性:

  1. fromDegrees和toDegrees开始和结束的角度
  2. pivotX和pivotY旋转的中心点

在xml中实现

<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
        android:fromDegrees="0"
        android:pivotX="50%" android:pivotY="50%" android:toDegrees="3600">
</rotate>

android动画机制tweenrotate

在Avtivity中引用:

    private void init() {
        mImageView = (ImageView) findViewById(R.id.iv);
        mRotateAnimation = (RotateAnimation) AnimationUtils.loadAnimation(MainActivity.this,R.anim.tween_roate);
    }

    public void start(View view) {
        mRotateAnimation.setDuration(3000);
        mRotateAnimation.setFillAfter(true);
        mImageView.startAnimation(mRotateAnimation);
    }

使用Java实现

老规矩,只因为在人群改写一句代码,从此忘不了你的容颜啊!!!

//        mRotateAnimation = (RotateAnimation) AnimationUtils.loadAnimation(MainActivity.this,R.anim.tween_roate);
    mRotateAnimation = new RotateAnimation(0,3600);

这里还是中心点不好指定,默认是以左上角位旋转中心

AnimationSet

最后一个,写完去吃饭

img

代表动画集合的类,就可可以同时播放几个效果,在xml对应的标签是set,注意的子标签(scale,translate,rotate,alpha)有duration和fillAfter属性,他们单独使用没有这个属性。

而且还可以指定差速器(下一节细说)

在xml中实现

<set xmlns:android="http://schemas.android.com/apk/res/android"
     android:duration="3000"
     android:fillAfter="true">
    <alpha
        android:fromAlpha="1.0"
        android:toAlpha="0">
    </alpha>
    <rotate
        android:fromDegrees="0"
        android:pivotX="50%" android:pivotY="50%" android:toDegrees="3600">
    </rotate>

    <scale
        android:fromXScale="1.0" android:fromYScale="1.0"
        android:pivotX="50%" android:pivotY="50%"
        android:toXScale="0.2" android:toYScale="0.2">
    </scale>

    <translate
        android:fromXDelta="0" android:toXDelta="100">
    </translate>
</set>

就是把刚才的四个动画复制一下,不过这里在跟标签中指定了时间和fillAfter属性

android动画机制tweenset1141

在Activity中引用,效果还有一点炫:

    private void init() {
        mImageView = (ImageView) findViewById(R.id.iv);
        mAnimationSet = (AnimationSet) AnimationUtils.loadAnimation(MainActivity.this, R.anim.tween_set);
    }

    public void start(View view) {
        mImageView.startAnimation(mAnimationSet);
    }

在java代码实现

   private void init() {
        mImageView = (ImageView) findViewById(R.id.iv);
//      构造参数是否分享差速器
        mAnimationSet = new AnimationSet(true);

        mRotateAnimation = (RotateAnimation) AnimationUtils.loadAnimation(MainActivity.this,R.anim.tween_roate);
        mRotateAnimation.setDuration(3000);
        mRotateAnimation.setFillAfter(true);

        mScaleAnimation = (ScaleAnimation) AnimationUtils.loadAnimation(MainActivity.this,R.anim.tween_scale);
        mScaleAnimation.setDuration(3000);
        mScaleAnimation.setFillAfter(true);

        mTranslateAnimation = new TranslateAnimation(0, 100, 0, 0);

        mAlphaAnimation = new AlphaAnimation(1, 0);
        mAlphaAnimation.setDuration(3000);
        mAlphaAnimation.setFillAfter(true);

        mAnimationSet.addAnimation(mRotateAnimation);
        mAnimationSet.addAnimation(mTranslateAnimation);
        mAnimationSet.addAnimation(mScaleAnimation);
        mAnimationSet.addAnimation(mAlphaAnimation);
    }

    public void start(View view) {
        mImageView.startAnimation(mAnimationSet);
    }

比较麻烦

Animation好玩的属性

  1. setRepeatCount和setRepeatMode设置重复次数和模式
  2. setStartOffset设置开始延迟

We're here to put a dent in the universe. Otherwise why else even be here?