最近一周系统看了Android动画方面的知识点,总结成一篇文章,供网友参考,也供日后自己复习使用。
Android系统提供了两类动画,View动画和Property动画。
View动画从API level 1就有,Property动画从API level 11引入的。
理解
View动画
Tween 动画
View动画包括Tween 动画和 Frame动画。Tween 动画是指在给定的初始值和终点值之间做缩放,位移,旋转,透明度等变换。Frame动画是指对给定的一组Drawable资源一个接一个的显示。
动画定义可以在xml中,也可以在代码中定义,推荐xml,因为可读性好,可重用。
动画xml文件放在目录 res/anim/ 下。xml文件只能有一个根元素,这些根元素可以是 <alpha>
, <scale>
, <translate>
, <rotate>
或者 <set> ,<set> 里可以保护其他根元素和<set> 元素。
<set android:shareInterpolator="false">
<scale
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:fromXScale="1.0"
android:toXScale="1.4"
android:fromYScale="1.0"
android:toYScale="0.6"
android:pivotX="50%"
android:pivotY="50%"
android:fillAfter="false"
android:duration="700" />
<set android:interpolator="@android:anim/decelerate_interpolator">
<scale
android:fromXScale="1.4"
android:toXScale="0.0"
android:fromYScale="0.6"
android:toYScale="0.0"
android:pivotX="50%"
android:pivotY="50%"
android:startOffset="700"
android:duration="400"
android:fillBefore="false" />
<rotate
android:fromDegrees="0"
android:toDegrees="-45"
android:toYScale="0.0"
android:pivotX="50%"
android:pivotY="50%"
android:startOffset="700"
android:duration="400" />
</set>
</set>
使用
View view = new ImageView(this);
Animation animation = AnimationUtils.loadAnimation(this, R.anim.anim_rotate);
view.startAnimation(animation);
<alpha>
,
<scale>
,
<translate>
,
<rotate>
<set> 对应的类分别是 AlphaAnimation,ScaleAnimation,TranslateAnimation,RotateAnimation ,AnimationSet 。
使用
AnimationSet animationSet = new AnimationSet(true);
Animation alphaAnim = new AlphaAnimation(0.0f,1.0f);
Animation translationAnim = new TranslateAnimation(Animation.RELATIVE_TO_SELF,1.0f,Animation.RELATIVE_TO_SELF,0.0f,
Animation.RELATIVE_TO_SELF,0.0f,Animation.RELATIVE_TO_SELF,0.0f);
animationSet.addAnimation(alphaAnim);
animationSet.addAnimation(translationAnim);
view.startAnimation(animationSet);
要对ViewGroup的每个child做动画,比如child进入界面时的动画,需要使用LayoutAnimationController
ListView listView = new ListView(this);
//create animation
AnimationSet animationSet = new AnimationSet(true);
Animation alphaAnim = new AlphaAnimation(0.0f,1.0f);
Animation translationAnim = new TranslateAnimation(Animation.RELATIVE_TO_SELF,1.0f,Animation.RELATIVE_TO_SELF,0.0f,
Animation.RELATIVE_TO_SELF,0.0f,Animation.RELATIVE_TO_SELF,0.0f);
animationSet.addAnimation(alphaAnim);
animationSet.addAnimation(translationAnim);
//create LayoutAnimationController
LayoutAnimationController animationController = new LayoutAnimationController(animationSet,0.5f);
//set LayoutAnimationController for ViewGroup
listView.setLayoutAnimation(animationController);
Frame动画
定义帧动画的xml文件存放在 res/drawable/ 下,可以用作View的背景,调用 start() 开始动画。
spin_animation.xml
<!-- Animation frames are wheel0.png -- wheel5.png files inside the
res/drawable/ folder -->
<animation-list android:id="@+id/selected" android:oneshot="false">
<item android:drawable="@drawable/wheel0" android:duration="50" />
<item android:drawable="@drawable/wheel1" android:duration="50" />
<item android:drawable="@drawable/wheel2" android:duration="50" />
<item android:drawable="@drawable/wheel3" android:duration="50" />
<item android:drawable="@drawable/wheel4" android:duration="50" />
<item android:drawable="@drawable/wheel5" android:duration="50" />
</animation-list>
// Load the ImageView that will host the animation and
// set its background to our AnimationDrawable XML resource.
ImageView img = (ImageView)findViewById(R.id.spinning_wheel_image);
img.setBackgroundResource(R.drawable.spin_animation);
// Get the background, which has been compiled to an AnimationDrawable object.
AnimationDrawable frameAnimation = (AnimationDrawable) img.getBackground();
// Start the animation (looped playback by default).
frameAnimation.start();
Property 动画
属性动画改变的是对象的属性,对象的外观也会跟着变化;而View动画,改变的只是View的外观,只改变了View的绘制区域,而起属性没有变化。(比如,一个View做位移动画后,触发点击事件的区域还在原来的位置)View动画只适用于View,而属性动画可适用于任何对象;View动画不能对background color作动画,但属性动画可以。
如果View动画能满足需求,就用它,因为View动画执行起来需要的时间和写的代码少。
通过下图看属性动画的原理
该图展示的是线性变化的动画,整个duration是40ms,每10ms x变化10.
该图展示的是非线性的,先加速后减速,第一个10ms,x变化6,第二个10ms,x变化14,第三个10ms,x变化14,第四个10ms,x变化6。
ValueAnimator animation = ValueAnimator.ofFloat(0f, 1f);
animation.setDuration(1000);
animation.start();
ValueAnimator animation = ValueAnimator.ofObject(new MyTypeEvaluator(), startPropertyValue, endPropertyValue);
animation.setDuration(1000);
animation.start();
但还需要给ValueAnimator设置
ValueAnimator.AnimatorUpdateListener,用于更新target的属性。
ObjectAnimator anim = ObjectAnimator.ofFloat(foo, "alpha", 0f, 1f);
anim.setDuration(1000);
anim.start();
AnimatorSet使用
AnimatorSet bouncer = new AnimatorSet();
bouncer.play(bounceAnim).before(squashAnim1);
bouncer.play(squashAnim1).with(squashAnim2);
bouncer.play(squashAnim1).with(stretchAnim1);
bouncer.play(squashAnim1).with(stretchAnim2);
bouncer.play(bounceBackAnim).after(stretchAnim2);
ValueAnimator fadeAnim = ObjectAnimator.ofFloat(newBall, "alpha", 1f, 0f);
fadeAnim.setDuration(250);
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.play(bouncer).before(fadeAnim);
animatorSet.start();
可以设置ViewGroup的layout变化时的动画。使用 LayoutTransition,viewGroup.setLayoutTransition()。但child add/remove,visible/invisble,gone时,都会触发这种动画。总共有4种情况, APPEARING,CHANGE_APPEARING,
DISAPPEARING
,CHANGE_DISAPPEARING。
调用LayoutTransition的setAnimator(type,animator). ViewGroup的默认layout change动画是没有打开的,在xml中可以设置
android:animateLayoutChanges="true"
Multiple ObjectAnimator objects
ObjectAnimator animX = ObjectAnimator.ofFloat(myView, "x", 50f); ObjectAnimator animY = ObjectAnimator.ofFloat(myView, "y", 100f); AnimatorSet animSetXY = new AnimatorSet(); animSetXY.playTogether(animX, animY); animSetXY.start();
One ObjectAnimator
PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat("x", 50f); PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("y", 100f); ObjectAnimator.ofPropertyValuesHolder(myView, pvhX, pvyY).start();
ViewPropertyAnimator
myView.animate().x(50f).y(100f);
属性动画也可以在xml中定义,xml文件
res/animator/
<set android:ordering="sequentially">
<set>
<objectAnimator
android:propertyName="x"
android:duration="500"
android:valueTo="400"
android:valueType="intType"/>
<objectAnimator
android:propertyName="y"
android:duration="500"
android:valueTo="300"
android:valueType="intType"/>
</set>
<objectAnimator
android:propertyName="alpha"
android:duration="500"
android:valueTo="1f"/>
</set>
AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(myContext, R.anim.property_animator); set.setTarget(myObject); set.start();
实践
QQ客户端侧滑菜单实现
侧滑菜单的效果截图如下:
58同城Loading View实现
也是参考的网友的实现方案,地址 https://github.com/zzz40500/android-shapeLoadingView在这两个项目中,都用到了Property 动画。