Android支持两种种类型的动画:属性动画和View动画。
View动画又分为补间动画(Tween动画)和帧动画(Frame动画或AnimationDrawable动画)。
动画的基本原理就是将组件的某个属性或整个组件的显示状态在一个特定的时间内从一个值或状态变化到一个新的值或状态。
我们先介绍View动画的补间动画。先从一个简单的例子开始,对补间动画有一个初步认识后再介绍补间动画的详细内容。
所谓补间动画就是在一个特定的时间内,按一定的速度将组件从一个位置移动到另一个位置、从一个角度旋转到另一个新的角度、将其显示透明度从一个值变换到另一个值、将其大小从一个尺度变换到另一个新的尺度。不仅如此,Android还允许将以上的4种操作合并在一个动画中执行。
一、补间动画举例
先看一个简单的例子,这个例子将一个TextView组件在4秒钟内以它的左下角为重心从角度0旋转顺时针到角度90,并且旋转的速度越来越快。运行效果如图所示:
期间,TextView在旋转,如图所示:
最后,4秒钟后完成动画,将显示动画的最终结果,如图所示:
现在看看实现这个例子的代码。
先看看布局文件res/layout/activity_main.xml,其内容如下:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.ttt.ex15animation01.MainActivity" >
<TextView
android:id="@+id/id_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_world" />
</RelativeLayout>
与布局一样,Android提供了两种定义动画的方式:通过XML文件定义动画和通过Java代码定义动画,
Android建议使用XML方式定义动画,并且View动画定义文件必须放置在res/anim工程目录下。为此,我们首先在工程的res目录下创建anim目录,并在其下创建一个名为my_rotate.xml的动画文件;
my_rotate.xml动画文件的内容为如下内容:
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/accelerate_interpolator"
android:fromDegrees="0"
android:toDegrees="90"
android:pivotX="0%"
android:pivotY="100%"
android:duration="4000"
android:fillAfter="true">
</rotate>
需要对这个文件的内容进行详细的解释。首先rotate标签表示我们定义旋转动画:其中的:
android:interpolator="@android:anim/accelerate_interpolator"
表示旋转动画的执行方式,称为动画插值器,其值为accelerate_interpolator,意思是动画的执行速度将越来越快。其中的
android:fromDegrees=“0”
android:toDegrees=“90”
表示旋转的初始角度和结束角度,分别为0度和90度。其中的:
android:pivotX=“0%”
android:pivotY=“100%”
表示以组件的左上角为原点的旋转中心点的坐标,有两种表示中心点的方式:带%的值和不带%的值。带%的值表示以组件的长度或高度为度量基础,不带%的值是以像素为度量基础。
在我们不知道组件的实际大小的情况下,使用百分比会更容易一些,例如,在我们的例子中,我们指定旋转中心的x坐标偏移组件长度的0%,也就是x=0,而y坐标则偏移组件宽度的100%,也就是y=组将的宽度。其中的
android:duration=“4000”
定义了动画执行的时间,单位是毫秒。其中的
android:fillAfter=“true”>
指定东环执行完成后组件的显示状态,true则表示组件保持动画执行完成后的状态,false则表示组件在动画执行完成后,回到动画执行前的状态。
已经定义好了的动画文件,现在需要修改MainActivity.java文件,使我们的TextView可以被动画处理。
修改后的MainActivity.java文件内容如下:
package com.ttt.ex15animation01;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.TextView;
public class MainActivity extends ActionBarActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView tv = (TextView) findViewById(R.id.id_tv);
Animation rotate = AnimationUtils.loadAnimation(this, R.anim.my_rotate);
tv.startAnimation(rotate);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
在onCreate毁掉函数中,我们获得TextView组件,并使用AnimationUtils类加载动画资源,然后在TextView组件上执行动画:
TextView tv = (TextView) findViewById(R.id.id_tv);
Animation rotate = AnimationUtils.loadAnimation(this, R.anim.my_rotate);
tv.startAnimation(rotate);
现在运行这个程序,即可得到如图1的效果。
二、补间动画类型
补间动画供包括4中动画形式,它们是:旋转动画、缩放动画、透明度动画和移位动画,标签分别为rotate、scale、alpha和translate。
1、定义rotate动画
定义rotate旋转动画的一般形式如下:
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@[package:]anim/interpolator_resource "
android:fromDegrees="float"
android:toDegrees="float"
android:pivotX="float"
android:pivotY="float"
android:startOffset="int"
android:duration="int"
android:fillAfter="boolean"
android:repeatCount="int"
android:repeatMode="restart | reverse"
>
</rotate>
表示启动动画的时间延迟和时间长度。
android:startOffset=“int”
android:duration=“int”
表示动画执行后是否在组件上保持动画执行后的最终结果。
android:fillAfter=“boolean”
表示动画重复的次数和重复的方式,重复的方式可取值为:restart、reverse。顾名思义,restart就是再次执行动画,reverse就是以相反的方式再次执行动画。
android:repeatCount=“int”
android:repeatMode=“int”
表示动画插值器,也就是采用何种方式来改变组件的值或组件的显示状态
android:interpolator="@[package:]anim/interpolator_resource "
Android内置的插值器如图所示:
2、定义scale动画
<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@[package:]anim/interpolator_resource "
android:fromXScale="float"
android:toXScale="float"
android:fromYScale="float"
android:toYScale="float"
android:pivotX="float"
android:pivotY="float"
android:startOffset="int"
android:duration="int"
android:fillAfter="boolean"
android:repeatCount="int"
android:repeatMode="restart | reverse"
>
</scale>
表示在x方向的以组件的宽度的基础的组件宽度变化的比例,例如,android:fromXScale=“1.4”、android:toXScale=“0.5”表示宽度从1.4倍变换到宽度的0.5倍。:
android:fromXScale=“float”
android:toXScale=“float”
表示组件在y方向上的以组件的高度为基础的组件高度变化比例。其他的参数同rotate中的说明
android:fromYScale=“float”
android:toYScale=“float”
3、定义alpha透明度动画
定义alpha透明度动画的一般形式如下:
<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@[package:]anim/interpolator_resource "
android:fromAlpha="float"
android:toAlpha="float"
android:startOffset="int"
android:duration="int"
android:fillAfter="boolean"
android:repeatCount="int"
android:repeatMode="restart | reverse"
>
</alpha>
表示组件的透明度值的变化,取值都从0.0到1.0,其中,0.0表示完全透明,1.0表示完全不透明。其他参数同rotate中的解释。
android:fromAlpha=“float”
android:toAlpha=“float”
4、定义translate移位动画
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@[package:]anim/interpolator_resource "
android:fromXDelta="float"
android:fromYDelta="float"
android:toXDelta="float"
android:toYDelta="float"
android:startOffset="int"
android:duration="int"
android:fillAfter="boolean"
android:repeatCount="int"
android:repeatMode="restart | reverse"
>
</translate>
表示以组件的左上角为原点的移动起始点的坐标,
android:fromXDelta=“float”
android:fromYDelta=“float”
有三种表示方式:普通数值、带%的数值和带%p的数值。其中普通数值表示像素点坐标值
例如,android:fromXDelta=“5”,表示起始点的x坐标为5;带%的数值表示以组件的宽度或高度为度量基础的像素点的坐标,
例如,android:fromXDelta="5%"表示起始点的x坐标为组件宽度的5%;带%p的数值表示以组件的父容器的宽度或高度为度量基础的像素点的坐标
表示移位结束时左上角所在的坐标点。表示方法同上。
android:toXDelta=“float”
android:toYDelta=“float”
5、定义复合set动画
除了可以使用rotate、scale、alpha和translate标签定义单个动画资源外,还可以使用set标签定义复合动画,所谓复合动画就是将多个动画合并成一个动画来执行。定义复合set动画的一般形式如下:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@[package:]anim/interpolator_resource"
android:shareInterpolator=["true" | "false"] >
<rotate …./>
<translate …./>
…
<set …> … </set>
</set>
也就是说,set动画是其他4类动画的组合,并且在set动画中还可以包含set动画。注意其中的一个配置参数:
android:shareInterpolator=["true" | "false"] >
表示在set中所指明的插值器是否用于所有的在set中定义的子动画,true表示是,false表示不。
三、使用动画监听器
动画Animation.AnimationListener监听器接口来监听动画执行的各个阶段,从Android的文档可以知道,该监听器接口包括三个接口方法,如图所示:
这三个方法分别用用于监听动画的开始(onAnimationStart)、结束(onAnimationEnd)和动画重复(onAnimationRepeat)。
修改MainActivity.java程序的onCreate回调函数,修改的onCreate函数如下:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView tv = (TextView) findViewById(R.id.id_tv);
Animation rotate = AnimationUtils.loadAnimation(this, R.anim.my_rotate);
rotate.setAnimationListener(new AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
// TODO Auto-generated method stub
}
@Override
public void onAnimationEnd(Animation animation) {
// TODO Auto-generated method stub
Toast.makeText(MainActivity.this, "动画结束",
Toast.LENGTH_LONG).show();;
}
@Override
public void onAnimationRepeat(Animation animation) {
// TODO Auto-generated method stub
}
});
tv.startAnimation(rotate);
}
在这个函数中,我们调用rotate.setAnimationListener设置rotate动画的监听器,并在onAnimationEnd方法中显示技术消息。运行修改后的程序,当动画结束时见显示如图所示的界面: