Android 3.0之后引入了属性动画,属性动画能够垂手可得的实现许多View动画作不到的事,java
属性动画实现原理就是修改控件的属性值实现的动画。android
具体先看下类关系:性能优化
Android属性动画(注意最低兼容版本,不过可使用开源项目来替代低版本问题)提供了如下属性:dom
XML方式属性动画代码示例ide
在xml中可直接用的属性动画节点有ValueAnimator、ObjectAnimator、AnimatorSet。以下是官方的一个例子和解释函数
<set android:ordering=["together" | "sequentially"]> <objectAnimator android:propertyName="string" android:duration="int" android:valueFrom="float | int | color" android:valueTo="float | int | color" android:startOffset="int" android:repeatCount="int" android:repeatMode=["repeat" | "reverse"] android:valueType=["intType" | "floatType"]/> <animator android:duration="int" android:valueFrom="float | int | color" android:valueTo="float | int | color" android:startOffset="int" android:repeatCount="int" android:repeatMode=["repeat" | "reverse"] android:valueType=["intType" | "floatType"]/> <set> ... </set> </set>
<set>属性布局
<objectAnimator>属性post
ValueAnimator同上<objectAnimator>
属性性能
XML属性动画使用方法优化
AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(myContext,R.animtor.property_animator);
set.setTarget(myObject);set.start();
Java方式属性动画
一、ObjectAnimator:继承自ValueAnimator,容许你指定要进行动画的对象以及该对象的一个属性。该类会根据计算获得的新值自动更新属性。大多数的状况使用ObjectAnimator就足够了,由于它使得目标对象动画值的处理过程变得足够简单,不用像ValueAnimator那样本身写动画更新的逻辑,可是ObjectAnimator有必定的限制,好比它须要目标对象的属性提供指定的处理方法(譬如提供getXXX,setXXX方法),这时候你就须要根据本身的需求在ObjectAnimator和ValueAnimator中看哪一种实现更方便了。
ObjectAnimator类提供了ofInt、ofFloat、ofObject这个三个经常使用的方法,这些方法都是设置动画做用的元素、属性、开始、结束等任意属性值。当属性值(上面方法的参数)只设置一个时就把经过getXXX反射获取的值做为起点,设置的值做为终点;若是设置两个(参数),那么一个是开始、另外一个是结束。
特别注意:ObjectAnimator的动画原理是不停的调用setXXX方法更新属性值,全部使用ObjectAnimator更新属性时的前提是Object必须声明有getXXX和setXXX方法。咱们一般使用ObjectAnimator设置View已知的属性来生成动画,而通常View已知属性变化时都会主动触发重绘图操做,因此动画会自动实现;可是也有特殊状况,譬如做用Object不是View,或者做用的属性没有触发重绘,或者咱们在重绘时须要作本身的操做,那均可以经过以下方法手动设置:
ObjectAnimator mObjectAnimator= ObjectAnimator.ofInt(view, "customerDefineAnyThingName", 0, 1) .setDuration(2000);
mObjectAnimator.addUpdateListener(new AnimatorUpdateListener()
{
@Override
public void onAnimationUpdate(ValueAnimator animation)
{
//int value = animation.getAnimatedValue(); 能够获取当前属性值
//view.postInvalidate(); 能够主动刷新
//view.setXXX(value);
//view.setXXX(value);
//......能够批量修改属性
}
});
在项目中的Y轴3D旋转动画实现实例:
ObjectAnimator.ofFloat(view, "rotationY", 0.0f, 360.0f).setDuration(1000).start();
二、PropertyValuesHolder:多属性动画同时工做管理类。有时候咱们须要同时修改多个属性,那就能够用到此类,具体以下:
PropertyValuesHolder a1 = PropertyValuesHolder.ofFloat("alpha", 0f, 1f);
PropertyValuesHolder a2 = PropertyValuesHolder.ofFloat("translationY", 0, viewWidth);
......
ObjectAnimator.ofPropertyValuesHolder(view, a1, a2, ......).setDuration(1000).start();
如上代码就能够实现同时修改多个属性的动画啦。
三、ValueAnimator:属性动画中的时间驱动,管理着动画时间的开始、结束属性值,相应时间属性值计算方法等。包含全部计算动画值的核心函数以及每个动画时间节点上的信息、一个动画是否重复、是否监听更新事件等,而且还能够设置自定义的计算类型。
特别注意:ValueAnimator只是动画计算管理驱动,设置了做用目标,但没有设置属性,须要经过updateListener里设置属性才会生效。
ValueAnimator animator = ValueAnimator.ofFloat(0, mContentHeight); //定义动画
animator.setTarget(view); //设置做用目标
animator.setDuration(5000).start();
animator.addUpdateListener(new AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation){
float value = (float) animation.getAnimatedValue();
view.setXXX(value); //必须经过这里设置属性值才有效
view.mXXX = value; //不须要setXXX属性方法
}
});
看上去能够发现和ObjectAnimator没啥区别,实际上正是因为ValueAnimator不直接操做属性值,因此要操做对象的属性能够不须要setXXX与getXXX方法,你彻底能够经过当前动画的计算去修改任何属性。
四、AnimationSet:动画集合,提供把多个动画组合成一个组合的机制,并可设置动画的时序关系,如同时播放、顺序播放或延迟播放。具体使用方法比较简单,以下:
ObjectAnimator a1 = ObjectAnimator.ofFloat(view, "alpha", 1.0f, 0f);
ObjectAnimator a2 = ObjectAnimator.ofFloat(view, "translationY", 0f, viewWidth);
......
AnimatorSet animSet = new AnimatorSet();
animSet.setDuration(5000);
animSet.setInterpolator(new LinearInterpolator());
//animSet.playTogether(a1, a2, ...); //两个动画同时执行
animSet.play(a1).after(a2); //前后执行
......//其余组合方式
animSet.start();
五、Evaluators相关类解释: Evaluators就是属性动画系统如何去计算一个属性值。它们经过Animator提供的
动画的起始和结束值去计算一个动画的属性值。
• IntEvaluator: 整数属性值。
• FloatEvaluator: 浮点数属性值。
• ArgbEvaluator: 十六进制color属性值。
• TypeEvaluator: 用户自定义属性值接口,譬如对象属性值类型不是int、float、color类型,
你必须实现这个接口去定义本身的数据类型
如须要实现一个自定义属性类型和计算规则的属性动画,以下类型float[]:
ValueAnimator valueAnimator = new ValueAnimator();
valueAnimator.setDuration(5000);
valueAnimator.setObjectValues(new float[2]); //设置属性值类型
valueAnimator.setInterpolator(new LinearInterpolator());
valueAnimator.setEvaluator(new TypeEvaluator<float[]>()
{
@Override
public float[] evaluate(float fraction, float[] startValue,float[] endValue)
{
//实现自定义规则计算的float[]类型的属性值
float[] temp = new float[2];
temp[0] = fraction * 2;
temp[1] = (float)Math.random() * 10 * fraction;
return temp;
}
});
valueAnimator.start();
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener()
{
@Override
public void onAnimationUpdate(ValueAnimator animation)
{
float[] xyPos = (float[]) animation.getAnimatedValue();
view.setHeight(xyPos[0]); //经过属性值设置View属性动画
view.setWidth(xyPos[1]); //经过属性值设置View属性动画
}
});
六、Interpolators相关类解释
• AccelerateDecelerateInterolator:先加速后减速。
• AccelerateInterpolator:加速。
• DecelerateInterpolator:减速。
• AnticipateInterpolator:先向相反方向改变一段再加速播放。
• AnticipateOvershootInterpolator:先向相反方向改变,再加速播放,会超出目标值而后缓慢移动至目标值,相似于弹簧回弹。
• BounceInterpolator:快到目标值时值会跳跃。
• CycleIinterpolator:动画循环必定次数,值的改变为一正弦函数:Math.sin(2 * mCycles * Math.PI * input)。
• LinearInterpolator:线性均匀改变。
• OvershottInterpolator:最后超出目标值而后缓慢改变到目标值。
• TimeInterpolator:一个容许自定义Interpolator的接口,以上都实现了该接口。
以下就是加速插值器的实现代码,咱们自定义时也能够相似实现:
//开始很慢而后不断加速的插值器。
public class AccelerateInterpolator implements Interpolator {
private final float mFactor;
private final double mDoubleFactor;
public AccelerateInterpolator() {
mFactor = 1.0f;
mDoubleFactor = 2.0;
}
......
//input 0到1.0。表示动画当前点的值,0表示开头,1表示结尾。
//return 插值。值能够大于1超出目标值,也能够小于0突破低值。
@Override
public float getInterpolation(float input) {
//实现核心代码块
if (mFactor == 1.0f) {
return input * input;
} else {
return (float)Math.pow(input, mDoubleFactor);
}
}
}
综上能够发现,咱们可使用现有系统提供标准的东东实现属性动画,也能够经过自定义继承相关接口实现本身的动画,只要实现上面提到的那些主要方法便可。
Java属性动画拓展之ViewPropertyAnimator动画
在Android API 12时,View中添加了animate方法,具体以下:
p
ublic class View implements Drawable.Callback, KeyEvent.Callback,AccessibilityEventSource {
......
/**
* This method returns a ViewPropertyAnimator object, which can be used to animate
* specific properties on this View.
*
* @return ViewPropertyAnimator The ViewPropertyAnimator associated with this View.
*/
public ViewPropertyAnimator animate() {
if (mAnimator == null) {
mAnimator = new ViewPropertyAnimator(this);
}
return mAnimator;
}
......
}
能够看见经过View的animate()方法能够获得一个ViewPropertyAnimator的属性动画(有人说他没有继承Animator类,是的,他是成员关系,不是以前那种继承关系)。
ViewPropertyAnimator提供了一种很是方便的方法为View的部分属性设置动画(切记,是部分属性),它能够直接使用一个Animator对象设置多个属性的动画;在多属性设置动画时,它比 上面的ObjectAnimator更加牛逼、高效,由于他会管理多个属性的invalidate方法统一调运触发,而不像上面分别调用,因此还会有一些性能优化。
以下就是一个例子:
myView.animate().x(0f).y(100f).start();
Java属性动画拓展之LayoutAnimator容器布局动画
Property动画系统还提供了对ViewGroup中View添加时的动画功能,咱们能够用LayoutTransition对ViewGroup中的View进行动画设置显示。LayoutTransition的动画效果都是设置给ViewGroup,而后当被设置动画的ViewGroup中添加删除View时体现出来。该类用于当前布局容器中有View添加、删除、隐藏、显示等时候定义布局容器自身的动画和View的动画,也就是说当在一个LinerLayout中隐藏一个View的时候,咱们能够自定义 整个因为LinerLayout隐藏View而改变的动画,同时还能够自定义被隐藏的View本身消失时候的动画等。
咱们能够发现LayoutTransition类中主要有五种容器转换动画类型,具体以下:
• LayoutTransition.APPEARING: 当View出现或者添加的时候View出现的动画。
• LayoutTransition.CHANGE_APPEARING:当添加View致使布局容器改变的时候整个布局容器的动画。
• LayoutTransition.DISAPPEARING: 当View消失或者隐藏的时候View消失的动画。
• LayoutTransition.CHANGE_DISAPPEARING:当删除或者隐藏View致使布局容器改变的时候整个布局容器的动画。
• LayoutTransition.CHANGE:当不是因为View出现或消失形成对其余View位置形成改变的时候整个布局容器的动画
XML方式使用系统提供的默认LayoutTransition动画:
咱们能够经过以下方式使用系统提供的默认ViewGroup的LayoutTransition动画:
android:animateLayoutChanges=”true”
在ViewGroup添加如上xml属性默认是没有任何动画效果的,由于前面说了,该动画针对于ViewGroup内部东东发生改变时才有效,
因此当咱们设置如上属性而后调运ViewGroup的addView、removeView方法时就能看见系统默认的动画效果了。
还有一种就是经过以下方式设置:
android:layoutAnimation=”@anim/customer_anim”
经过这种方式就能实现不少吊炸天的动画。
Java方式使用系统提供的默认LayoutTransition动画
在使用LayoutTransition时,你能够自定义这几种事件类型的动画,也可使用默认的动画,总之最终都是经过setLayoutTransition(LayoutTransition lt)方法把这些动画以一个LayoutTransition对象设置给一个ViewGroup。
譬如实现如上Xml方式的默认系统LayoutTransition动画以下:
mTransitioner = new LayoutTransition();
mViewGroup.setLayoutTransition(mTransitioner);
稍微再高端一点吧,咱们来自定义这几类事件的动画,分别实现他们,那么你能够像下面这么处理:
mTransitioner = new LayoutTransition();
......
ObjectAnimator anim = ObjectAnimator.ofFloat(this, "scaleX", 0, 1);
......//设置更多动画
mTransition.setAnimator(LayoutTransition.APPEARING, anim);
......//设置更多类型的动画
mViewGroup.setLayoutTransition(mTransitioner);
经过LayoutTransition就能实现相似小米手机计算器切换普通型和科学型的炫酷动画了。