动画Animations在App中的作用有多重要勿需多言,弹出式的PopupWindow、Tab切换、Loding等等。Android 3.0前,Android只支持两种动画模式:补间动画**Tween Animation和帧动画Frame animation;而在Android3.0时引入了一个新的动画系统:属性动画**property animation,三者在SDK中被称为property animation,view animation,drawable animation。 (可通过NineOldAndroids项目在3.0之前的系统中使用Property Animation。),接下来将分别总结整理下前两者以及相关类的关系的知识点。
所谓补间动画即开发者只需指定开始、结束的关键帧,动画变化的“中间帧”则由系统根据相关算法计算补齐。所以View Animation就是一系列View形状的变换(如大小的缩放,透明度的改变,位置的改变),View animation只能应用于View对象,而且只支持一部分属性,如支持缩放旋转而不支持背景颜色的改变,它只是改变了View对象绘制的位置,而没有改变View对象本身,(比如:你有一个ImageButton,坐标(100,100),Width:200,Height:50,而你有一个动画使其变为Width:100,Height:100,你会发现动画过程中触发按钮点击的区域仍是(100,100)-(300,150))。
补间动画的定义既可以用代码定义也可以用xml定义(建议用xml定义)。
可以给一个View同时设置多个动画,比如从透明至不透明的淡入效果,与从小到大的放大效果,这些动画既可以同时进行,也可以在一个完成之后开始另一个。
Interpolater是一个接口,是根据特定算法计算出整个动画所需要动态插入帧的密度和位置,简而言之就是Interpolater负责控制动画的变化速度,使得基本动画能以匀速、加速、减速、抛物线变化。在补间动画里的四大动画的节点里有可以设置interpolator 属性(当然我们也可以实现Interpolater接口定义自己的加速器)Android里提供了以下五种加速器:
Java Code | 应用的xml资源android:interpolator=”@android:anim/ | 作用 |
---|---|---|
LinearInterpolator | linear_interpolator” | 匀速改变 |
AccelerateInterpolator | accelerate_interpolator” | 在开始时改变较慢,然后开始加速 |
AccelerateDecelerateInterpolator | accelerate_decelerate_interpolator” | 在开始和结束的时较慢,中间加速 |
CycleInterpolator | cycle_interpolator” | 动画循环播放特定的次数,按正弦曲线改变 |
DecelerateInterpolator | decelerate_interpolator” | 在开始地方速度较快,然后开始减速 |
/*如果是在代码上设置共享一个interpolator,则可以在AnimationSet设置interpolator*/
AnimationSet animationSet = new AnimationSet(true);
animationSet.setInterpolator(new AccelerateInterpolator());
/*如果不设置共享一个interpolator则可以在每一个Animation对象上面设置interpolator*/
AnimationSet animationSet = new AnimationSet(false);
alphaAnimation.setInterpolator(new AccelerateInterpolator());
rotateAnimation.setInterpolator(new DecelerateInterpolator());
补间动画有四种变化分别对应四个子节点:alpha、scale、translate、rotate和一个重要的属性interpolator(如果在一个set标签中包含多个动画效果,如果想让这些动画效果共享一个Interpolator,则设置android:shareInterpolator=”true”)
<!-- 浮点型值( 0.0f表示完全透明,1.0f表示完全不透明): fromAlpha 属性为动画起始时透明度 toAlpha 属性为动画结束时透明度 长整型值( 时间以毫秒为单位): duration 属性为动画持续时间 -->
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >
<alpha android:duration="1000" android:fromAlpha="0.0" android:toAlpha="1.0" />
</set>
<!-- 浮点型值(0.0表示收缩到没有,1.0表示正常无伸缩, 值小于1.0表示收缩,值大于1.0表示放大) fromXScale 属性为动画起始时 X轴的缩放比 toXScale 属性为动画结束时 X轴的缩放比 (pivotX,pivotY)缩放中心,其中从0%-100%中取值 ,50%为物件的X或Y方向坐标上的中点位置 布尔型值: fillAfter 属性 当设置为true ,该动画转化在动画结束后被应用 -->
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >
<scale android:duration="1000" android:fillAfter="false" android:fromXScale="0.0" android:fromYScale="0.0" android:interpolator="@android:anim/accelerate_decelerate_interpolator" android:pivotX="50%" android:pivotY="50%" android:toXScale="1.4" android:toYScale="1.4" />
</set>
<!-- 整型值: fromXDelta 属性为动画起始时 X坐标上的位置 toXDelta 属性为动画结束时 X坐标上的位置 fromYDelta 属性为动画起始时 Y坐标上的位置 toYDelta 属性为动画结束时 Y坐标上的位置 Ps: 没有指定fromXType toXType fromYType toYType 时候, 默认是以自己为相对参照物 -->
<set xmlns:android="http://schemas.android.com/apk/res/android" >
<translate android:duration="2000" android:fromXDelta="30" android:fromYDelta="30" android:toXDelta="-80" android:toYDelta="300" />
</set>
<!-- 浮点数型值: fromDegrees 属性为动画起始时物件的角度 toDegrees 属性为动画结束时物件旋转的角度 可以大于360度 Ps: 当角度为负数——表示逆时针旋转, 当角度为正数——表示顺时针旋转 (负数from——to正数:顺时针旋转),(负数from——to负数:逆时针旋转) (正数from——to正数:顺时针旋转),(正数from——to负数:逆时针旋转) pivotX 属性为动画相对于物件的X坐标的开始位置 pivotY 属性为动画相对于物件的Y坐标的开始位置 其中从0%-100%中取值,50%为物件的X或Y方向坐标上的中点位置 -->
<set xmlns:android="http://schemas.android.com/apk/res/android" >
<rotate android:duration="4000" android:fromDegrees="0" android:interpolator="@android:anim/accelerate_decelerate_interpolator" android:pivotX="50%" android:pivotY="50%" android:toDegrees="+350" />
</set>
xml文件的根元素可以为,,,,interpolator元素或(表示以上几个动画的集合,set可以嵌套)。默认情况下,所有动画是同时进行的,可以通过startOffset属性设置各个动画的开始偏移(开始时间)来达到动画顺序播放的效果。xml动画文件的使用可以参见这篇博文。
我们都知道Android使用Animation代表抽像的动画基类,上文所说的四种动画效果和一个set节点也一定对应着四个继承了Animation的子类与一个动画集合类,即一种动画效果对应着一个class,关系如下:
xml | Java class |
---|---|
alpha | AlphaAnimation |
scale | ScaleAnimation |
translate | TranslateAnimation |
rotate | RotateAnimation |
set | AnimationSet |
AnimationSet animSets=new AnimationSet(true);
AlphaAnimation(float fromAlpha, float toAlpha);
ScaleAnimation(float fromX, float toX, float fromY, float toY);
ScaleAnimation scaleAnim=new ScaleAnimation(float fromX, float toX, float fromY, float toY, float pivotX, float pivotY)
ScaleAnimation(float fromX, float toX, float fromY, float toY, int pivotXType, float pivotXValue, int pivotYType, float pivotYValue)
RotateAnimation(float fromDegrees, float toDegrees)
RotateAnimation(float fromDegrees, float toDegrees, float pivotX, float pivotY)
RotateAnimation(float fromDegrees, float toDegrees, int pivotXType, float pivotXValue, int pivotYType, float pivotYValue)
TranslateAnimation(float fromXDelta, float toXDelta, float fromYDelta, float toYDelta);
TranslateAnimation(int fromXType, float fromXValue, int toXType, float toXValue, int fromYType, float fromYValue, int toYType, float toYValue)
RotateAnimation rotateAnimation = new RotateAnimation(0, 360,
Animation.RELATIVE_TO_SELF,0.5f,
Animation.RELATIVE_TO_SELF,0.5f);
rotateAnimation.setDuration(1000);
rotateAnimation.setInterpolator(new AccelerateDecelerateInterpolator());
void setRepeatCount(int repeatCount);
//设置监听
/** *onAnimationEnd(Animation animation) - 当动画结束时调用 *onAnimationRepeat(Animation animation) - 当动画重复时调用 *onAniamtionStart(Animation animation) - 当动画启动时调用 */
void setAnimationListener(Animation.AnimationListener listener)
void setStartOffset(long startOffset)
void setStartTime(long startTimeMillis)
void addAnimation(Animation a)
mImage.startAnimation(animationSet);
一个较完整的例子:
/*使用AnimationUtils装载动画xml配置文件*/
Animation animation = AnimationUtils.loadAnimation(
AnimationActivity.this, R.anim. doubleani);
/*启动动画集*/
image.startAnimation(animation);
AnimationSet animationSet = new AnimationSet(true);
AlphaAnimation alphaAnimation = new AlphaAnimation(1, 0);
RotateAnimation rotateAnimation = new RotateAnimation(0, 360,
Animation.RELATIVE_TO_SELF,0.5f,
Animation.RELATIVE_TO_SELF,0.5f);
rotateAnimation.setDuration(3000);
animationSet.addAnimation(rotateAnimation);//添加动画至集合
animationSet.addAnimation(alphaAnimation);
mImage.startAnimation(animationSet);//启动动画集
帧动画是一帧一帧的格式显示动画效果。创建帧动画我们除了通过在xml中用animation-list 作为根节点,item定义每一帧要显示的图片之外,也可以用Java代码的形式来创建帧动画。Drawable和xml帧动画可参见Android入门——Drawable与对应的资源xml的应用
AnimationDrawable animDrawble=new AnimationDrawable();
animDrawble.addFrame(Drawable drawable)
animDrawble.start();
animDrawble.stop();
/*加载xml帧动画文件*/
ImageView img =(ImageView)findViewById(R.id.spinning_wheel_image);
img.setBackgroundResource(R.drawable.anim_maindraw);
AnimationDrawable frameAnimation = (AnimationDrawable) img.getBackground();
frameAnimation.start();
在start()之前要先stop(),不然在第一次动画之后会停在最后一帧,导致动画只触发一次;还有官方建议不要在onCreate中调用start,因为AnimationDrawable还没有完全跟Window相关联,如果想要界面显示时就开始动画的话,可以在onWindowFoucsChanged()中调用start()。
LayoutAnimationsController可以用于实现使多个控件按顺序一个一个的显示。
<!-- anim_layoutanim_main_list.xml android:delay - 动画间隔时间;子类动画时间间隔 (延迟)百分数如60% 也可以是一个浮点数 如“1.2”等 android:animationOrder - 动画执行的循序(normal:顺序,random:随机,reverse:反向显示) android:animation – 引用动画效果文件 -->
<layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android" android:delay="0.6" android:animationOrder="normal" android:animation="@anim/anim_main_list"/>
<!--anim_main_list.xml-->
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@android:anim/accelerate_interpolator" android:shareInterpolator="true">
<alpha android:fromAlpha="0.0" android:toAlpha="1.0" android:duration="2000"/>
</set>
<!--activity_main.xml-->
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" >
<ListView android:id="@id/android:list" android:layout_width="fill_parent" android:layout_height="wrap_content" android:scrollbars="vertical" android:layoutAnimation="@anim/anim_layoutanim_main_list"/>
</LinearLayout>
应用在layout节点下就设置对应的android:layoutAnimation属性
<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layoutAnimation="@anim/anim_layoutanim_main_list"
>
/*创建一个Animation对象:可以通过装载xml文件,或者是直接使用Animation的构造方法创建Animation对象*/
Animation animation = (Animation) AnimationUtils.loadAnimation(
AnimationActivity.this, R.anim.anim_main_list);
/*创建LayoutAnimationController对象*/
LayoutAnimationController controller = new LayoutAnimationController(animation);
/*设置控件的显示顺序以及延迟时间*/
controller.setOrder(LayoutAnimationController.ORDER_NORMAL);
controller.setDelay(0.6f);
/*为ViewGrop(ListView)设置LayoutAnimationController属性*/
listView.setLayoutAnimation(controller);