×

Android-动画-属性动画

96
龙衣袭
2018.06.22 17:21 字数 990

属性动画只对Android 3.0(API 11)以上版本的Android系统才有效,对于低版本的可以使用开源动画库nineoldandroids去实现兼容,该开源动画库在低版本的实现也是通过View动画实现,只是使用方式像属性动画。属性动画可以设置给任何Object,包括那些还没有渲染到屏幕上的对象。并且属性动画是可扩展的,可以让你自定义任何类型和属性的动画。

属性动画

  • 相比 View 动画的优势
    View 动画只能作用在 View 上面,而属性动画可以对任何对象做动画。View 动画只能支持四种简单的变换,而属性动画可以实现更加复杂的动画效果。
  • 属性动画之间的关系
    属性动画中有ValueAnimatorObjectAnimatorAnimatorSet等概念。其中 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 中,这种情况就必须通过代码来动态地创建属性动画。

属性动画的监听器

属性动画蹄冻了监听器用于监听动画的播放过程,主要有如下两个接口:AnimatorUpdataListenerAnimatorListener

  • 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,属性动画就简单学到这里了~
源码地址

开发
Web note ad 1