Android实现动画组合的四种方式
先上动图,本文介绍实现下面动图中组合动画的四种方式
方式一:视图动画之AnimationSet
- xml方式实现
<?xml version="1.0" encoding="utf-8"?>
<set
android:fillAfter="true"
android:duration="3000"
android:shareInterpolator="@android:anim/accelerate_decelerate_interpolator"
xmlns:android="http://schemas.android.com/apk/res/android">
<!--透明度从无到有-->
<alpha android:fromAlpha="0"
android:toAlpha="1"/>
<!--旋转两圈-->
<rotate
android:pivotY="50%"
android:pivotX="50%"
android:fromDegrees="0"
android:toDegrees="720"/>
<!--放大三倍-->
<scale android:pivotX="50%"
android:pivotY="50%"
android:fromXScale="0.1"
android:fromYScale="0.1"
android:toXScale="3"
android:toYScale="3"/>
<!--平移至中间位置-->
<translate
android:fromXDelta="0"
android:fromYDelta="0"
android:toXDelta="35%p"
android:toYDelta="42.5%p"/>
</set>
//1.通过xml方式引入动画
Animation animationSet = AnimationUtils.loadAnimation(this,R.anim.anim_set_pic);
//设置动画时长为3秒
animationSet.setDuration(3000);
//设置插值器为先加速再减速
animationSet.setInterpolator(new AccelerateDecelerateInterpolator());
//动画完成后保持位置
animationSet.setFillAfter(true);
//开始动画
ibSagiri.startAnimation(animationSet);
- 代码方式实现
//2.通过代码生成方式
AnimationSet animationSet = new AnimationSet(true); //true表示共用同一个插值器
//透明度从0至1
AlphaAnimation alphaAnimation = new AlphaAnimation(0, 1);
//旋转两圈
RotateAnimation rotateAnimation = new RotateAnimation(0, 720, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
//放大三倍
ScaleAnimation scaleAnimation = new ScaleAnimation(0.1f, 3, 0.1f, 3, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
//平移距离x方向为父控件宽的35%,y方向为父控件高的42.5%
TranslateAnimation translateAnimation = new TranslateAnimation(Animation.ABSOLUTE, 0, Animation.RELATIVE_TO_PARENT, 0.35f, Animation.ABSOLUTE, 0, Animation.RELATIVE_TO_PARENT, 0.425f);
animationSet.addAnimation(alphaAnimation);
animationSet.addAnimation(rotateAnimation);
animationSet.addAnimation(scaleAnimation);
animationSet.addAnimation(translateAnimation);
//设置动画时长为3秒
animationSet.setDuration(3000);
//设置插值器为先加速再减速
animationSet.setInterpolator(new AccelerateDecelerateInterpolator());
//动画完成后保持位置
animationSet.setFillAfter(true);
//开始动画
ibSagiri.startAnimation(animationSet);
方式二:属性动画1之AnimatorSet
//生成一个透明度变化的属性动画对象
ObjectAnimator alphaAnimator = ObjectAnimator.ofFloat(ibSagiri, "alpha", 0, 0.2f, 0.5f, 1);
//旋转两圈的动画
ObjectAnimator rotationAnimator = ObjectAnimator.ofFloat(ibSagiri, "rotation", 0, 360, 540, 720);
//X轴移动35%父视图的长度
ObjectAnimator translationXAnimator = ObjectAnimator.ofFloat(ibSagiri, "translationX", 0, clParent.getWidth() * 0.35f);
//Y轴移动42.5%父视图的长度
ObjectAnimator translationYAnimator = ObjectAnimator.ofFloat(ibSagiri, "translationY", 0, clParent.getHeight() * 0.425f);
//XY方向都放大3倍
ObjectAnimator scaleXAnimator = ObjectAnimator.ofFloat(ibSagiri, "scaleX", 0, 1, 2, 3);
ObjectAnimator scaleYAnimator = ObjectAnimator.ofFloat(ibSagiri, "scaleY", 0, 1, 2, 3);
//生成一个animatorSet对象
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.setDuration(3000);
animatorSet.setInterpolator(new AccelerateDecelerateInterpolator());
//播放多条动画
animatorSet.playTogether(alphaAnimator, rotationAnimator, translationXAnimator, translationYAnimator, scaleXAnimator, scaleYAnimator);
animatorSet.start();
方式三:属性动画2之PropertyValuesHolder
//生成一个透明度变化的valuesHolder,其他同上
PropertyValuesHolder alphaHolder = PropertyValuesHolder.ofFloat("alpha", 0, 0.2f, 0.5f, 1);
PropertyValuesHolder rotationHolder = PropertyValuesHolder.ofFloat("rotation", 0, 360, 540, 720);
PropertyValuesHolder translationXHolder = PropertyValuesHolder.ofFloat("translationX", 0, clParent.getWidth() * 0.35f);
PropertyValuesHolder translationYHolder = PropertyValuesHolder.ofFloat("translationY", 0, clParent.getHeight() * 0.425f);
PropertyValuesHolder scaleXHolder = PropertyValuesHolder.ofFloat("scaleX", 0, 1, 2, 3);
PropertyValuesHolder scaleYHolder = PropertyValuesHolder.ofFloat("scaleY", 0, 1, 2, 3);
////利用多个Holder生成一个ObjectAnimator对象
ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(ibSagiri, alphaHolder, rotationHolder, translationXHolder, translationYHolder, scaleXHolder, scaleYHolder);
//设置动画时间
animator.setDuration(3000);
//设置插值器
animator.setInterpolator(new AccelerateDecelerateInterpolator());
animator.start();
方式四:ViewPropertyAnimator
ibSagiri.animate()
// .alpha(1) 使用该种方式无法实现透明度的变化
.rotation(720)
.translationX(clParent.getWidth() * 0.35f).translationY(clParent.getHeight() * 0.425f)
.scaleX(3).scaleY(3)
.setDuration(3000)
.setInterpolator(new AccelerateDecelerateInterpolator())
;
该方式有一个缺馅,无法实现透明度从0到1的变化。
关于ViewPropertyAnimator的小知识:
ViewPropertyAnimator并没有像ObjectAnimator一样使用反射或者JNI技术;而ViewPropertyAnimator会根据预设的每一个动画帧计算出对应的所有属性值,并设置给控件,然后调用一次invalidate()
函数进行重绘,从而解决了在使用ObjectAnimator时每个属性单独计算、单独重绘的问题。所以ViewPropertyAnimator相对于ObjectAnimator和组合动画,性能有所提升。
-----摘自启舰《Android自定义控件开发入门与实战》P153
Tips:动画种类知识
Android中的动画共分为两大类,视图动画(ViewAnimation)和属性动画(PropertyAnimator)
- 视图动画:只是视觉上移动控件,实际控件放置区域依然不变
- 属性动画:以改变控件属性的方式来达到做动画的效果,实际控件放置区域会随动画而做改变。
总结如下图所示