属性动画只对
Android 3.0(API 11)以上版本的Android系统才有效
,对于低版本的可以使用开源动画库nineoldandroids
去实现兼容,该开源动画库在低版本的实现也是通过View动画
实现,只是使用方式像属性动画。属性动画可以设置给任何Object
,包括那些还没有渲染到屏幕上的对象。并且属性动画是可扩展的,可以让你自定义任何类型和属性的动画。
属性动画
-
相比 View 动画的优势
View 动画只能作用在 View 上面,而属性动画可以对任何对象做动画。View 动画只能支持四种简单的变换,而属性动画可以实现更加复杂的动画效果。 -
属性动画之间的关系
属性动画中有ValueAnimator
、ObjectAnimator
和AnimatorSet
等概念。其中ObjectAnimator
继承自ValueAnimator
,而AnimatorSet
是动画集合,可以定义一组动画。
实例
改变一个对象的 translationY 属性,让其沿着 Y 轴平移一段距离:对象的高度
btnTranslateAnim.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
ObjectAnimator.ofFloat(btnObjectAnim,"translationY",-btnObjectAnim.getHeight()).start();
}
});
改变一个对象的背景色属性,让背景色在 3s 内实现从红色到蓝色的渐变且动画会无限循环,有反转效果
btnChangeBgAnim.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
ValueAnimator colorAnim = ObjectAnimator.ofInt(btnObjectAnim,"backgroundColor",0xFFF8080,0xFF8080FF);
colorAnim.setDuration(3000);
colorAnim.setEvaluator(new ArgbEvaluator());
colorAnim.setRepeatCount(ValueAnimator.INFINITE);
colorAnim.setRepeatMode(ValueAnimator.REVERSE);
colorAnim.start();
}
});
动画集合,在 5s 内对 View 实现旋转、平移、缩放、透明度的改变
btnSetAnim.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.playTogether(
ObjectAnimator.ofFloat(btnObjectAnim,"rotationX",0,360),
ObjectAnimator.ofFloat(btnObjectAnim,"rotationY",0,180),
ObjectAnimator.ofFloat(btnObjectAnim,"rotation",0,90),
ObjectAnimator.ofFloat(btnObjectAnim,"translationX",0,90),
ObjectAnimator.ofFloat(btnObjectAnim,"translationY",0,90),
ObjectAnimator.ofFloat(btnObjectAnim,"scaleX",1,1.5f),
ObjectAnimator.ofFloat(btnObjectAnim,"scaleY",1,0.5f),
ObjectAnimator.ofFloat(btnObjectAnim,"alpha",1,0.25f,1)
);
animatorSet.setDuration(5 * 1000);
animatorSet.start();
}
});
属性动画推荐用 Java 代码实现
因为很多时候一个属性的起始值是无法提前确定的,比如让一个 Button 从屏幕的左边移动到屏幕的右边,由于我们无法提前知道屏幕的宽度,因此无法将属性动画定义在 XML 中,这种情况就必须通过代码来动态地创建属性动画。
属性动画的监听器
属性动画蹄冻了监听器用于监听动画的播放过程,主要有如下两个接口:
AnimatorUpdataListener
和AnimatorListener
-
AnimatorListener
的定义如下
public static interface AnimatorListener{
void onAnimationStart(Animator animation);
void onAnimationEnd(Animator animation);
void onAnimationCancel(Animator animation);
void onAnimationRepeat(Animator animation);
}
系统还提供了 AnimatorListenerAdapter
类,这样我们就可以有选择的实现上面的 4 个方法了,因为有时候不是每个方法我们都需要。
-
AnimatorUpdateListener
的定义如下
public static interface AnimatorUpdateListener{
void onAnimationUpdate(ValueAnimator animation);
}
AnimatorUpdateListener
比较特殊,它会监听整个动画过程,动画是由许多帧动画组成的,每播放一帧,onAnimationUpdate 就会被调用一次。
对任意属性做动画
属性动画要求动画作用的对象蹄冻该属性的 get 和 set 方法,属性动画根据外界传递的该属性初始值和最终值,以动画的效果多次去调用 set 方法,每次传递给 set 方法的值都不一样,最后所传递的值会接近最终值。
-
实例:将一个 Button 的宽度从当前宽度增加到 500px
Button 的内部虽然提供了 getWidth 方法和 setWidth 方法,但是这两个方法 Button 继承自 Text View 中的,而setWidth
方法是设置 TextView 的最大宽度和最小宽度,而 Button 通过 setWidth 方法是不能去修改控件的宽度。可以通过以下三个方法去实现。 -
方法1:给你的对象添加上 get set 方法,如果你有权限的话。
这里没有权限可以给 Button 添加上 get set 方法,所有方法1在这里不能实现。 -
方法2:用一个类来包装原始对象,间接为其提供 get set 方法
使用方便,容易理解,实现方式如下(在实现的效果会有一个闪烁的过程,不知道是什么原因...):
1. 定义一个包裹类
private static class ViewWrapper{
private View mTarget ;
public ViewWrapper(View target){
this.mTarget = target ;
}
public int getWidth(){
return mTarget.getLayoutParams().width ;
}
public void setWidth(int width){
mTarget.getLayoutParams().width = width ;
mTarget.requestLayout();
}
}
2. 调用包裹类实现属性动画
( mBtnObjectAnim 为要实现动画的对象 )
ViewWrapper viewWrapper = new ViewWrapper(mBtnObjectAnim);
ObjectAnimator.ofInt(viewWrapper,"width",500).setDuration(5000).start();
方法3:采用 ValueAnimator 监听动画过程,自己实现属性的改变
ValueAnimator valueAnimator = ValueAnimator.ofInt(1, 100);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
// 持有一个 IntEvaluator 对象方便下面估值的时候使用
IntEvaluator intEvaluator = new IntEvaluator();
@Override
public void onAnimationUpdate(ValueAnimator animation) {
// int currentVallue = (int) animation.getAnimatedValue();
float fraction = animation.getAnimatedFraction();
mBtnObjectAnim.getLayoutParams().width = intEvaluator.evaluate(fraction,start,end) ;
mBtnObjectAnim.requestLayout();
}
});
valueAnimator.setDuration(5000).start();
ok,属性动画就简单学到这里了~
源码地址
网友评论