很多属性都是见名知义的,下面呢简单介绍一下各属性名称的含义。
属性动画的核心类有3个类,AnimatorSet,ObjectAnimator以及ValueAnimator
XML文件中的 <set>标签对应AnimatorSet, <set>标签的ordering属性有2个候选值"sequentially"|"together",分别表示 <set>标签内的动画是按照前后顺序播放和同时播放。
<animatior>对应ValueAnimator,
android:duration:表示动画的时长
android:valueFrom:表示属性的起始值
android:valueTo:表示属性的结束值
android:startOffset:表示动画的延迟时间,动画开始后,需要延迟多少毫秒后才会真正播放该动画
android:repeatCount:表示动画的重复次数,默认值是0,为-1时,表示无限循环。
android:repeatMode:表示动画的重复播放模式,restart表示动画每次都是重新开始播放,reverse表示动画第1 次播放完毕后,第2次会逆向播放,第3次又从头开始播放,以此类推
<objectAnimator>对应ObjectAnimator,
android:propertyName:表示属性动画作用对象的属性名称
android:valueType:表示android:propertyName的值的类型,分为intType,和floatType,分别代表整型数值和浮点型数值,若android:propertyName指定的属性表示的是颜色,那么无需指定android:valueType,系统会自动适配
其他属性的含义与上面的<animatior>一致。
属性动画的进阶
我们先来看一个需求:要求对一个Button做动画,要求让其宽度从原始宽度增加到500px。这也太简单了,
Button mButton = (Button) findViewById(R.id.button);
ObjectAnimator.ofInt(mButton,"width",500).setDuration(1000).start();
程序运行,但是却没有效果,这是为什么呢,仔细想想没效果也是应该的,因为你随便传递了一个属性名称过去,轻则动画没有效果,重则直接Crash。那么这个号称可以对任意属性做动画的属性动画使用的时候有哪些需要注意的地方呢
属性动画要求动画的作用对象提供该属性的get和set方法,
属性的改变必须通过某种方法反映出来,比如会带来UI的修改之类的
以上的条件缺一不可
这时又有一个问题如果想要对一个对象的属性做动画,但是属性又没有对应的get和set方法怎么办呢??
概括来讲有如下3种解决办法:
给你的对象加上get和set方法,如果你有权限的话。而这个方法对于Android SDK内部实现的类就不可行,这个方法是最简单的,但是往往是不可行的。
用一个类包装原始对象,间接为其提供get和set方法
采用ValueAnimator,监听动画过程,自己实现属性的改变
下面仍以上面Button的宽度动画作为需求给出方法2,3的解决代码
方法2:
mButton = (Button) findViewById(R.id.button);
ObjectAnimator.ofInt(new ViewWrapper(mButton),"width",500).setDuration(1000).start();private class ViewWrapper{ private View mTarget; public ViewWrapper(View mTarget) { this.mTarget = mTarget;
} public int getWidth() { return mTarget.getLayoutParams().width;
} public void setWidth(int width) {
mTarget.getLayoutParams().width = width;
mTarget.requestLayout();
}
}
方法3:
使用方法3之前,我们先来看属性动画的监听器AnimatorUpdateListener和AnimatorListener
属性动画的监听器AnimatorUpdateListener和AnimatorListener
AnimatorUpdateListener
public static interface AnimatorListener {
void onAnimationStart(Animator animation);
void onAnimationEnd(Animator animation);
void onAnimationCancel(Animator animation);
void onAnimationRepeat(Animator animation);
}
如上代码所示AnimatorListener监听了动画的开始、结束、取消和重复播放,同时系统提供了AnimatorListenerAdapter适配器方便我们使用,我们可以继承这个类并有选择的实现方法。
AnimatorListener
public static interface AnimatorUpdateListener { /**
* <p>Notifies the occurrence of another frame of the animation.</p>
*
* @param animation The animation which was repeated.
*/
void onAnimationUpdate(ValueAnimator animation);
}
如上图所示,AnimatorUpdateListener 监听了动画的整个过程,动画每播放一帧,onAnimationUpdate就被调用一次,
下面就来看一下如何使用上面的属性动画的监听器来实现属性动画
mButton = (Button) findViewById(R.id.button);
performAnimate(mButton, mButton.getWidth(), 500);private void performAnimate(final View target, final int start, final int end) {
ValueAnimator valueAnimator = ValueAnimator.ofInt(1, 100);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { // 持有一个IntEvaluator对象,方便下面估值的时候使用
private IntEvaluator mEvaluator = new IntEvaluator(); @Override
public void onAnimationUpdate(ValueAnimator animator) { // 获得当前动画的进度值,整型,1-100之间
int currentValue = (Integer) animator.getAnimatedValue();
Log.d(TAG, "current value: " + currentValue); // 获得当前进度占整个动画过程的比例,浮点型,0-1之间
float fraction = animator.getAnimatedFraction(); // 直接调用整型估值器通过比例计算出宽度,然后再设给Button
target.getLayoutParams().width = mEvaluator.evaluate(fraction, start, end);
target.requestLayout();
}
});
valueAnimator.setDuration(5000).start();
}
使用动画的注意事项
OOM问题,此类问题主要出现在帧动画中,帧动画中如果使用大量图片,则可能会造成OOM问题,避免的方法同理,最好不要在帧动画中使用大量大尺寸的图片
View动画的问题,View动画的作用主题实际上是View的影子,所以View动画不适合做有交互性点击的动画,另外View动画也不能真正改变View的状态,所以有的时候会出现动画结束后,View.setVisibily(VIEW.GONE)失效,或者其他异常情况,使用View.clearAnimation()清除动画即可
内存泄露,在属性动画中有一类无限循环的动画,这类动画要在Activity销毁之前及时停止,否则会造成Activity无法回收导致内存泄漏。
本篇总结
本章呢接着上一篇说了Android动画的另外一个大类属性动画,至此Android动画相关的文章完结,因笔者水平有限,所以有不当之处还请指出
下篇预告
下篇呢,开始Android并发编程系列
参考博文
原文出处:https://www.cnblogs.com/wangle12138/p/9467084.html