Android动画分析(一)

Android 动画种类

  • View Animation: 视图动画(Tween(补间)动画),只能被用来设置View的动画。

  • Drawable Animation: 帧动画(也叫 Frame 动画)其实可以划分到视图动画的类别,专门用来一个一个的显示 Drawable 的resources,就像放幻灯片一样。

  • Property Animation: 属性动画只对 Android 3.0(API 11)以上版本的Android 系统才有效,这种动画可以设置给任何 Object,包括那些还没有渲染到屏幕上的对象。这种动画是可扩展的,可以让你自定义任何类型和属性的动画。

1. View Animation 视图动画使用解析

    1. 视图动画特点

      • 视图动画可以在一个视图容器内执行一系列简单变换(平移、缩放、旋转、透明度)
      • 视图动画通过XML 或 Android 代码定义,建议使用 XML 文件定义,因为它更具可读性、可重用性。
    1. 动画属性
xml属性 java 方法 解释
android:detachWallpaper setDetachWallpaper(boolean) 是否在壁纸上运行
android:duration setDuration(long) 动画持续时间,毫秒为单位
android:fillAfter setFillAfter(boolean) 控件动画结束时是否保持动画最后的状态
android:fillBefore setFillBefore(boolean) 控件动画结束时是否还原到开始动画前的状态
android:fillEnabled setFillEnabled(boolean) 与android:fillBefore效果相同
android:interpolator setInterpolator(Interpolator) 设定插值器(指定的动画效果,譬如回弹等)
android:repeatCount setRepeatCount(int) 重复次数
android:repeatMode setRepeatMode(int) 重复类型有两个值,reverse表示倒序回放,restart表示从头播放
android:startOffset setStartOffset(long) 调用start函数之后等待开始运行的时间,单位为毫秒
android:zAdjustment setZAdjustment(int) 表示被设置动画的内容运行时在Z轴上的位置(top/bottom/normal),默认为normal

2-1 Alpha属性详解

xml属性 java方法 解释
android:fromAlpha AlphaAnimation(float fromAlpha, …) 动画开始的透明度(0.0到1.0,0.0是全透明,1.0是不透明)
android:toAlpha AlphaAnimation(…, float toAlpha) 动画结束的透明度,同上

2-2 Rotate属性详解

xml属性 java方法 解释
android:fromDegrees RotateAnimation(float fromDegrees, …) 旋转开始角度,正代表顺时针度数,负代表逆时针度数
android:toDegrees RotateAnimation(…, float toDegrees, …) 旋转结束角度,正代表顺时针度数,负代表逆时针度数
android:pivotX RotateAnimation(…, float pivotX, …) 缩放起点X坐标(数值、百分数、百分数p,譬如50表示以当前View左上角坐标加50px为初始点、50%表示以当前View的左上角加上当前View宽高的50%做为初始点、50%p表示以当前View的左上角加上父控件宽高的50%做为初始点)
android:pivotY RotateAnimation(…, float pivotY) 缩放起点Y坐标,同上规律

2-3 Scale属性详解

xml属性 java方法 解释
android:fromXScale ScaleAnimation(float fromX, …) 初始X轴缩放比例,1.0表示无变化
android:toXScale ScaleAnimation(…, float toX, …) 结束X轴缩放比例
android:fromYScale ScaleAnimation(…, float fromY, …) 初始Y轴缩放比例
android:toYScale ScaleAnimation(…, float toY, …) 结束Y轴缩放比例
android:pivotX ScaleAnimation(…, float pivotX, …) 缩放起点X轴坐标(数值、百分数、百分数p,譬如50表示以当前View左上角坐标加50px为初始点、50%表示以当前View的左上角加上当前View宽高的50%做为初始点、50%p表示以当前View的左上角加上父控件宽高的50%做为初始点)
android:pivotY ScaleAnimation(…, float pivotY) 缩放起点Y轴坐标,同上规律

2-4 Translate属性详解

xml属性 java方法 解释
android:fromXDelta TranslateAnimation(float fromXDelta, …) 起始点X轴坐标(数值、百分数、百分数p,譬如50表示以当前View左上角坐标加50px为初始点、50%表示以当前View的左上角加上当前View宽高的50%做为初始点、50%p表示以当前View的左上角加上父控件宽高的50%做为初始点)
android:toXDelta TranslateAnimation(…, float toXDelta, …) 结束点X轴坐标,同上规律
android:fromYDelta TranslateAnimation(…, float fromYDelta, …) 起始点Y轴从标,同上规律
android:toYDelta TranslateAnimation(…, float toYDelta) 结束点Y轴坐标,同上规律

2-5 AnimationSet详解
AnimationSet 继承自 Animation,是上面四种的组合容器管理类,没有自己特有的属性,他的属性也继承自 Animation 。所以特别注意,当我们对set标签使用 Animation 的属性时会对该标签下的所有子控件都产生影响。

2-6 View Animation 使用实例

  • xml 使用实例
    R.anim 目录下新建一个动画 xml文件。



    

    

    

    

java代码中使用:

ImageView image= (ImageView) findViewById(R.id.image);
Animation animation = AnimationUtils.loadAnimation(this, R.anim.view_animation);
image.startAnimation(animation);

2-7 Animation 比较实用的方法介绍:

Animation类的方法 解释
reset() 重置Animation的初始化
cancel() 取消Animation动画
start() 开始Animation动画
setAnimationListener(AnimationListener listener) 给当前Animation设置动画监听
hasStarted() 判断当前Animation是否开始
hasEnded() 判断当前Animation是否结束

2-8 View 中和视图动画相关的几个常用方法:

View类的常用动画操作方法 解释
startAnimation(Animation animation) 对当前 View 开始设置的Animation 动画
clearAnimation() 取消当前 View 在执行的 Animation 动画

2-9 视图动画需要注意的地方

  • 视图动画执行完之后并未改变 View 的真实布局属性值。

切记这一点,譬如我们在 Activity 中有一个 Button 在屏幕上方,我们设置了平移动画移动到屏幕下方,然后保持动画最后执行状态,看起来 Button
是在屏幕下方,但是这时点击屏幕下方动画执行之后的 Button,Button 是没有任何反应的,而点击原来屏幕上方原来是 Button 的地方却能响应点击Button的事件。这可以说是视图动画的一个 bug 。

2-10 视图动画插值器 Interpolator

  • Android 的各种插值器都实现了Interpolator接口,系统提供的插值器具体如下:
java类 xml id值 描述
AccelerateDecelerateInterpolator @android:anim/accelerate_decelerate_interpolator 动画始末速率较慢,中间加速
AccelerateInterpolator @android:anim/accelerate_interpolator 动画开始速率较慢,之后慢慢加速
AnticipateInterpolator @android:anim/anticipate_interpolator 开始的时候从后向前甩
AnticipateOvershootInterpolator @android:anim/anticipate_overshoot_interpolator 类似上面AnticipateInterpolator
BounceInterpolator @android:anim/bounce_interpolator 动画结束时弹起
CycleInterpolator @android:anim/cycle_interpolator 循环播放速率改变为正弦曲线
DecelerateInterpolator @android:anim/decelerate_interpolator 动画开始快然后慢
LinearInterpolator @android:anim/linear_interpolator 动画匀速改变
OvershootInterpolator @android:anim/overshoot_interpolator 向前弹出一定值之后回到原来位置
PathInterpolator 新增,定义路径坐标后按照路径坐标来跑。
  • 插值器使用方法:
    在 res/anim/ 目录下创建 my_Interpolator.xml 插值器文件。r如下:


在视图动画文件中引用自定义的或者系统提供的。




    

    

2. Drawable Animation(Drawable动画)使用详解

  • Drawable 动画其实就是 Frame 动画(帧动画),它允许你实现像播放幻灯片一样的效果,这种动画的实质其实是 Drawable,所以这种动画的XML 定义方式文件一般放在 res/drawable/ 目录下。

  • Drawable动画详细说明

    我们依旧可以使用 xml 或者 java 方式实现帧动画。但是依旧推荐使用xml,具体如下:

    必须是根节点,包含一个或者多个 元素,属性有:
    android:oneshot true 代表只执行一次,false 循环执行。
    类似一帧的动画资源。

    animation-list 的子项,包含属性如下:
    android:drawable:一个 frame 的 Drawable 资源。
    android:duration :一个 frame 显示多长时间。

举个栗子:




    

在 java 代码中调用:

ImageView rocketImage = (ImageView) findViewById(R.id.rocket_image);
rocketImage.setBackgroundResource(R.drawable.rocket_thrust);

rocketAnimation = (AnimationDrawable) rocketImage.getBackground();
rocketAnimation.start();

PS 注意的地方:
AnimationDrawable.start() 方法不能在 Activity 的 onCreate 方法中调运,因为 AnimationDrawable 还未完全附着到 window 上,所以最好的调运时机是 onWindowFocusChanged() 方法中。

3. Property Animation(属性动画)使用详解

上文说了视图动画最大的缺陷就是改变的只是显示,并不能显示响应事件。因此,Android 在 3.0 后推出 Property Animation(属性动画)来解决这个问题。

在属性动画中,使用的最多情况就是:AnimatorSetObjectAnimator 搭配。使用一个 ObjectAnimator 可以控制对象的一个属性,而使用多个 ObjectAnimator 就可以控制对象的多个属性,组合到 AnimatorSet 就组成了动画。

属性动画很重要的一点就是:属性动画通过调用属性的 getset 方法来真实控制一个View的属性值,因此可以响应事件。

3-1 ObjectAnimator

  • ObjectAnimator 是属性动画框架中最重要的实行类。创建一个 ObjectAnimator对象通过它的静态方法就可以了。

举个栗子

ObjectAnimator animator = ObjectAnimator.ofFloat(view,"translationX",300);
animator.setDuration(3000);
animator.start();

该静态方法的第一个参数是要操纵的View,第二个是要操纵的属性,第三个是一个可变的数组参数,也可以是一个值,一个值表示变化到此值

  • ObjectAnimator要操纵的属性必须具有 getset 方法,不然 ObjectAnimator 不会生效,常见的可以操纵的属性如下:
  1. translationXtranslationY:这两个属性作为一种增量来控制着 View 对象从它布局容器的左上角坐标偏移的位置。

  2. rotationrotationXrotationY:这三个属性控制 View 对象围绕支点进行 2D 和 3D 旋转。

  3. scaleXscaleY:控制 View 对象围绕它的支点进行 2D 缩放。

  4. pivotXpivotY:控制 View 对象的支点位置,围绕这个支点进行旋转和缩放变换处理。默认情况下,支点就是该 View 的中心点。

  5. xy:这两个属性是 View 对象在它的容器中的最终位置,是最初的左上角的 translationXtranslationY 值得累计和。

  6. alpha:View 的透明度。1 为不透明,0 为全透明。

3-2 PropertyValuesHolder
类似视图动画的 AnimationSet,在属性动画中,如果针对同一个对象的多个属性,要同时作用多种动画,可以使用 PropertyValuesHolder 来实现。

举个栗子

//平移的同时改变X,Y轴的缩放
PropertyValuesHolder pv1 = PropertyValuesHolder.ofFloat("translationX",300f);
PropertyValuesHolder pv2 = PropertyValuesHolder.ofFloat("scaleX",1f,0,1f);
PropertyValuesHolder pv3 = PropertyValuesHolder.ofFloat("scaleY",1f,0,1f);

ObjectAnimator.ofPropertyValuesHolder(imageView,pv1,pv2,pv3).setDuration(3000).start();

3-3 ValueAnimatior
ValueAnimatior 本身不提供任何动画效果,它更像一个数值发生器,用来产生具有一定规律的数字,从而让调用者控制动画的实现过程。

举个栗子

ValueAnimator animator = ValueAnimator.ofInt(0,1000);
animator.setTarget(imageView);
animator.setDuration(3000).start();
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                int value = (Integer)animation.getAnimatedValue();
               //使用这个 value 改变 View 的状态
                ViewGroup.LayoutParams layoutParams = imageView.getLayoutParams();
                layoutParams.height = value;
                imageView.setLayoutParams(layoutParams);
            }
        });

3-4 AnimationSet
AnimationSet 能对同一个对象的多个属性同时进行动画效果,还能实现精确的顺序控制,这点比 PropertyValuesHolder更灵活。

举个栗子

AnimatorSet animatorSet = new AnimatorSet();
ObjectAnimator animator = ObjectAnimator.ofFloat(imageView,"translationX",300);
ObjectAnimator animator1 = ObjectAnimator.ofFloat(imageView,"translationY",300);
animatorSet.setDuration(3000);
animatorSet.play(animator).after(animator1);
animatorSet.start();

在属性动画中,AnimationSet 通过 playTogether()(同时播放)、playSequentially()(顺序播放)、animatorSet.play().with()(同时播放)、animatorSet.play().before()(先 play()before())、animatorSet.play().after()(先 after()play() )这些方法来控制多个动画的协同工作方式,从而控制动画的播放顺序。

3-4 属性动画的事件监听
一个完整的动画具有 StartRepeatEndCancel 四个过程,我们可以很方便地监听其中一个或者几个事件。

举个栗子

ObjectAnimator animator = ObjectAnimator.ofFloat(imageView,"translationX",300);
animator.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) {

            }
        });

或者监听其中一个事件:

ObjectAnimator animator = ObjectAnimator.ofFloat(imageView,"translationX",300);

animator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                super.onAnimationEnd(animation);
            }
        });

3-5 在XML中使用属性动画
属性动画和视图动画一样,可以直接写在 XML 中,通过 AnimatorInflater.loadAnimator(context,res) 使用。

举个栗子
在 res 目录下新建一个 animator 目录(注意不能是 anim),然后写 XML 文件。




    

    
        
        
    
    

在代码中引用:

Animator animator = AnimatorInflater.loadAnimator(this,R.animator.object_animation);
animator.setTarget(imageView);
animator.start();

4. 总结

动画在安卓中使用的非常普遍,是当地使用动画能增添程序的趣味性。本篇介绍了安卓常见的动画的用法,下一篇介绍如何自定义动画。

参考资料

Android应用开发之所有动画使用详解

你可能感兴趣的:(Android动画分析(一))