文章主要内容来源《Android开发艺术探索》,部份内容来源网上的文章,文中会有连接。android
Android系统提供了两个动画框架:属性动画框架和View动画框架。 两个动画框架都是可行的选项,可是属性动画框架一般是首选的使用方法,由于它更灵活,并提供更多的功能。 除了这两个框架,还可使用Drawable动画(即逐帧动画,AnimationDrawable),它容许你加载Drawable资源并逐帧地显示它们。算法
View动画框架(补间动画)
View动画框架中一共提供了AlphaAnimation(透明度动画)、RotateAnimation(旋转动画)、ScaleAnimation(缩放动画)、TranslateAnimation(平移动画)四种类型的补间动画;而且View动画框架还提供了动画集合类(AnimationSet),经过动画集合类(AnimationSet)能够将多个补间动画以组合的形式显示出来。补间动画的实现,通常会采用xml文件的形式,那样代码会更容易书写和阅读,同时也更容易复用。框架属性动画框架
与属性动画相比View动画存在一个缺陷,View动画改变的只是View的显示,而没有改变View的响应区域,而且View动画只能对View作四种类型的补间动画。所以Google在Android3.0(API级别11)及其后续版本中添加了属性动画框架,从名称中就能够知道只要某个类具备属性(即该类含有某个字段的set和get方法),那么属性动画框架就能够对该类的对象进行动画操做(其实就是经过反射技术来获取和执行属性的get,set方法),一样属性动画框架还提供了动画集合类(AnimatorSet),经过动画集合类(AnimatorSet)能够将多个属性动画以组合的形式显示出来。dom做者:ForeverCy
连接:http://www.jianshu.com/p/b117c974deaf
來源:简书
著做权归做者全部。商业转载请联系做者得到受权,非商业转载请注明出处。ide
View动画的四种变换效果对应着Animation的四个子类:TranslateAnimation、ScaleAnimation、RotateAnimation、AlphaAnimation。四种动画能够用这四个类经过代码实现,也可使用XML文件来定义。建议使用XML来定义动画,由于XML格式可读性好并且方便复用。oop
名称 | 标签 | 子类 |
---|---|---|
平移动画 |
|
TranslateAnimation |
缩放动画 |
|
ScaleAnimation |
选中动画 |
|
RotateAnimation |
透明度动画 |
|
AlphaAnimation |
<set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="" android:shareInterpolator="true|false"> <translate android:fromXDelta="" android:toXDelta="" android:fromYDelta="" android:toYDelta="" /> <scale android:fromXScale="" android:toXScale="" android:fromYScale="" android:toYScale="" android:pivotX="" android:pivotY="" /> <rotate android:fromDegrees="" android:toDegrees="" android:pivotX="" android:pivotY="" /> <alpha android:fromAlpha="" android:toAlpha="" /> <set> <!--set嵌套set--> </set> </set>
View动画能够是单个动画,也能够由一系列动画组成,使用
android:interpolator表示动画集合所使用的插值器,插值器影响动画的速度,好比非匀速动画就须要经过插值器来控制动画的播放过程。这个属性能够不指定,默认是@android:anim/accelerate_decelerate_interpolator,即加速减速插值器。
android:shareInterpolator表示集合中的动画是否和集合共享同一个插值器。若是集合不指定插值器,那么子动画就须要单独指定所须要的插值器或者使用默认值。lua
android:fromXDelta x的起始值
android:toXDelta x的结束值
android:fromYDelta y的起始值
android:toYDelta y的结束值.net
android:fromXScale 水平方向缩放的起始值
android:toXScale 水平方向缩放的结束值
android:fromYScale 竖直方向缩放的起始值
android:toYScale 竖直方向缩放的结束值
android:pivotX 缩放的轴点的x坐标
android:pivotY 缩放的轴点的y坐标线程
android:fromDegrees 旋转开始的角度
android:toDegrees 旋转结束的角度
android:pivotX 旋转的轴点的x坐标
android:pivotY 选中的轴点的y坐标
android:fromAlpha 透明度的起始值
android:toAlpha 透明度的结束值
android:duration 动画的持续时间
android:fillBefore 动画结束后是否回到执行前的位置
android:fillAfter 动画结束后是否停留在结束位置
android:interpolator 动画使用的插值器
android:startOffset 动画执行以前的等待时间
android:repeatCount 动画重复执行的次数
xml属性都有对应的set方法
首先编写动画xml文件test_anim.xml
Button mButton = (Button)findViewById(R.id.button); Animation animation = AnimationUtils.loadAnimation(context, R.anim.test_anim); mButton.startAnimation(animation);
也能够经过代码实现
AlphaAnimation animation = new AlphaAnimation(0, 1); animation.setDuration(300); mButton.startAnimation(animation);
使用setAnimationListener方法能够给动画添加过程监听。
<layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android" android:delay="150" android:animationOrder="normal" android:animation="@anim/anim_item"/>
android:delay 子元素开始动画的时间延迟
android:animationOrder 子元素动画的顺序。有normal(顺序)、reverse(逆向)、random(随机)三种顺序。
android:animation 子元素入场的具体动画
<translate xmlns:android="http://schemas.android.com/apk/res/android" android:fromXDelta="500" android:toXDelta="0"/>
<ListView android:id="@+id/list" android:layout_width="match_parent" android:layout_height="match_parent" android:layoutAnimation="@anim/anim_layout" />
除了经过xml中指定layoutAnimation属性,也能够经过LayoutAnimationController来实现:
Animation animation = AnimationUtils.loadAnimation(context, R.anim.anim_item); LayoutAnimationController controller = new LayoutAnimationController(animation); controller.setDelay(0.5f); controller.setOrder(LayoutAnimationController.ORDER_NORMAL); listView.setLayoutAnimation(controller);
使用overridePendingTransition(int enterAnim, int exitAnim)方法实现Activity的切换动画,这个方法必须在startActivity()或者finish()以后调用才能生效。
Fragment也能够添加切换动画,经过FragmentTransaction中的setCustomAnimations()方法实现。
帧动画的标签是
示例代码
<animation-list xmlns:android="http://schemas.android.com/apk/res/android" android:oneshot="false"> <item android:drawable="@drawable/img1" android:duration="500"/> <item android:drawable="@drawable/img2" android:duration="500"/> <item android:drawable="@drawable/img3" android:duration="500"/> </animation-list>
Button mButton = (Button)findViewById(R.id.button1); mButton.setBackgroundResource(R.drawable.frame_animation); AnimationDrawable drawable = (AnimationDrawable)mButton.getBackground(); drawable.start();
注意帧动画容易引发OOM。
属性动画从 API 11 才有,属性动画能够对任意对象的属性进行动画而不只仅是View,达到的效果是:在一个时间间隔内完成对象从一个属性值到另外一个属性值的改变。属性动画经常使用的动画类:ValueAnimator、ObjectAnimator、AnimatorSet。ObjectAnimator继承自ValueAnimator,AnimatorSet是动画集合。
属性动画也有对应的xml标签,可是建议使用代码来实现属性动画,由于使用代码比xml简单。并且不少时候一个属性的起始值没法提早肯定。
ObjectAnimator.ofFloat(myObject, "translationY", -myObject.getHeight()).start();
ValueAnimator anim = ObjectAnimator.ofInt(myObject, "backgroundColor",0xFFFF8080,0xFF8080FF); anim.setDuration(3000); anim.setEvaluator(new ArgbEvaluator()); anim.setRepeatCount(ValueAnimator.INFINITE); anim.setRepeatMode(ValueAnimator.REVERSE); anim.start();
AnimatorSet set = new AnimatorSet(); set.playTogether( ObjectAnimator.ofFloat(myView, "rotationX", 0, 360), ObjectAnimator.ofFloat(myView, "rotationY", 0, 180), ObjectAnimator.ofFloat(myView, "rotation", 0, -90), ObjectAnimator.ofFloat(myView, "translationX", 0, 90), ObjectAnimator.ofFloat(myView, "translationY", 0, 90), ObjectAnimator.ofFloat(myView, "scaleX", 1, 1.5f), ObjectAnimator.ofFloat(myView, "scaleY", 1, 0.5f), ObjectAnimator.ofFloat(myView, "alpha", 1, 0.25f, 1) ); set.setDuration(5*1000).start();
上面代码用到一个主要的方法
ObjectAnimator.ofFloat(target, propertyName, values...);
target 是动画目标,任何对象,不必定必须是View
propertyName 是属性名字
values 是可变参数, 从v1变化到v2到vn。。。
例子:
mIv是一个imageView
//alpha 从0 到1 的动画
ObjectAnimator.ofFloat(mIv, "alpha", 0f,1f)
.setDuration(500)
.start();
若是要实现其余效果,修改propertyName和values就好了。
属性动画的原理就是经过反射,以动画的效果屡次调用set方法来改变属性值的。因此,使用属性动画时,相应的对象属性必须有set方法,get方法能够没有,可是若是使用动画的时候没有传递初始值,就必须提供get方法,由于系统要经过get方法获取属性的默认初始值。
alpha 透明度
rotation z轴旋转
rotationX x轴旋转
rotationY y轴旋转
translationX x水平偏移
translationY y水平偏移
ScaleX x轴缩放
ScaleY y轴缩放
插值器(TimeInterpolator/Interpolator)用来修饰动画效果,定义动画的变化规率(变化趋势),好比平移动画,能够匀速平移也能够加速平移,这个由插值器决定。
估值器(Evaluator)用来决定具体的数值变化,好比(匀)加速平移时,“加速度”是多少由估值器决定。
插值器TimeInterpolator和Interpolator,后者是继承前者的接口。
TimeInterpolator接口是属性动画中新增的,用于兼容Interpolator接口,这使得全部过去的Interpolator实现类均可以直接在属性动画使用。
出自:http://blog.csdn.net/carson_ho/article/details/72863901
IntEvaluator 以整型的形式从初始值到结束值 进行过渡
FloatEvaluator 以浮点型的形式从初始值到结束值 进行过渡
ArgbEvaluator 以Argb类型的形式从初始值到结束值 进行过渡
若是系统内置的插值器和估值器没法知足需求,也能够自定义。
View动画的插值器实现Interpolator接口,View动画没有估值器
属性动画的插值器实现实现TimeInterpolator接口,估值器实现TypeEvaluator接口
自定义插值器和估值器参考系统内置的插值器和估值器便可。
如下摘自http://blog.csdn.net/carson_ho/article/details/72863901
实现Interpolator接口自定义插值器的说明(TimeInterpolator接口相同)
public interface Interpolator { // 内部只有一个方法 float getInterpolation(float input) { // 参数说明 // input值值变化范围是0-1,且随着动画进度(0% - 100% )均匀变化 // 即动画开始时,input值 = 0;动画结束时input = 1 // 而中间的值则是随着动画的进度(0% - 100%)在0到1之间均匀增长 ...// 插值器的计算逻辑 return xxx; // 返回的值就是用于估值器继续计算的fraction值 } }
实现TypeEvaluator接口自定义估值器的说明
public interface TypeEvaluator { public Object evaluate(float fraction, Object startValue, Object endValue) { // 参数说明 // fraction:插值器getInterpolation()的返回值 // startValue:动画的初始值 // endValue:动画的结束值 ....// 估值器的计算逻辑 return xxx; // 赋给动画属性的具体数值 // 使用反射机制改变属性变化 // 特别注意 // 插值器的input值 和 估值器fraction有什么关系呢? // 答:input的值决定了fraction的值:input值通过计算后传入到插值器的getInterpolation() // 而后经过实现getInterpolation()中的逻辑算法,根据input值来计算出一个返回值,而这个返回值就是fraction了 } }
View动画和属性动画均可以使用插值器,估值器只有属性动画能够用。
插值器用法
// 步骤1:建立须要设置动画的视图View Button mButton = (Button) findViewById(R.id.Button); // 步骤2:建立透明度动画的对象 & 设置动画效果 Animation alphaAnimation = new AlphaAnimation(1,0); alphaAnimation.setDuration(3000); // 步骤3:建立对应的插值器类对象 Interpolator overshootInterpolator = new OvershootInterpolator(); // 步骤4:给动画设置插值器 alphaAnimation.setInterpolator(overshootInterpolator); // 步骤5:播放动画 mButton.startAnimation(alphaAnimation);
估值器用法
// 在第3个参数中传入对应估值器类的对象 ObjectAnimator anim = ObjectAnimator.ofObject(myView2, "height", new Evaluator(),1,3);
有两个监听接口AnimatorListener和AnimatorUpdateListener。AnimatorListener和View动画的AnimationListener相似,能够监听动画的开始、结束等过程。AnimatorUpdateListener能够监听动画的每一帧变化,动画每变化一帧,接口里的方法被调用一次。
private void performAnimate(final View button, final int start, final int end) { ValueAnimator valueAnimator = ValueAnimator.ofInt(1, 100); valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { //持有一个IntEvaluator对象,方便下面估值的时候使用 private IntEvaluator mIntEvaluator = new IntEvaluator(); @Override public void onAnimationUpdate(ValueAnimator animator) { //得到当前动画的进度值,整型1-100之间 int currentValue = (int) animator.getAnimatedValue(); //得到当前进度占整个动画过程的比例,浮点型,0-1之间 float fraction = animator.getAnimatedFraction(); //直接调用整型估值器,经过比例计算出宽度,而后设给Button button.getLayoutParams().width = mIntEvaluator.evaluate(fraction, start, end); button.requestLayout(); } }); valueAnimator.setDuration(5000).start(); } @Override public void onClick(View v) { if (v == mButton) { performAnimate(mButton, mButton.getWidth(), 500); } }
View动画能够设置ViewGroup的子View的出场动画,属性动画能够为ViewGroup的子View的显示和隐藏设置过渡动画。出场动画文中已经介绍,属性动画实现的过分动画详细见ForeverCy的文章Android中的View动画和属性动画 中的相关部分。