Android View动画框架 Animation框架定义了透明度、旋转、缩放和位移几种常见的动画,控制的是整个view,原理是每次绘制视图时view所在的viewgroup中的drawchild函数获取该view的animation的transformation值,然后调用canvas.concat(transformToApply.getMatrix()),通过矩阵换算完成动画帧,如果动画没有完成,就继续调用invalidate()函数,启动下次绘制来驱动动画,从而完成整个动画的绘制。
视图动画 视图动画使用简单,效果丰富,提供了四种方式,并提供了animationset动画集合,混合使用多种动画。
透明度动画
为视图增加透明度的变换动画。
1 2 3 AlphaAnimation aa = new AlphaAnimation(0, 1); aa.setDuration(1000); view.startAnimation(aa);
旋转动画
为视图增加旋转的变换动画。
1 2 3 RotateAnimation ra = new RotateAnimation(0, 360, 100, 100); ra.setDuration(1000); view.startAnimation(ra);
也可以以自身为旋转中心
1 2 3 RotateAnimation ra = new RotateAnimation(0, 360, RotateAnimation.RELATIVE_TO_SELF, 0.5F, RotateAnimation.RELATIVE_TO_SELF, 0.5F);
位移动画
为视图移动时增加位移动画
1 2 3 TranslationAnimation ta = new TranslationAnimation(0, 200, 0, 300); ta.setDuration(1000); view.startAnimation(ta);
缩放动画
为视图的缩放增加动画效果
1 2 3 ScaleAnimation sa = new ScaleAnimation(0, 2, 0, 2); sa.setDuration(1000); view.startAnimation(sa);
也可以以自身为缩放中心
1 2 3 4 5 ScaleAnimation sa = new ScaleAnimation(0, 1, 0, 1, Animation.RELATIVE_TO_SELF, 0.5F, Animation.RELATIVE_TO_SELF, 0.5F); sa.setDuration(1000); view.startAnimation(sa);
动画合集
使用AnimationSet,可以将动画以组合的形式展现出来。
1 2 3 4 5 6 7 8 9 10 11 12 AnimationSet as = new AnimationSet(true); as.setDuration(1000); AlphaAnimation aa = new AlphaAnimation(0, 1); aa.setDuration(1000); as.addAnimation(aa); TranslateAnimation ta = new TranslateAnimation(0, 100, 0, 200); ta.setDuration(1000); as.addAnimation(ta); view.startAnimation(as);
属性动画 由于视图动画改变的只是view的显示,而并不是view的属性,会导致一些问题。
ObjectAnimator
ObjectAnimator是属性动画框架中最重要的实体类,创建一个ObjectAnimator只需要通过他的静态工厂类直接返回一个ObjectAnimator对象。参数包括一个对象和对象的属性名字,但这个属性必须有get和set函数,内部会通过java反射机制来调用set函数修改对象属性值。
1 2 3 4 ObjectAnimator animator = ObjectAnimator.ofFloat( view, "translationX", 300); animator.setDuration(300); animator.start();
第一个参数为要操纵的view,第二个参数为要操纵的属性,第三个三处为一个可变数组参数,需要传进该属性变化的一个取值过程。
如果需要操控一个值,但是该值没有setget方法,可以使用wrapper方法来进行一层包装。
1 2 3 4 5 6 7 8 9 10 11 12 13 private static class WrapperView{ private View mTarget; public WrapperView(View target){ mTarget = target; } public int getWidth(){ return mTarget.getLayoutParams().width; } public void setWidth(int width){ mTarget.getLayoutParams().width = width; mTarget.requestLayout(); } }
1 2 ViewWrapper wrapper = new ViewWrapper(mButton); ObjectAnimator.ofInt(wrapper, "width", 500).setDuration(5000).start();
PropertyValuesHolder
类似视图动画中的AnimationSet,在属性动画中,如果针对同一个对象的多个属性,要同时作用多种动画,可以使用PropertyValuesHolder来实现。
1 2 3 4 PropertyValuesHolder pvh1 = PropertyValuesHolder.ofFloat("translationX", 300f); PropertyValuesHolder pvh2 = PropertyValuesHolder.ofFloat("scaleX", 1f, 0, 1f); PropertyValuesHolder pvh3 = PropertyValuesHolder.ofFloat("scaleY", 1f, 0, 1f); ObjectAnimator.ofPropertyValuesHolder(view, pvh1, pvh2, pvh3).setDuration(1000).start();
ValueAnimator
ValueAnimator本身不提供任何动画效果,它更像一个数值发生器,用来产生具有一定规律的数字,从而让调用者来控制动画的实现过程。
1 2 3 4 5 6 7 8 9 10 ValueAnimator animator = ValueAnimator.ofFloat(0, 100); animator.setTarget(view); animator.setDuration(1000).start(); animator.addUpdateListener(new AnimatorUpdateListener(){ @Override public void onAnimationUpdate(ValueAnimator animation){ Float value = (Float) animation.getAnimatedValue(); //TODO use the value } })
动画事件的监听
一个完整的动画具有Start, Repeat, End, Cancel四个过程,对动画使用AddListener()即可很方便的监听到这四个事件。
AnimatorSet
对于一个属性同时作用多个属性动画效果吗可以使用之前的PrpertyValuesHolder实现,而AnimatorSet不仅可以实现效果,还能控制顺序。
1 2 3 4 5 6 7 ObjectAnimator animator1 = ObjectAnimator.ofFloat(view, "translationX", 300f); ObjectAnimator animator2 = ObjectAnimator.ofFloat(view, "scaleX", 1f, 0f, 1f); ObjectAnimator animator3 = ObjectAnimator.ofFloat(view, "scaleY", 1f, 0f, 1f); AnimatorSet set = new AnimatorSet(); set.setDuration(1000); set.playTogether(animator1, animator2, animator3); set.start();
使用playTogether(), playSequentially(), animSet.play().with(),before(),after()来控制多个动画的协同工作方式。
在xml中使用属性动画
1 2 3 4 5 6 7 8 <?xml version="1.0" encoding="utf-8"?> <objectAnimator xmlns:Android="http://schemas.Android.com/apk/res/Android" Android:duration="1000" Android:propertyName="scaleX" Android:valueFrom="1.0" Android:valueTo="2.0" Android:valueType="floatType"> </objectAnimator>
1 2 3 4 5 public void scaleX(View view){ Animator anim = AnimatorInflater.loadAnimator(this, R.animator.scalex); anim.setTarget(mMv); anim.start(); }
View的animate方法
animate方法是属性动画的一种简写方式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 view.animate() .alpha(0) .y(300) .setDuration(300) .withStartAction(new Runnable(){ @Override public void run(){ } }) .withEndAction(new Runnable(){ @Override public void run(){ } }).start();
布局动画 布局动画是指在ViewGroup上,给ViewGroup添加view时添加一个动画过度效果。
最简单的布局动画,只需要添加
1 Android:animateLayoutChanges="true"
另外,还可以通过使用LayoutAnimationController类来自定义一个子View的过度效果。
1 2 3 4 5 6 7 8 9 LinearLayout ll = (LinearLayout)findViewById(R.id.ll); //设置过渡动画 ScaleAnimation sa = new ScaleAnimation(0, 1, 0, 1); sa.setDuration(2000); //设置布局动画的显示属性 LayoutAnimationController lac = new LayoutAnimationController(sa, 0.5F); lac.setOrder(LayoutAnimationController.ORDER_NORMAL); //为viewgroup设置布局动画 ll.setLayoutAnimation(lac);
上述代码可以使得子view出现时有一个缩放的效果。
插值器 插值器用于定义动画变化速率。
自定义动画 自定义动画是继承一个Animation然后自己写,自定义动画可以获得当前矩阵对象,然后对矩阵进行操作变化,可以实现任何效果的动画。