Android三种动画(属性、视图、帧动画)介绍基本使用

Android动画基本可以分为三类:
View Animation(视图动画)、Property Animation:(属性动画)和Drawable Animation(帧动画)。其中视图动画早在Android老版本就已经支持了,只能对view控件编辑动画。属性动画是Android在3.0版本后推出的API,是Google为了解决视图动画推出的,可以对任意的控件进行动画编辑。帧动画即一帧一帧的显示形成动画的。
属性动画可以完全代替视图动画,解决视图动画不能解决的问题,在现实使用中,属性动画较为使用频繁,本篇幅介绍属性动画的基本使用、帧动画的基本使用和补间动画的基本使用。
1、属性动画的基本使用:
属性动画的原理是通过特定的时长来改变一个属性的值,从而达到动画效果,使用的比较频繁的有三个类:ValueAnimator、ObjectAnimator、AnimatorSet。
**两种实现方法:**Android代码实现、xml文件实现。
android代码实现(以ObjectAnimator使用为例 ):
[1]通过onFloat返回ObjectAnimator 对象
ObjectAnimator oa = ObjectAnimator.onFloat(Object target, String propertyName, float… values) ;
[2]设置时长oa.setDuration(5000);
[3]启动oa.start();
xml实现方式:
[1]在res目录新建一个animator(animator为属性动画,anim为补间动画)目录,在改目录下创建xml文件。
对应的根节点:
animator 对应ValueAnimator
objectAnimator 对应ObjectAnimator
set 对应AnimatorSet
[2]在Android代码中使用属性动画资源:
oa.setTarget(iv);
oa.start();
下面解析一下ValueAnimator、ObjectAnimator、AnimatorSet这三个在属性动画中常用的类的用法。
ValueAnimator: 负责对值在提供时间得过度计算运行,还负责管理动画的播放次数、播放模式、动画监听器等,是个比较重要的类。它表示从设置的时间内(Duration设置)如何平滑的过度给定的初始值到结束值(ofFloat等的参数值)。如下例子,通过设置监听,打印出在1000ms内0过度到1的变化(至于Android如何实现这个变化在后面讲),结果如图1所示

//ValueAnimator
    private void ValueAnimator_test() {
    //设置初始值0和结束值1
        ValueAnimator valueA = ValueAnimator.ofFloat(0f,1f);
        //设置时间为1000ms
        valueA.setDuration(1000);
        //设置监听器,一旦值发生变化,即获取后打印出来
        valueA.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float animatorValue = (float) animation.getAnimatedValue();
                Log.e("tag","value : "+animatorValue);
            }
        });
        //启动
        valueA.start();
    }

android 组合动画结束回到原位置 android三种动画_android


如上演示了ValueAnimator的基本用法,在实际应用不会常用到此类,应用得多的是ObjectAnimator,但ValueAnimator是ObjectAnimator的基类,ObjectAnimator继承自ValueAnimator类。

ObjectAnimator:使用比较频繁的类,最终调用的还是ValueAnimator。该类实现Android各种动画
例如例子,以缩放从1倍到3倍到1倍的变化,在4000ms内完成此动作,结果如图2所示。也可左右移动,通过控件的getTranslationX获取当前x的位置,在当前位置移动到500处再移动回原来的位置,此动作在设置在4000ms内完成。结果如图3所示。

//ObjectAnimator
    private void ObjectAnimator_test() {
        /*
        * alpha:透明度
        *rotation:旋转角度
        *scaleY:竖直方向4秒内扩大3倍再缩放回原来的比例。
        * */
        ObjectAnimator objectA = ObjectAnimator.ofFloat(animText,"scaleY",1f,3f,1f);
        objectA.setDuration(4000);
        objectA.start();
        /*先调用TextView的getTranslationX方法来获取当前View的位置,在ofFloat第二个参数指定移动的方法,
        * 第三个参数指定从当前位置移动到500处再移动回到原来位置。
        * */
        /*float tranX = animText.getTranslationX();
        ObjectAnimator objectA = ObjectAnimator.ofFloat(animText,"translationX",tranX,500,tranX);
        objectA.setDuration(4000);
        objectA.start();*/
    }

android 组合动画结束回到原位置 android三种动画_动画_02


android 组合动画结束回到原位置 android三种动画_补间动画_03


至于其他效果,例如旋转,设置透明变化等,也可以参照此来设置显示相应的效果。

AnimatorSet:组合动画(四种组合方式如注释),即能同时将旋转、移动、透明等变化一起显示动作,也可以按先后顺序来显示等。
如下,显示透明变化后,同时进行缩放和旋转。效果如图3

/*
    * 组合动画
    * after(Animator anim)   将现有动画插入到传入的动画之后执行
    * after(long delay)   将现有动画延迟指定毫秒后执行
    * before(Animator anim)   将现有动画插入到传入的动画之前执行
    * with(Animator anim)   将现有动画和传入的动画同时执行
    * */
    private void AnimatorSet_test()
    {
        ObjectAnimator Sca = ObjectAnimator.ofFloat(animText,"scaleY",1f,3f);
        ObjectAnimator Rot = ObjectAnimator.ofFloat(animText,"rotation",0f,270f);
        ObjectAnimator alp = ObjectAnimator.ofFloat(animText,"alpha",1f,0f,1f);
        AnimatorSet set = new AnimatorSet();
        set.setDuration(3000);
        set.play(Sca).with(Rot).before(alp);
        set.start();
    }

android 组合动画结束回到原位置 android三种动画_动画_04

给动画设置监听器:

/*
    * 监听器:在某种状态发出某个动作
    *例子:在Y轴方向放大结束后,将textview字体改为浅黄色。
    * */
    private void Listener_test()
    {
        final ObjectAnimator objAni = ObjectAnimator.ofFloat(animText,"scaleY",1f,3f);
        objAni.setDuration(3000);
        objAni.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                animText.setTextColor(0xffb8860b);
            }
        });
        objAni.start();
    }

android 组合动画结束回到原位置 android三种动画_补间动画_05


在xml中设置动画方式:

在上面已经简单谈过xml的的使用方式,在这里以组合动画为例简单写一下xml的使用方式。

<?xml version="1.0" encoding="utf-8"?>
<!--
xml三种定义动画标签:
<animator>  对应代码中的ValueAnimator
<objectAnimator>  对应代码中的ObjectAnimator
<set>  对应代码中的AnimatorSet
-->
<!--<animator xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="3000"
    android:valueFrom="0f"
    android:valueTo="1f"
    android:valueType="floatType"
   />-->

<!--
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
    android:valueTo="3"
    android:valueFrom="1"
    android:valueType="floatType"
    android:propertyName="scaleX"
     />
-->

<set xmlns:android="http://schemas.android.com/apk/res/android">
    <objectAnimator
        android:duration="4000"
        android:propertyName="translationX"
        android:valueTo="0"
        android:valueType="floatType"
        android:valueFrom="500">
    </objectAnimator>

    <set
        android:ordering="together">
        <objectAnimator
            android:duration="4000"
            android:propertyName="rotation"
            android:valueFrom="0"
            android:valueTo="360"
            android:valueType="floatType"
            ></objectAnimator>
        <set
            android:ordering="sequentially">
            <objectAnimator
                android:duration="3000"
                android:propertyName="alpha"
                android:valueFrom="1"
                android:valueType="floatType"
                android:valueTo="0">
            </objectAnimator>
            <objectAnimator
                android:valueTo="1"
                android:valueFrom="0"
                android:duration="3000"
                android:propertyName="alpha"
                android:valueType="floatType">
            </objectAnimator>
        </set>
    </set>
</set>
/*
    * xml布局方式的Java调用代码如下
    * */
    private void xml_test()
    {
        Animator animator = AnimatorInflater.loadAnimator(this,R.animator.anim);
        animator.setTarget(animText);
        animator.start();
    }

xml使用的效果如下:

android 组合动画结束回到原位置 android三种动画_动画_06

2、帧动画基本使用:

帧动画即一个帧一个帧的拼在一起显示成动画,这里以进度为例,连续显示7张图片。

/*使用布局方式*/
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
    android:oneshot="false">

    <item android:drawable="@drawable/load1"
        android:duration="100"
        />

    <item android:drawable="@drawable/load2"
        android:duration="100"
        />
    <item android:drawable="@drawable/load3"
        android:duration="100"
        />
    <item android:drawable="@drawable/load4"
        android:duration="100"
        />
    <item android:drawable="@drawable/load5"
        android:duration="100"
        />
    <item android:drawable="@drawable/load6"
        android:duration="100"
        />
    <item android:drawable="@drawable/load7"
        android:duration="100"
        />
</animation-list>

/*Java代码调用方式
*这里需要在onWindowFocusChanged实现,是因为AnimationDrawable播放动画是依附在window上面的,而在Activity onCreate方法中调用时*Window还未初始化完毕,要想实现播放必须在onWindowFocusChanged中添加如下代码:*/
   @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);
        imagev.setImageResource(R.drawable.framentanimator);
        AnimationDrawable ad = (AnimationDrawable) imagev.getDrawable();
        ad.start();
    }
/*
    * 使用纯Java代码实现帧动画
    * */
    public void useJavashowfrement()
    {
        AnimationDrawable aDrawable =new  AnimationDrawable();
        for (int i=7;i>0;i--)
        {
            int id = getResources().getIdentifier("load"+i,"drawable",getPackageName());
            Drawable drawable = getResources().getDrawable(id);
            aDrawable.addFrame(drawable,100);
        }
        aDrawable.setOneShot(false);
        imagev.setImageDrawable(aDrawable);
        aDrawable.start();
    }

效果如下:

android 组合动画结束回到原位置 android三种动画_属性动画_07

3、补间动画的基本使用:
下面通过几个按钮来加载补间的几种动画,MainActivity的程序如下:

package com.example.namitortest;

import android.app.Activity;
import android.os.Bundle;
import android.os.PersistableBundle;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.Button;
import android.widget.ImageView;

/**
 * Created by new on 2017/7/14.
 */

public class TweenTest extends Activity implements View.OnClickListener{
    private ImageView showV;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.tween);
        showV = (ImageView) findViewById(R.id.showV);
        Button alphaB = (Button) findViewById(R.id.alphaBtn);
        Button scaleB = (Button) findViewById(R.id.scaleBtn);
        Button translateB = (Button) findViewById(R.id.translateBtn);
        Button rotateB = (Button) findViewById(R.id.rotateBtn);
        Button setB = (Button) findViewById(R.id.setBtn);
        alphaB.setOnClickListener(this);
        scaleB.setOnClickListener(this);
        rotateB.setOnClickListener(this);
        translateB.setOnClickListener(this);
        setB.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId())
        {
            case R.id.alphaBtn:
                Animation animation = new AnimationUtils().loadAnimation(getApplicationContext(),R.anim.tween_alpha);
                showV.startAnimation(animation);
                break;
            case R.id.rotateBtn:
                Animation animation1 = new AnimationUtils().loadAnimation(getApplicationContext(),R.anim.tween_rotate);
                showV.startAnimation(animation1);
                break;
            case R.id.setBtn:
                Animation animation2 = new AnimationUtils().loadAnimation(getApplicationContext(),R.anim.tween_set);
                showV.startAnimation(animation2);
                break;
            case R.id.scaleBtn:
                Animation animation3 = new AnimationUtils().loadAnimation(getApplicationContext(),R.anim.tween_scale);
                showV.startAnimation(animation3);
                break;
            case R.id.translateBtn:
                Animation animation4 = new AnimationUtils().loadAnimation(getApplicationContext(),R.anim.tween_translate);
                showV.startAnimation(animation4);
                break;
            default:
                break;
        }
    }
}

xml布局如下:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="alpha"
        android:id="@+id/alphaBtn"
        android:layout_marginLeft="20dp"
        android:layout_marginTop="20dp"/>
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/translateBtn"
        android:text="translate"
        android:layout_toRightOf="@id/alphaBtn"
        android:layout_marginLeft="20dp"
        android:layout_marginTop="20dp"/>
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/scaleBtn"
        android:text="scale"
        android:layout_toRightOf="@id/translateBtn"
        android:layout_marginLeft="20dp"
        android:layout_marginTop="20dp"/>

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/setBtn"
        android:text="set"
        android:layout_below="@id/alphaBtn"
        android:layout_marginLeft="20dp"
        android:layout_marginTop="20dp"
        />
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/rotateBtn"
        android:text="rotate"
        android:layout_marginLeft="20dp"
        android:layout_toRightOf="@id/setBtn"
        android:layout_below="@id/scaleBtn"
        android:layout_marginTop="20dp"
        />
    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/showV"
        android:src="@mipmap/ic_launcher"
        android:layout_below="@id/setBtn"
        android:layout_marginTop="150dp"
        android:layout_marginLeft="150dp"
        />
</RelativeLayout>

程序比较简单,通过5个按钮分别对应translate、scale、set、rotate、aphla五种动画。主要通过AnimationUtils().loadAnimation来获取Animation对象,再将控件的Animation设置为此动画方式即可。效果如下:

设置透明变化alpha效果:

android 组合动画结束回到原位置 android三种动画_android 组合动画结束回到原位置_08


设置移动变化translate效果:

android 组合动画结束回到原位置 android三种动画_动画_09


设置旋转rotate效果:

android 组合动画结束回到原位置 android三种动画_android_10


设置缩放scale效果:

android 组合动画结束回到原位置 android三种动画_android_11


设置动画组合set:

android 组合动画结束回到原位置 android三种动画_属性动画_12

这些是补间动画、帧动画和属性动画的基本使用,其中属性动画还有更高级的使用是补间动画实现不了的。