android动画及用法

android中三种动画:view animation, drawable animation, property animation(3.0以后引入).
官方链接:http://developer.android.com/guide/topics/graphics/overview.html

1.view animation/tweened animation 补间动画

淡入淡出、缩放、平移、旋转四种
给出两个关键帧,通过一些算法将给定属性值在给定的时间内在两个关键帧间渐变。
View animation只能应用于View对象,而且只支持一部分属性,如支持缩放旋转而不支持背景颜色的改变。
缺点:

  • 只能作用于view对象
  • 只支持alpha,scale,translate,rotate,不支持背景颜色改变
  • 只是改变了View的显示效果而已(只是改变了view的绘制位置,没有改变view对象本身),而不会真正去改变View的属性

现在屏幕的左上角有一个按钮,然后我们通过补间动画将它移动到了屏幕的右下角,现在你可以去尝试点击一下这个按钮,点击事件是绝对不会触发的,因为实际上这个按钮还是停留在屏幕的左上角,只不过补间动画将这个按钮绘制到了屏幕的右下角而已。

可以通过设置interpolator属性改变动画渐变的方式,如AccelerateInterpolator,开始时慢,然后逐渐加快。默认为AccelerateDecelerateInterpolator。
xml中放在res/anim目录下

2.drawable Animation/frame Animation 帧动画

逐帧动画的工作原理很简单,其实就是将一个完整的动画拆分成一张张单独的图片,然后再将它们连贯起来进行播放,类似于动画片的工作原理。

<animation-list xmlns:android="http://schemas.android.com/apk/res/android" android:oneshot="true">    <item android:drawable="@drawable/rocket_thrust1" android:duration="200" />    <item android:drawable="@drawable/rocket_thrust2" android:duration="200" />    <item android:drawable="@drawable/rocket_thrust3" android:duration="200" /></animation-list>

使用注意:SDK中提到的,不要在onCreate中调用start,因为AnimationDrawable还没有完全跟Window相关联,如果想要界面显示时就开始动画的话,可以在onWindowFoucsChanged()中调用start()。

3.property animation

在Property Animation中,可以对动画应用以下属性:

  • Duration:动画的持续时间
  • TimeInterpolation:属性值的计算方式,如先快后慢
  • TypeEvaluator:根据属性的开始、结束值与TimeInterpolation计算出的因子计算出当前时间的属性值
  • Repeat Count and behavoir:重复次数与方式,如播放3次、5次、无限循环,可以此动画一直重复,或播放完时再反向播放
  • Animation sets:动画集合,即可以同时对一个对象应用几个动画,这些动画可以同时播放也可以对不同动画设置不同开始偏移
  • Frame refreash delay:多少时间刷新一次,即每隔多少时间计算一次属性值,默认为10ms,最终刷新时间还受系统进程调度与硬件的影响

ValueAnimator

ValueAnimator表示一个动画,包含动画的开始值,结束值,持续时间等属性。
ValueAnimator封装了一个TimeInterpolator,TimeInterpolator定义了属性值在开始值与结束值之间的插值方法。
ValueAnimator还封装了一个TypeEvaluator,根据开始、结束值与TimeInterpolator计算得到的值计算出属性值。
ValueAnimator根据动画已进行的时间跟动画总时间(duration)的比计算出一个时间因子(0~1),然后根据TimeInterpolator计算出另一个因子,最后TypeAnimator通过这个因子计算出属性值

//几个float值平滑过渡ValueAnimator anim = ValueAnimator.ofFloat(0f, 5f, 3f, 10f);anim.setDuration(300);anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {    @Override    public void onAnimationUpdate(ValueAnimator animation) {        float currentValue = (Float) animation.getAnimatedValue();        Log.d("TAG", "cuurent value is " + currentValue);    }});anim.setStartDelay(1000);anim.setTarget(null);anim.setRepeatCount(5);//anim.setInterpolator(value);//anim.setEvaluator(value);//anim.setFrameDelay(frameDelay);anim.start();

ObjectAnimator extends ValueAnimator

ValueAnimator只不过是对值进行了一个平滑的动画过渡,但我们实际使用到这种功能的场景好像并不多

float curTranslationX = textview.getTranslationX();ObjectAnimator oa = ObjectAnimator.ofFloat(image1, "translationX", curTranslationX, -40, curTranslationX);//ObjectAnimator animator = ObjectAnimator.ofFloat(textview, "alpha", 1f, 0f, 1f); oa.setDuration(1000);oa.addListener(new AnimatorListener() {    @Override    public void onAnimationStart(Animator animation) {    }    @Override    public void onAnimationRepeat(Animator animation) {}    @Override    public void onAnimationEnd(Animator animation) {}    @Override    public void onAnimationCancel(Animator animation) {}});oa.start();

动画回调太多了,不想监听那么多事件,使用AnimatorListenerAdapter

oa.addListener(new AnimatorListenerAdapter() {    public void onAnimationRepeat(Animator animation) {    }});

TimeInterplator

  • AccelerateInterpolator      加速,开始时慢中间加速
  • DecelerateInterpolator       减速,开始时快然后减速
  • AccelerateDecelerateInterolator  先加速后减速,开始结束时慢,中间加速
  • AnticipateInterpolator       反向 ,先向相反方向改变一段再加速播放
  • AnticipateOvershootInterpolator  反向加回弹,先向相反方向改变,再加速播放,会超出目的值然后缓慢移动至目的值
  • BounceInterpolator        跳跃,快到目的值时值会跳跃,如目的值100,后面的值可能依次为85,77,70,80,90,100
  • CycleIinterpolator         循环,动画循环一定次数,值的改变为一正弦函数:Math.sin(2 * mCycles * Math.PI * input)
  • LinearInterpolator         线性,线性均匀改变
  • OvershottInterpolator       回弹,最后超出目的值然后缓慢改变到目的值

当Layout改变时应用动画

ViewGroup中的子元素可以通过setVisibility使其Visible、Invisible或Gone,当有子元素可见性改变时(VISIBLE、GONE),可以向其应用动画,通过LayoutTransition类应用此类动画:

transition.setAnimator(LayoutTransition.DISAPPEARING, customDisappearingAnim);

通过setAnimator应用动画,第一个参数表示应用的情境,可以以下4种类型:

  • APPEARING        当一个元素在其父元素中变为Visible时对这个元素应用动画
  • CHANGE_APPEARING    当一个元素在其父元素中变为Visible时,因系统要重新布局有一些元素需要移动,对这些要移动的元素应用动画
  • DISAPPEARING       当一个元素在其父元素中变为GONE时对其应用动画
  • CHANGE_DISAPPEARING  当一个元素在其父元素中变为GONE时,因系统要重新布局有一些元素需要移动,这些要移动的元素应用动画.

第二个参数为一Animator。

mTransitioner.setStagger(LayoutTransition.CHANGE_APPEARING, 30);

此函数设置动画延迟时间,参数分别为类型与时间。

组合动画

实现组合动画功能主要需要借助AnimatorSet这个类,这个类提供了一个play()方法,如果我们向这个方法中传入一个Animator对象(ValueAnimator或ObjectAnimator)将会返回一个AnimatorSet.Builder的实例,AnimatorSet.Builder中包括以下四个方法:

  • after(Animator anim) 将现有动画插入到传入的动画之后执行
  • after(long delay) 将现有动画延迟指定毫秒后执行
  • before(Animator anim) 将现有动画插入到传入的动画之前执行
  • with(Animator anim) 将现有动画和传入的动画同时执行
//image3先从屏幕外移动进屏幕,然后开始旋转360度,旋转的同时进行淡入淡出操作ObjectAnimator moveIn = ObjectAnimator.ofFloat(image3, "translationX", -500f, 0f);  ObjectAnimator rotate = ObjectAnimator.ofFloat(image3, "rotation", 0f, 360f);  ObjectAnimator fadeInOut = ObjectAnimator.ofFloat(image3, "alpha", 1f, 0f, 1f);  AnimatorSet animSet = new AnimatorSet();  animSet.play(rotate).with(fadeInOut).after(moveIn);  animSet.setDuration(5000);  animSet.start(); 

使用XML写动画

使用xml写动画没有代码快,但是可以重用性好。
目录:res/animator文件夹
共三种标签:

  • <animator> 对应代码中的ValueAnimator
  • <objectAnimator> 对应代码中的ObjectAnimator
  • <set> 对应代码中的AnimatorSet

从0到100平滑过渡的动画:

<animator xmlns:android="http://schemas.android.com/apk/res/android" android:valueFrom="0" android:valueTo="100" android:valueType="intType"/> 

视图的alpha属性从1变成0:

<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android" android:valueFrom="1" android:valueTo="0" android:valueType="floatType" android:propertyName="alpha"/> 

将一个视图先从屏幕外移动进屏幕,然后开始旋转360度,旋转的同时进行淡入淡出操作:

<set xmlns:android="http://schemas.android.com/apk/res/android" android:ordering="sequentially" >      <objectAnimator android:duration="2000" android:propertyName="translationX" android:valueFrom="-500" android:valueTo="0" android:valueType="floatType" >      </objectAnimator>      <set android:ordering="together" >          <objectAnimator android:duration="3000" android:propertyName="rotation" android:valueFrom="0" android:valueTo="360" android:valueType="floatType" >          </objectAnimator>          <set android:ordering="sequentially" >              <objectAnimator android:duration="1500" android:propertyName="alpha" android:valueFrom="1" android:valueTo="0" android:valueType="floatType" >              </objectAnimator>              <objectAnimator android:duration="1500" android:propertyName="alpha" android:valueFrom="0" android:valueTo="1" android:valueType="floatType" >              </objectAnimator>          </set>      </set>  </set>  

ValueAnimator的高级用法

搞清楚什么是TypeEvaluator:
ValueAnimator.ofFloat()方法就是实现了初始值与结束值之间的平滑过度,它内置了一个FloatEvaluator:

public class FloatEvaluator implements TypeEvaluator {      public Object evaluate(float fraction, Object startValue, Object endValue) {          float startFloat = ((Number) startValue).floatValue();          return startFloat + fraction * (((Number) endValue).floatValue() - startFloat);      }  }

自定义一个View,里面使用ValueAnimator.ofObject来定义动画:

public class MyAnimView extends View {      public static final float RADIUS = 50f;      private MyPoint currentPoint;      private Paint mPaint;      public MyAnimView(Context context, AttributeSet attrs) {          super(context, attrs);          mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);          mPaint.setColor(Color.BLUE);      }      @Override      protected void onDraw(Canvas canvas) {          if (currentPoint == null) {              currentPoint = new MyPoint(RADIUS, RADIUS);            drawCircle(canvas);              startAnimation();          } else {              drawCircle(canvas);          }      }      private void drawCircle(Canvas canvas) {          float x = currentPoint.getX();          float y = currentPoint.getY();          canvas.drawCircle(x, y, RADIUS, mPaint);      }      private void startAnimation() {          MyPoint startPoint = new MyPoint(RADIUS, RADIUS);        MyPoint endPoint = new MyPoint(getWidth() - RADIUS, getHeight() - RADIUS);          ValueAnimator anim = ValueAnimator.ofObject(new PointEvaluator(), startPoint, endPoint);          anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {              @Override              public void onAnimationUpdate(ValueAnimator animation) {                  currentPoint = (MyPoint) animation.getAnimatedValue();//PointEvaluator计算好的                invalidate();            }          });          anim.setDuration(5000);          anim.start();      }  }

MyPoint:

public class MyPoint {    private float x;    private float y;    public MyPoint(float x, float y) {        this.x = x;        this.y = y;    }    public float getX() {        return x;    }    public float getY() {        return y;    }}

PointEvaluator:

public class PointEvaluator implements TypeEvaluator<MyPoint> {    @Override    public MyPoint evaluate(float fraction, MyPoint startValue, MyPoint endValue) {        float x = startValue.getX() + fraction * (endValue.getX() - startValue.getX());        float y = startValue.getY() + fraction * (endValue.getY() - startValue.getY());        MyPoint point = new MyPoint(x, y);        return point;    }}

效果:

再增加ObjectAnimator,两个动画playwith,先看效果:

MyAnimView增加setColor方法:

...private String color;  public String getColor() {      return color;  }public void setColor(String color) {      this.color = color;      mPaint.setColor(Color.parseColor(color));      invalidate();  }  

修改startAnimation,使用AnimatorSet将两个动画一起播放:

private void startAnimation() {      Point startPoint = new Point(RADIUS, RADIUS);      Point endPoint = new Point(getWidth() - RADIUS, getHeight() - RADIUS);      ValueAnimator anim = ValueAnimator.ofObject(new PointEvaluator(), startPoint, endPoint);      anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {          @Override          public void onAnimationUpdate(ValueAnimator animation) {              currentPoint = (Point) animation.getAnimatedValue();              invalidate();          }      });      ObjectAnimator anim2 = ObjectAnimator.ofObject(this, "color", new ColorEvaluator(),               "#0000FF", "#FF0000");      AnimatorSet animSet = new AnimatorSet();      animSet.play(anim).with(anim2);      animSet.setDuration(5000);      animSet.start();  }  

ColorEvaluator.java:

//计算一个颜色字符串然后返回public class ColorEvaluator implements TypeEvaluator {      private int mCurrentRed = -1;      private int mCurrentGreen = -1;      private int mCurrentBlue = -1;      @Override      public Object evaluate(float fraction, Object startValue, Object endValue) {          String startColor = (String) startValue;          String endColor = (String) endValue;          int startRed = Integer.parseInt(startColor.substring(1, 3), 16);          int startGreen = Integer.parseInt(startColor.substring(3, 5), 16);          int startBlue = Integer.parseInt(startColor.substring(5, 7), 16);          int endRed = Integer.parseInt(endColor.substring(1, 3), 16);          int endGreen = Integer.parseInt(endColor.substring(3, 5), 16);          int endBlue = Integer.parseInt(endColor.substring(5, 7), 16);          // 初始化颜色的值         if (mCurrentRed == -1) {              mCurrentRed = startRed;          }          if (mCurrentGreen == -1) {              mCurrentGreen = startGreen;          }          if (mCurrentBlue == -1) {              mCurrentBlue = startBlue;          }          // 计算初始颜色和结束颜色之间的差值         int redDiff = Math.abs(startRed - endRed);          int greenDiff = Math.abs(startGreen - endGreen);          int blueDiff = Math.abs(startBlue - endBlue);          int colorDiff = redDiff + greenDiff + blueDiff;          if (mCurrentRed != endRed) {              mCurrentRed = getCurrentColor(startRed, endRed, colorDiff, 0,                      fraction);          } else if (mCurrentGreen != endGreen) {              mCurrentGreen = getCurrentColor(startGreen, endGreen, colorDiff,                      redDiff, fraction);          } else if (mCurrentBlue != endBlue) {              mCurrentBlue = getCurrentColor(startBlue, endBlue, colorDiff,                      redDiff + greenDiff, fraction);          }          // 将计算出的当前颜色的值组装返回         String currentColor = "#" + getHexString(mCurrentRed)                  + getHexString(mCurrentGreen) + getHexString(mCurrentBlue);          return currentColor;      }      /** * 根据fraction值来计算当前的颜色。 */      private int getCurrentColor(int startColor, int endColor, int colorDiff,              int offset, float fraction) {          int currentColor;          if (startColor > endColor) {              currentColor = (int) (startColor - (fraction * colorDiff - offset));              if (currentColor < endColor) {                  currentColor = endColor;              }          } else {              currentColor = (int) (startColor + (fraction * colorDiff - offset));              if (currentColor > endColor) {                  currentColor = endColor;              }          }          return currentColor;      }      /** * 将10进制颜色值转换成16进制。 */      private String getHexString(int value) {          String hexString = Integer.toHexString(value);          if (hexString.length() == 1) {              hexString = "0" + hexString;          }          return hexString;      }  }  

Intorplator:

第一个动画增加以下:

anim.setInterpolator(new BounceInterpolator());

设置TimeInterpolator,这个接口要实现float getInterpolation(float input);
时间因子input(0~1):已进行的时间跟动画总时间的比,0代表开始,1代表结束

ViewPropertyAnimator

它是3.1系统中增加的一个功能。是为了方便使用ObjctAnimator来操作View,代码更加人性化。

参考:
http://developer.android.com/guide/topics/graphics/overview.html
http://www.cnblogs.com/angeldevil/archive/2011/12/02/2271096.html
http://blog.csdn.net/guolin_blog/article/details/43536355

更多相关文章

  1. android 动画使用
  2. 详解Android中的Menu菜单键
  3. (转载)Android一些不常见的API及一些其他注意事项
  4. Android加载动画库
  5. Android(安卓)动画学习笔记
  6. android activity之间共享数据(application context)
  7. Android(安卓)动画学习
  8. Android O CarService
  9. Android 开机动画源码分析

随机推荐

  1. 数组元素排序之冒泡排序
  2. 如何格式化不属于任何段的损坏块 (文档 I
  3. 30岁还可以转行做运维吗
  4. web打印动态分页、预览。内容满了,自动换
  5. 密码错误频繁登录引发的“library cache
  6. MVCC(Multi-Version Concurrent Control,多
  7. 查看服务器性能工具
  8. linux运维的发展方向
  9. rhel7搭建可用实验环境
  10. CAP定理