Android动画初探

来源:互联网 发布:淘宝旺旺客服头像 编辑:程序博客网 时间:2024/06/05 20:09

前言

本文是我的第一篇博客,以读书笔记的形式记录学习的知识点,方便回顾。本文所记内容参考任玉刚老师所著《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做动画,必须满足两个条件:

  1. object必须提供abc的setAbc方法,如果没有传递初始值还要提供getAbc方法。
  2. setAbc执行后要有UI表现,否则看不到效果,动画也就没有意义了。

如果对任意属性做动画,官方建议的三种方法是:

  1. 如果可以加get和set方法的话,加上这些方法。
  2. 包装原来的view,提供get和set方法。
  3. 采用ValueAnimator,监听动画过程,自己根据状态去改变属性。

3.5 注意事项

  1. view动画只是改变view的显示效果,并不会改变view的真实状态。如果动画运行结束后view的一些动作执行失败,可以使用viw.clearAnimation()清除view的状态。
  2. 在Android3.0以前的系统上,不管是view动画还是属性动画,如果一个Button平移到了一个地方,在动画结束的地方点击button是没有反应的,只有在button原始位置点击才会响应。从Android3.0开始,属性动画的单击事件在动画的结束位置,而view动画仍然在原位置。

参考文献
【1】Android开发艺术探索. 任玉刚 著

原创粉丝点击