一:属性动画简介

    Android 属性动画是API 11引入的,更在的版本可以使用Nineoldandroids来实现,Nineoldandroids官方网站http://nineoldandroids.com。    Nineoldandroids对属性动画做了兼容,在API 11之前的版本通过代理View动画来实现,因此在API 11之前的版本,本质还是View动画。Nineoldandroids的功能和系统原生的android,animation.*中类的功能用法完全一致。比较常用的几个动画类是:ValueAnimator,ObjectAnimator和AnimatorSet,其中ObjectAnimator继承自ValueAnimator,AnimatorSet是动画集合。    先看几个小列子:

1.

ObjectAnimator.ofInt(myObjec,"width",500).setDuration(5000).start();
上面这句代码的作用就是使用ObjectAnimator属性动画来让myObjec这个对象的width属性在5s变为500px。

2.

ObjectAnimator.ofFloat(myObjec,"translationY", -myObjec.getHeight()).start();
上面这段代码的作用就是改变对象myObjec的translationY属性,让其沿着Y轴向上平移一段距离(myObjec的高度)。

3.

AnimatorSet set = new AnimatorSet();        set.playTogether(            ObjectAnimator.ofFloat(myObjec, "alpha", 1,0.5f,1),            ObjectAnimator.ofFloat(myObjec, "rotationX", 0,180),            ObjectAnimator.ofFloat(myObjec, "rotationY", 0,270),            ObjectAnimator.ofFloat(myObjec, "translationY", 0,100),            ObjectAnimator.ofFloat(myObjec, "translationX", 0,100),            ObjectAnimator.ofFloat(myObjec, "rotation", 0,-270),            ObjectAnimator.ofFloat(myObjec, "scaleX", 1,1.2f),            ObjectAnimator.ofFloat(myObjec, "scaleY", 1,0.5f)            );        set.setDuration(5000).start();
上面代码的作用在5s内对View做了透明度,旋转,平移,缩放动画。从上面3个小例子不难看出,对一个view使用属性动画的代码还是比较容易理解的,当然,属性动画也可以通过XML来定义。需要定义在res/animator目录下面。其大概样式如下:
<?xml version="1.0" encoding="utf-8"?>  <set xmlns:android="http://schemas.android.com/apk/res/android" android:ordering="together" >      <objectAnimator android:duration="1000" android:propertyName="scaleX" android:valueFrom="1" android:valueTo="0.5" >      </objectAnimator>      <animator android:duration="1000" android:valueFrom="1" android:valueTo="0.5" >      </animator>  </set>

下面对标签说明下:
objectAnimator标签属性:

  • android:propertyName——表示属性动画的作用对象的属性名称;

  • android:duration——动画的时长;

  • android:valueFrom——表示属性的起始值;

  • android:valueTo——表示属性的结束值;

  • android:startOffset——动画的延迟时间;

  • android:repeatCount——动画的重复次数(默认值0,-1表示无限循环);

  • android:repeatMode——动画的重复模式(“repeat”表示连续重复,“reverse”表示逆向重复。);

  • android:valueType——表示android:propertyName所指属性的类型,有“intType”和“floatType”两个可选,分别表示属性的类型为整形和浮点型。(如果android:propertyName所指的属性为颜色,那么不需要指定android:valueType,系统会自动做处理)。

    使用XML定义的属性动画非常简单,代码大概如下:

 Animator anim = AnimatorInflater.loadAnimator(this, R.animator.scale);  anim.setTarget(mMv);  anim.start(); 

二:属性动画的监听器

属性动画提供了监听器用于监听动画的播放过程,主要有AnimatorUpdateListener和AnimatorListener。AnimatorListener的定义如下:
public static Interface AnimatorListener{        void onAnimationStart(Animator arg0);        void onAnimationRepeat(Animator arg0);        void onAnimationEnd(Animator arg0);        void onAnimationCancel(Animator arg0);        }

从定义中可以看出它可以监听动画的开始、结束、取消以及重复播放。使用起来也很简单因为系统提供了AnimatorListener的适配器。使用代码如下:

ValueAnimator valueAnimator = ValueAnimator.ofInt(1, 100);        valueAnimator.addListener(new AnimatorListener() {            @Override            public void onAnimationStart(Animator arg0) {                // TODO Auto-generated method stub            }            @Override            public void onAnimationRepeat(Animator arg0) {                // TODO Auto-generated method stub             }            @Override            public void onAnimationEnd(Animator arg0) {                // TODO Auto-generated method stub            }            @Override            public void onAnimationCancel(Animator arg0) {                // TODO Auto-generated method stub            }        });

三:高级使用

首先先分析下属性动画的原理:
属性动画要求动画作用的对象提供该属性的set和get方法,属性动画根据外界传递的初始值和最终值,以动画的效果多次去调用set方法,没次传递给set方法的值都不一样,确切说是随着时间的推移,所传递的值越来越接近最终的值。那么想要给object的属性A做动画,那么必须要满足以下两个条件:
(1)object必须提供setA方法,如果动画开始的时候没有传递初始值,那么还要提供getA方法,因为系统要调用getA方法去获取初始值。
(2)object的setA对属性A所做的改变必须能够通过某种方式反映出来,比如会带来UI的变换之类的否则动画无效果。
例如,想给一个Button增加一个动画,使他的宽在5s内增加到500px。从Button的源码可以知道Button继承自TextView其getWidth获取的是其宽度,但是其setWidth是TextView和其子类的专属方法,它的作用不是设置View的宽度,而是设置TextView的最大宽度和最小宽度。其实就是,TextView的宽度对应XML中的android:layout_width属性,而TextView还有一个属性android:width,这个属性就对应了setWidth方法。所以通过setWidth无法改变控件的宽度。官方文档对于这种情况给出了3中解决方法:

  • 1.给你的对象加上get和set方法,如有你有权限的话;
  • 2.用一个类来包装原始对象,间接的为其提供get和set方法;
  • 3.采用ValueAnimator监听动画过程,自己实现属性变化。

这里发现第一种方案可行性极低,因为我们通常是没有修改这些组件的权限的。下面用代码来实现以下第二中方案,先看代码:

 private void performAnimate(){        ViewWrapper wrapper = new ViewWrapper(button,button.getWidth());        ObjectAnimator.ofInt(wrapper,"width",500).setDuration(5000).start();    }    private static class ViewWrapper{        private View mTarget;        private int mWidth;        public ViewWrapper(View target,int width){            mTarget = target;            mWidth = width;        }        public int getWidth(){            //return mTarget.getLayoutParams().width;            return mWidth;        }        public void setWidth(int width){            mTarget.getLayoutParams().width = width;            mTarget.requestLayout();        }    }

从上面代码中不难看出我们首先是定义了一个类(ViewWrapper)来包装原始对象(Button),然后通过ViewWrapper的get和set方法来改变原对象的宽度。
对于第三种解决方案,同样先看代码:

private void performAnimate(final View target, final int start, final int end) {        ValueAnimator valueAnimator = ValueAnimator.ofInt(1, 100);        valueAnimator.addUpdateListener(new AnimatorUpdateListener() {            // 持有一个IntEvaluator对象,方便下面估值的时候使用            private IntEvaluator mEvaluator = new IntEvaluator();            @Override            public void onAnimationUpdate(ValueAnimator animator) {                // 获得当前动画的进度值,整型,1-100之间                int currentValue = (Integer) animator.getAnimatedValue();                Log.d(TAG, "current value: " + currentValue);                // 获得当前进度占整个动画过程的比例,浮点型,0-1之间                float fraction = animator.getAnimatedFraction();                // 直接调用整型估值器通过比例计算出宽度,然后再设给Button                target.getLayoutParams().width = mEvaluator.evaluate(fraction, start, end);                target.requestLayout();            }        });        valueAnimator.setDuration(5000).start();    }

上面的代码,会在5s内将一个数从1变到100,然后动画的每一帧都会调用onAnimationUpdate方法,在这个方法内可以获取当前的值和当前值所占的比例,就可以计算出此刻的宽度是多少,例如时间过了一半,那么当前值应该是50,比例是0.5,假设Button的初始宽度是100px,最终宽度是500px,那么此时的Button应该增加了(500-100)*0.5=200,那么当前的宽度应该是100+200=300。

到此属性动画大概讲述了一遍。

更多相关文章

  1. Android(安卓)Activity界面切换添加动画特效
  2. android实现字体闪烁动画的方法
  3. Android开发——Android搜索框架(二)
  4. Android:interpolator用法
  5. [Android] ACTION_GET_CONTENT与ACTION_PICK的区别
  6. 创建android逐帧动画的两种方式
  7. Android(安卓)Activity界面切换添加动画特效
  8. Android(安卓)UI系列 - 布局 - 目录
  9. android dialog 动画

随机推荐

  1. 一步一步学习androidNDK编程(java给c传递
  2. Android之几个dos小命令
  3. Unity与Android交互-案例演示接入穿山甲
  4. Android init 启动过程分析
  5. android intent和intent action大全
  6. 关于 Android(安卓)Studio 鼠标中键的一
  7. Android任务栈TaskStack
  8. Android(安卓)UI开发第二十篇——仿launc
  9. andriod线性布局部分用法
  10. android通过蓝牙连接打印机实现格式化打