前言
本文是我的第一篇博客,以读书笔记的形式记录学习的知识点,方便回顾。本文所记内容参考任玉刚老师所著《Android开发艺术探索》一书,若想更详细的了解Android动画知识,可以参考此书。
概述
Android动画分为三种:view动画、帧动画和属性动画。其实帧动画算是View动画的一种。view动画是通过对view进行一系列变换(缩放、旋转、透明度、平移)达到动画效果,帧动画是通过连续播放一系列图片达到动画效果,属性动画是通过对view的属性进行控制来达到动画效果。帧动画由于是加载多张图片,如果图片较大容易发生OOM(out of memory)。属性动画是API 11的新特性。
1. view动画
view动画对应Animation的四个子类:ScaleAnimation、RotateAnimation、AlphaAnimation、TranslateAnimation。这四种方式的动画既可以通过定义xml来实现、也可以通过代码中定义实现。view动画可以只有其中一个,也可以把多个view动画组合成一个复杂动画。
1.1 动画的参数
缩放动画:
- fromXScale——水平方向起始值
- toXScale———水平方向结束值
- fromYScale——垂直方向起始值
- toYscale———垂直方向结束值
- pivotX———–缩放轴点X坐标
- pivotY———–缩放轴点Y坐标
旋转动画:
- fromdegrees—-开始时角度
- toDegrees——-结束时角度
- pivotX———–缩放轴点X坐标
- pivotY———–缩放轴点Y坐标
透明度动画:
- fromAlpha——透明度起始值
- toAlpha———透明度结束值
平移动画:
- fromXdelta—–水平方向起始值
- toXdelta——–水平方向结束值
- fromYdelta—–垂直方向起始值
- toYdelta——–垂直方向结束值
共有属性:
- duration——动画持续时间
- fillAfter——-动画结束后view是否停留在结束位置
1.2 xml中定义动画
xml格式定义的动画一般在res/anim目录下。
下边示例view_anim.xml是定义了一个缩放动画和透明度动画的集合,该动画持续时间3000ms,集合中的动画和集合公用一个插值器(android:shareInterpolator=”true”) 。
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:shareInterpolator="true"
android:duration="3000">
<scale
android:fromXScale="30dp"
android:toXScale="60dp"
android:fromYScale="30dp"
android:toYScale="60dp" />
<alpha
android:fromAlpha="0"
android:toAlpha="1"/>
</set>
代码中运行该动画集:
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
Animation animation = AnimationUtils.loadAnimation(this,R.anim.view_anim);
fab.startAnimation(animation);
1.3 代码中定义动画
该动画是平移动画和旋转动画的集合。
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
AnimationSet animationSet = new AnimationSet(true);
TranslateAnimation translateAnimation = new TranslateAnimation(0,400,0,400);
RotateAnimation rotateAnimation = new RotateAnimation(0,180);
animationSet.addAnimation(translateAnimation);
animationSet.addAnimation(rotateAnimation);
animationSet.setDuration(3000);
fab.startAnimation(animationSet);
如果觉得这些view动画都不符合项目需求,也可以自定义view动画,只需继承Animation并重写initialize和applyTransfromation方法即可。
1.4 其它view动画
1.4.1 LayoutAnimation
LayoutAnimation可以作用于ViewGroup,这样子view就都有动画效果了。
参数:
- delay——————-动画延迟执行的时间
- animationOrder——-子view执行动画的顺序
- animation————–子view使用的动画
父view GridLayout使用layoutAnimation属性,该布局加载时会自动执行动画。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<GridLayout
android:id="@+id/grid_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layoutAnimation="@anim/layout_anim"
android:background="@color/colorPrimaryDark">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="ok"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="ok"/>
</GridLayout>
</LinearLayout>
LayoutAnimation文件,放在res/anim目录下,这个LayoutAnimation的子view使用的动画是view_anim.xml,由 android:animation=”@anim/view_anim”指定。该布局中的 android:delay=”0.6”表示动画延迟view_anim.xml动画时间(3000ms)的60%后执行。
<?xml version="1.0" encoding="utf-8"?>
<layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"
android:animationOrder="normal"
android:delay="0.6"
android:animation="@anim/view_anim">
</layoutAnimation>
如果代码中使用LayoutAnimation的话,需要定义LayoutAnimationController对象(需用子view动画初始化),然后ViewGroup对象调用setLayoutAnimation即可。
1.4.2 Activity 切换动画
Activity的切换动画一般是框架控制的,如果想自定义Activity的切换动画也是可以的。这就需要在startActivity之后或者finish之后调用overridePendingTransition(int enterAnim, int exitAnim)方法。当然,Fragment也可以通过设置相应的动画达到不同的切换效果。
2. 帧动画
帧动画是把一系列图片顺序播放,把这些图片定义在一个xml中,放在res/drawable目录下,帧动画定义了一个类AnimationDrawable。
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="true">
<item android:drawable="@drawable/ic_menu_camera" android:duration="1000"></item>
<item android:drawable="@drawable/ic_menu_gallery" android:duration="1000"></item>
<item android:drawable="@drawable/ic_menu_share" android:duration="1000"></item>
</animation-list>
代码中使用
Button mButton = (Button) findViewById(R.id.button_test);
mButton.setBackgroundResource(R.drawable.drawable_anim);
AnimationDrawable animationDrawable = (AnimationDrawable) mButton.getBackground();
animationDrawable.start();
3. 属性动画
属性动画是对对象的属性做动画,只要这个对象有某个属性,就可以对它做动画。属性动画的默认执行时间是300ms,帧刷新频率是10ms/帧,它是通过属性值的刷新达到动画的效果。与属性动画有关的常用类有:ObjectAnimator继承自ValueAnimator,而AnimatorSet是动画集合类。
3.1 属性动画示例
属性动画可以写在xml文件中,但这样书写对动画的控制不太方便,一般都是把属性动画写在代码中。
Button mButton = (Button) findViewById(R.id.button_test);
AnimatorSet animatorSet = new AnimatorSet();
ObjectAnimator rotationX = ObjectAnimator.ofFloat(mButton,"rotationX",0,180);
ObjectAnimator rotationY = ObjectAnimator.ofFloat(mButton,"rotationY",0,180);
ObjectAnimator scaleX = ObjectAnimator.ofFloat(mButton,"scaleX",1.0f,2.0f);
ObjectAnimator scaleY = ObjectAnimator.ofFloat(mButton,"scaleY",1.0f,2.0f);
ObjectAnimator alpha = ObjectAnimator.ofFloat(mButton,"alpha",1.0f,0f,1.0f);
animatorSet.playTogether(rotationX,rotationY,scaleX,scaleY,alpha);
animatorSet.setDuration(3000).start();
3.2 插值器和估值器
属性动画的状态改变是由插值器(Interpolator)和估值器(TypeEvaluator)共同决定的。插值器根据时间流逝的百分比计算出属性值改变的百分比,估值器根据属性改变的百分比计算出改变后的属性值。系统内置的有线性插值器(LinearInterpolator),加速减速插值器(AccelerateDecelerateInterpolator)、减速插值器(DecelerateInterpolator)等;系统内置的估值器有IntEvaluator、FloatEvaluator、ArgbEvaluator等。
3.3 监听器
属性动画的执行过程可以通过监听器来监听,相应的监听器有:AnimatorListener和AnimatorUpdateListener。
对alpha动画设置监听器:
ObjectAnimator alpha = ObjectAnimator.ofFloat(mButton,"alpha",1.0f,0f,1.0f);
alpha.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
});
AnimatorListener需要实现所有的四个方法,而如果你只想实现其中一个方法,其它方法不重写是不行的。好在系统给我们提供了另一个监听动画执行过程的类AnimatorListenerAdapter,用这个类实现监听就可以只写你想实现的类了。
ObjectAnimator alpha = ObjectAnimator.ofFloat(mButton,"alpha",1.0f,0f,1.0f);
alpha.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationCancel(Animator animation) {
super.onAnimationCancel(animation);
}
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
}
});
另一个监听类是AnimatorUpdateListener,它是在动画每次刷新帧时都会执行。
ObjectAnimator alpha = ObjectAnimator.ofFloat(mButton,"alpha",1.0f,0f,1.0f);
alpha.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
}
});
3.4 对任意属性做动画
属性动画的原理是:属性动画要求动画作用对象的属性提供get和set方法,动画执行过程中不断的调用set方法设置属性值。我门对object的属性abc做动画,必须满足两个条件:
- object必须提供abc的setAbc方法,如果没有传递初始值还要提供getAbc方法。
- setAbc执行后要有UI表现,否则看不到效果,动画也就没有意义了。
如果对任意属性做动画,官方建议的三种方法是:
- 如果可以加get和set方法的话,加上这些方法。
- 包装原来的view,提供get和set方法。
- 采用ValueAnimator,监听动画过程,自己根据状态去改变属性。
3.5 注意事项
- view动画只是改变view的显示效果,并不会改变view的真实状态。如果动画运行结束后view的一些动作执行失败,可以使用viw.clearAnimation()清除view的状态。
- 在Android3.0以前的系统上,不管是view动画还是属性动画,如果一个Button平移到了一个地方,在动画结束的地方点击button是没有反应的,只有在button原始位置点击才会响应。从Android3.0开始,属性动画的单击事件在动画的结束位置,而view动画仍然在原位置。
参考文献
【1】Android开发艺术探索. 任玉刚 著