本篇博客基于《Android开发艺术探索》,将会介绍以下两种动画:
事实上帧动画也是补间动画的一种,但是它们的使用方式略有不同,所以将它们分开介绍。
补间动画(Tween animation)也叫做View动画,因为它的作用对象是View,它支持平移、缩放、旋转和透明度四种变换效果,它们的具体描述如下表所示:
名称 | 标签 | 子类 | 效果 |
---|---|---|---|
平移动画 | TranslateAnimation | 移动View | |
缩放动画 | ScaleAnimation | 放大或缩小View | |
旋转动画 | RotateAnimation | 旋转View | |
透明度动画 | AlphaAnimation | 改变View透明度 |
补间动画的创建有两种形式:XML文件和代码形式,下面分别介绍它们。
XML文件形式即通过在XML文件中设置相关属性来达到动画的效果,需要特别注意的是动画相关的XML文件必须放置在 res/anmi/ 文件夹中,如下图所示:
刚创建的文件如下所示:
<set xmlns:android="http://schemas.android.com/apk/res/android">
set>
可以看到有一个
属性 | 描述 |
---|---|
interpolator | 表示动画集合所采用的插值器,默认为加减速插值器 |
shareInterpolator | 表示集合中的动画是否和集合共享同一个插值器。如果集合不指定插值器,那么子动画就需要单独指定所需的插值器或使用默认值 |
例子:
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:shareInterpolator="false">
......
set>
在这个例子中 intercepolator
设置为 @android:anim/accelerate_decelerate_interpolator
,即默认值,如果不设置该属性达到的效果也是一样的。将 shareInterpolator
属性设置为 false
表示集合中的动画不和集合共享同一插值器。
属性 | 描述 |
---|---|
fromXDelta | 表示 x 的起始值 |
toXDelta | 表示 x 的结束值 |
fromYDelta | 表示 y 的起始值 |
toYDelta | 表示 y 的结束值 |
其中,各个属性有如下三种取值类型可供选择:
类型 | 描述 |
---|---|
float | 当取值为浮点类型的数值时,表示为绝对值类型,默认以px为单位 |
% | 相对自身的百分比取值,表示以当前View的宽度或高度为基数计算 |
%p | 相对父布局的百分比取值,表示以父视图的宽度或高度为基数计算 |
平移动画的起始点为View的左上角位置,如下图所示:
例子:
<translate
android:duration="100"
android:fromXDelta="0.5"
android:toXDelta="100.5"
android:fromYDelta="0.5"
android:toYDelta="100.5" />
该例子表示View从 (0.5, 0.5) 的位置平移到 (100.5, 100.5) 的位置,动画时间为100ms。
属性 | 描述 |
---|---|
fromXScale | 水平方向缩放的起始值 |
toXScale | 水平方向缩放的结束值 |
fromYScale | 竖直方向缩放的起始值 |
toYScale | 竖直方向缩放的结束值 |
pivotX | 缩放的轴点的 x 坐标 |
pivotY | 缩放的轴点的 y 坐标 |
例子:
<scale
android:duration="500"
android:fromXScale="0.5"
android:toXScale="1.5"
android:fromYScale="0.5"
android:toYScale="1.5"/>
这个例子是将View从原来的0.5倍放大到原来的1.5倍,动画时间是500ms。缩放轴点为View左上角(默认情况下),如果想以View中心为轴点,可以做如下设置:
<scale
android:duration="500"
android:fromXScale="0.5"
android:toXScale="1.5"
android:fromYScale="0.5"
android:toYScale="1.5"
android:pivotX="50%"
android:pivotY="50%"/>
其中轴点的取值方式也有三种类型可供选择:浮点型数字、相对自身的百分号%和相对父布局的百分比%p,这三种类型的含义在 translate 部分已经说过,这里不再赘述。
属性 | 描述 |
---|---|
fromDegrees | 旋转开始的角度 |
toDegrees | 旋转结束的角度 |
pivotX | 旋转的轴点的 x 坐标 |
pivotY | 旋转的轴点的 y 坐标 |
<rotate
android:duration="400"
android:fromDegrees="0.0"
android:toDegrees="90.0"/>
该例子表示View从0°旋转90°,轴点为View的左上角(默认情况下)。如果想以View中心为轴点的话,可以按如下进行属性设置:
<rotate
android:duration="400"
android:fromDegrees="0.0"
android:toDegrees="90.0"
android:pivotX="50%"
android:pivotY="50%"/>
这和缩放动画中轴点的相关设置是一致的,同样可以有三种取值方式:浮点型数值、相对自身的百分比以及相对父布局的百分比,这里不再赘述。
属性 | 描述 |
---|---|
fromAlpha | 表示透明度的起始值 |
toAlpha | 表示透明度的结束值 |
alpha属性的取值为0.0~1.0。其中0.0表示完全透明,1.0表示完全不透明。
例子:
<alpha
android:duration="500"
android:fromAlpha="0.0"
android:toAlpha="1.0"/>
这个例子表示将View的透明度从完全透明变为完全不透明,动画时间为500ms。
上面所说的为各自标签所特有的属性,它们之间也存在一些共有的属性,如下表所示:
属性 | 描述 |
---|---|
duration | 动画的持续时间,单位为ms |
fillAfter | 动画结束后View是否停留在结束位置,true表示停留在结束位置 |
startOffset | 动画执行延迟的时间,单位为ms |
interpolator | 用于控制动画在不同时段的执行速度,默认是加减速插值器 |
repeatCount | 动画的重复次数,默认为0,即不重复 |
repeatMode | 有两个取值:restart和reverse,reverse表示动画正反轮流执行,restart表示一直从头开始执行 |
zAdjustment | 在执行动画过程中调整Z轴的位置,有三个取值可选:normal、top和bottom,默认为normal |
前面的XML文件设置完成之后,我们在Java中如何将它们引入相关的View播放动画呢?这就要借助 AnimationUtils#loadAnimation
方法来添加了,例如我们现在要为一个 ImageView 添加动画,代码如下所示:
Animation anim = AnimationUtils.loadAnimation(MainActivity.this, R.anim.anmi_demo);
imageView.startAnimation(anim);
上面就是关于XML形式的简要介绍,接下来我们来了解通过Java代码的形式设置补间动画。
在Java中,translate、scale、rotate、alpha、set分别对应下面的几个类:
下面分别介绍它们的使用。
TranslateAnimation
有三个构造方法来创建对象,这三个构造方法的说明如下所示:
public TranslateAnimation(Context context, AttributeSet attrs)
参数 | 含义 |
---|---|
context | 上下文对象 |
attrs | xml中读取的属性设置 |
public TranslateAnimation(float fromXDelta, float toXDelta, float fromYDelta, float toYDelta)
参数 | 含义 |
---|---|
fromXDelta | 动画开始时x的取值,单位为px |
toXDelta | 动画结束时x的取值,单位为px |
fromYDelta | 动画开始时y的取值,单位为px |
toYDelta | 动画结束时y的取值,单位为px |
public TranslateAnimation(int fromXType, float fromXValue, int toXType, float toXValue,
int fromYType, float fromYValue, int toYType, float toYValue)
参数 | 含义 |
---|---|
fromXType | 动画开始时x的取值类型 |
fromXValue | 动画开始时x的取值,其取值受fromXType影响 |
toXType | 动画结束时x的取值类型 |
toXValue | 动画结束时x的取值,其取值受toXType影响 |
fromYType | 动画开始时y的取值类型 |
fromYValue | 动画开始时y的取值,其取值受fromYType影响 |
toYType | 动画结束时y的取值类型 |
toYValue | 动画结束时y的取值,其取值受toYType影响 |
在这个构造方法中,Type 的取值有如下三个,它们的描述如下表所示:
Type | 描述 |
---|---|
Animation.ABSOLUTE | 取绝对值,所取值表示像素值的大小,单位为px |
Animation.RELATIVE_TO_SELF | 相对自身的百分比取值,所取值表示相对自身长/宽的百分比 |
Animation.RELATIVE_TO_PARENT | 相对父布局的百分比取值,所取值表示相对父布局长/宽的百分比 |
下面我们以 ImageView 从 (0,0) 处平移到 (100,100) 处为例进行代码的示范:
TranslateAnimation anim = new TranslateAnimation(0.0f, 100.0f, 0.0f, 100.0f);
anim.setDuration(1000);
imageView.startAnimation(anim);
ScaleAnimation
有4个构造方法来创建对象,它们的说明如下所示:
public ScaleAnimation(Context context, AttributeSet attrs)
参数 | 含义 |
---|---|
context | 上下文对象 |
attrs | xml中读取的属性设置 |
public ScaleAnimation(float fromX, float toX, float fromY, float toY)
参数 | 含义 |
---|---|
fromX | x开始时的缩放比例 |
toX | x结束时的缩放比例 |
fromY | y开始时的缩放比例 |
toY | y结束时的缩放比例 |
public ScaleAnimation(float fromX, float toX, float fromY, float toY,
float pivotX, float pivotY)
参数 | 含义 |
---|---|
fromX | x开始时的缩放比例 |
toX | x结束时的缩放比例 |
fromY | y开始时的缩放比例 |
toY | y结束时的缩放比例 |
pivotX | 缩放轴点的x坐标,单位为px |
pivotY | 缩放轴点的y坐标,单位为px |
public ScaleAnimation(float fromX, float toX, float fromY, float toY,
int pivotXType, float pivotXValue, int pivotYType, float pivotYValue)
参数 | 含义 |
---|---|
fromX | x开始时的缩放比例 |
toX | x结束时的缩放比例 |
fromY | y开始时的缩放比例 |
toY | y结束时的缩放比例 |
pivotXType | 缩放轴点x的取值类型 |
pivotXValue | 缩放轴点的x的取值,其取值受pivotXType影响 |
pivotYType | 缩放轴点y的取值类型 |
pivotYValue | 缩放轴点的y的取值,其取值受pivotYType影响 |
其中 Type 的取值同样也有三种:Animation.ABSOULTE
、Animation.RELATIVE_TO_SELF
和 Animation.RELATIVE_TO_PARENT
,分别表示像素值、相对自身的百分比取值以及相对父布局的百分比取值。
下面我们还是以ImageView
为例,缩放轴点设置为其中点,开始时缩小到原来的0.5倍,然后经过500 ms的时间逐渐扩大到原来的1.5倍,代码如下所示:
ScaleAnimation anim = new ScaleAnimation(0.5f, 1.5f, 0.5f, 1.5f,
Animation.RELATIVE_TO_SELF, 0.5f,
Animation.RELATIVE_TO_SELF, 0.5f);
anim.setDuration(500);
imageView.startAnimation(anim);
可以看到我们在这里由于需要取View的中点作为轴点,所以采用相对自身百分比的形式进行取值。
RotateAnimation
同样有4个方法来创建对象,说明如下所示:
public RotateAnimation(Context context, AttributeSet attrs)
参数 | 含义 |
---|---|
context | 上下文对象 |
attrs | xml中读取的属性设置 |
public RotateAnimation(float fromDegrees, float toDegrees)
参数 | 含义 |
---|---|
fromDegrees | 开始旋转时的角度值 |
toDegrees | 旋转结束时的角度值 |
public RotateAnimation(float fromDegrees, float toDegrees, float pivotX, float pivotY)
参数 | 含义 |
---|---|
fromDegrees | 开始旋转时的角度值 |
toDegrees | 旋转结束时的角度值 |
pivotX | 轴点的x坐标,单位为px |
pivotY | 轴点的y坐标,单位为px |
public RotateAnimation(float fromDegrees, float toDegrees, int pivotXType, float pivotXValue,
int pivotYType, float pivotYValue)
参数 | 含义 |
---|---|
fromDegrees | 开始旋转时的角度值 |
toDegrees | 旋转结束时的角度值 |
pivotXType | 轴点x的取值类型 |
pivotXValue | 轴点x的取值,其取值受pivotXType的影响 |
pivotYType | 轴点y的取值类型 |
pivotYValue | 轴点y的取值,其取值受pivotYType的影响 |
接下来同样通过一个例子来展示下它的使用,我们还是以ImageView
为例,以其中点为轴心旋转90°,代码如下所示:
RotateAnimation anim = new RotateAnimation(0.0f, 90.0f,
Animation.RELATIVE_TO_SELF, 0.5f,
Animation.RELATIVE_TO_SELF, 0.5f);
anim.setDuration(1000);
imageView.startAnimation(anim);
AlphaAnimation
应当是这所有动画类型里面最为简单的了,它只有以下两个构造方法:
public AlphaAnimation(Context context, AttributeSet attrs)
参数 | 含义 |
---|---|
context | 上下文对象 |
attrs | xml中读取的属性设置 |
public AlphaAnimation(float fromAlpha, float toAlpha)
参数 | 含义 |
---|---|
fromAlpha | 动画开始时的透明度,0表示完全透明,1表示完全不透明 |
toAlpha | 动画结束时的透明度,0表示完全透明,1表示完全不透明 |
AlphaAnimation
的应用比较简单,这里就不给出示例了。
AnimationSet
和前面的4个类不同,它是用于组合动画的,它有如下两个构造方法:
public AnimationSet(Context context, AttributeSet attrs)
参数 | 含义 |
---|---|
context | 上下文对象 |
attrs | xml中读取的属性设置 |
public AnimationSet(boolean shareInterpolator)
参数 | 含义 |
---|---|
shareInterpolator | 用于设置是否和集合中的动画共享同一个插值器 |
在初始化完 AnimationSet
对象之后,我们就可以通过 Animation#addAnimation
方法将动画添加到集合当中了,示例如下所示:
TranslateAnimation translateAnim = new TranslateAnimation(0.0f, 100.0f, 0.0f, 100.0f);
AlphaAnimation alphaAnim = new AlphaAnimation(0.0f, 1.0f);
AnimationSet animSet = new AnimationSet(false);
animSet.addAnimation(translateAnim);
animSet.addAnimation(alphaAnim);
animSet.setDuration(1000);
imageView.startAnimation(animSet);
这个例子将平移动画和透明度动画进行了组合,动画持续时间为1s。以上就是有关补间动画中Java代码形式的所有内容。
我们还可以通过开启动画监听来处理播放动画启动时、动画结束时、重复播放动画时的相关代码逻辑。动画监听的开启通过调用 Animation#setAnimationListener
方法进行设置,传入的参数为 Animation.AnimationListener
,示例如下所示:
TranslateAnimation anim = new TranslateAnimation(0.0f, 100.0f, 0.0f, 100.0f);
anim.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
// 动画启动时回调该方法
}
@Override
public void onAnimationEnd(Animation animation) {
// 动画播放结束时回调该方法
}
@Override
public void onAnimationRepeat(Animation animation) {
// 动画重复播放时回调该方法
}
});
虽然上面对补间动画进行了各个角度和维度的批判,但是补间动画依然有它存在的意义,要不 Google 也不会现在都还对它进行支持。它主要有两种使用场景,下面对它们一一进行介绍。
LayoutAnimation
的作用对象是 ViewGroup
,它可以为 ViewGroup
指定一个动画,这样当它的子元素出场时都会带有这种动画效果。这种效果最常见的使用场景是ListView
的进场动画,它同样有XML和Java代码两种使用方式,使用如下所示:
定义的XML文件毫无疑问也是放在 res/anim/ 文件夹下的,如下所示:
<layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"
android:delay="0.5"
android:animation="@anim/anmi_demo"
android:animationOrder="normal">
layoutAnimation>
其中,anmi_demo.xml
的代码如下:
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="300"
android:interpolator="@android:anim/accelerate_interpolator"
android:shareInterpolator="true">
<translate
android:fromXDelta="100%p"
android:toXDelta="0"/>
<alpha
android:fromYDelta="0.0"
android:toYDelta="1.0"/>
set>
我们此时需要的标签为 layoutAnimation
,它的属性如下表所示:
属性 | 描述 |
---|---|
delay | 子元素开始动画的时间延迟,它是一个百分比的取值,例如取值0.5时,假设子元素的入场动画周期为200ms,那么0.5就表示每个子元素的动画都需要延时100ms后再开启 |
animation | 为子元素指定的具体的入场动画 |
animationOrder | 一共有三个取值可选:normal、random 和 reverse,normal表示顺序显示,random表示随机显示,reverse表示逆序显示 |
interpolator | 插值器设置 |
在设置完成之后我们需要在相应的ViewGroup
中进行属性设置,这里以ListView
为例:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<ListView
android:id="@+id/list_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layoutAnimation="@anim/anim_list_view"/>
LinearLayout>
这样我们对ListView
子元素的进场动画就设置完成了,效果图如下所示:
接下来我们看到如何用Java代码的形式实现同样的效果。
使用Java代码的形式需要借助一个类:LayoutAnimationController,它就相当于XML中的animation-list标签,我们接下来直接看到代码:
Animation anim = AnimationUtils.loadAnimation(this, R.anim.anmi_demo);
LayoutAnimationController controller = new LayoutAnimationController(anim, 0.5f);
controller.setInterpolator(new LinearInterpolator());
controller.setOrder(LayoutAnimationController.ORDER_NORMAL);
mListView.setLayoutAnimation(controller);
最后实现的效果是一样的。
补间动画除了能为ViewGroup
设置动画外,还能为Activity
设置切换效果。这里需要借助Activity
中的:
void overridePendingTransition(int enterAnim, int exitAnim)
参数 | 含义 |
---|---|
enterAnim | Activity被打开时,所需动画的资源id |
exitAnim | Activity被暂停时,所需动画的资源id |
这个方法必须在 startActivity
或者 finish
方法之后调用才能生效,下面是示例代码:
Intent intent = new Intent(MainActivity.this, SecondActivity.class);
startActivity(intent);
overridePendingTransition(R.anim.fade_in, R.anim.fade_out);
@Override
public void finish(){
super.finish();
overridePendingTransition(R.anim.fade_in, R.anim.fade_out);
}
其中,fade_in.xml
和 fade_out.xml
的代码如下所示:
// res/anmi/fade_in.xml
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="300"
android:interpolator="@android:anim/accelerate_interpolator"
android:shareInterpolator="true">
<alpha
android:fromAlpha="0.0"
android:toAlpha="1.0"/>
set>
// res/anmi/fade_out.xml
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="300"
android:interpolator="@android:anim/accelerate_interpolator"
android:shareInterpolator="true">
<alpha
android:fromAlpha="1.0"
android:toAlpha="0.0"/>
set>
效果如下所示:
可以看到,通过调用 overridePendingTransition
方法,我们实现了简单的淡入、淡出效果。
除了Activity
之外,Fragment
之间的切换也是可以设置相应的动画的。Fragment
有两种,一种是v4包下的,另一种是普通的Fragment
,使用方式如下所示:
android.support.v4.app.Fragment
v4包下的Fragment
是用过FragmentTransaction#setCustomAnimations
来进行动画设置的,这个方法的定义如下所示:
public abstract FragmentTransaction setCustomAnimations(@AnimatorRes @AnimRes int enter,
@AnimatorRes @AnimRes int exit, @AnimatorRes @AnimRes int popEnter,
@AnimatorRes @AnimRes int popExit)
参数 | 含义 |
---|---|
enter | Fragment被添加或绑定时所呈现动画的资源id |
exit | Fragment被移除或解绑时所呈现动画的资源id |
popEnter | Fragment从栈中弹出时所呈现动画的资源id |
popExit | Fragment压入栈时所呈现动画的资源id |
为了便于区分这里笔者就直接通过不同的背景表示不同的Fragment
,这里我们采用平移动画切换Fragment
,Java代码如下所示:
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private Button prevButton;
private Button nextButton;
private FirstFragment firstFragment;
private SecondFragment secondFragment;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
prevButton = (Button)findViewById(R.id.prev_button);
nextButton = (Button)findViewById(R.id.next_button);
prevButton.setOnClickListener(this);
nextButton.setOnClickListener(this);
firstFragment = new FirstFragment();
secondFragment = new SecondFragment();
getSupportFragmentManager().beginTransaction().add(R.id.container, firstFragment).commit();
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.prev_button:
getSupportFragmentManager().beginTransaction()
.setCustomAnimations(R.anim.slide_left_in, R.anim.slide_right_out)
.replace(R.id.container, firstFragment)
.commit();
break;
case R.id.next_button:
getSupportFragmentManager().beginTransaction()
.setCustomAnimations(R.anim.slide_right_in, R.anim.slide_left_out)
.replace(R.id.container, secondFragment)
.commit();
break;
}
}
}
效果图如下所示:
android.app.Fragment
实际上普通Fragment
和v4包下的Fragment
使用非常相似,但是需要注意的是v4包下的Fragment只能采用补间动画,而普通Fragment则可以采用属性动画。由于使用非常相似,这里就不再赘述了。
帧动画其实也属于补间动画的一种,所以它的作用对象也是View。它按照顺序播放一组预先定义好的图片。系统提供了 AnimationDrawable
类来使用帧动画。它的实现同样有XML形式和Java代码的形式。
首先我们需要一个XML文件来定义一个AnimationDrawable
,该XML文件必须位于 res/drawable/ 文件夹下,如下所示:
// res/drawable/frame_anim.xml
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="false">
<item android:drawable="@drawable/anim_1" android:duration="200"/>
<item android:drawable="@drawable/anim_2" android:duration="200"/>
<item android:drawable="@drawable/anim_3" android:duration="200"/>
<item android:drawable="@drawable/anim_4" android:duration="200"/>
animation-list>
接下来在 Activity
中,我们通过一个 ImageView
来展示帧动画,代码如下所示:
ImageView imageView = (ImageView) findViewById(R.id.image_view);
imageView.setBackgroundResource(R.drawable.frame_anim);
AnimationDrawable drawable = (AnimationDrawable) imageView.getBackground();
drawable.start();
运行代码,效果图如下所示:
可以看到通过4张图片的逐帧播放,我们实现了帧动画的效果,接下来我们对帧动画的一些属性做简要的介绍。
animation-list为一个图片集合,它的内部放置的就是动画中每一帧的图片,它的属性如下:
属性 | 描述 |
---|---|
oneshot | 动画是否播放一次后就停止,false为无限循环播放 |
visiable | 用于表示当前动画是否可见,true表示可见,false表示不可见 |
item标签就是帧动画当中的每一帧,它有两个属性如下表所示:
属性 | 描述 |
---|---|
drawable | 用于指定当前帧的图片资源 |
duration | 当前帧在动画当中的持续时间 |
在用XML文件设置好了之后,就可以将该文件设置为UI的背景,然后通过 AnimationDrawable#start
方法来开启帧动画了。接下来我们看到Java代码的实现方式。
Java代码形式依然借助的是 AnimationDrawable 这个类,首先我们先通过下表来了解下这个类中的常用方法:
方法 | 描述 |
---|---|
start | 启动帧动画 |
addFrame | 向动画中添加帧,参数类型为Drawable,同时还要设置该帧的持续时间 |
stop | 停止帧动画 |
setOneshot | 设置动画是否播放一次后就停止,false为无限循环播放 |
setVisiable | 用于表示当前动画是否可见 |
借助上面的几个方法,一般情况下足够满足我们的需求了,接下来看到例子:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
AnimationDrawable animationDrawable = new AnimationDrawable();
initDrawable(animationDrawable);
ImageView imageView = (ImageView) findViewById(R.id.image_view);
imageView.setImageDrawable(animationDrawable);
animationDrawable.setOneShot(false);
animationDrawable.start();
}
private void initDrawable(AnimationDrawable animationDrawable) {
for (int i = 1; i <= 4; i++) {
int id = getResources().getIdentifier("anim_" +i, "drawable", getPackageName());
Drawable drawable = getResources().getDrawable(id);
animationDrawable.addFrame(drawable, 200);
}
}
}
《Android开发艺术探索》
希望这篇文章对你有所帮助~