Android 属性动画简介

3.0以前,android支持两种动画模式,tween animation,frame animation,在android3.0中又引入了一个新的动画系统:property animation,这三种动画模式在SDK中被称为property animation,view animation,drawable animation。

可通过NineOldAndroids项目在3.0之前的系统中使用Property Animation。

            tween animation:

               补间动画:支持简单的缩放、平移、旋转、透明度基本的动画,它只是改变了View对象绘制的位置,注意这是“绘制”,而不是实际的位置。比如你让一个button变成它的两倍大小,但是它能接受你点击的区域还是原来的button区域,没有做任何改变。

而且有一定的局限性。比如:你希望View有一个颜色的切换动画;你希望可以使用3D旋转动画;你希望当动画停止时,View的位置就是当前的位置,这个补间动画无法做到,虽然有个setFillAfter(停留在动画的最后一帧)和setFillBefore(停留在动画的第一帧),

(如果你想使用这两个属性,需要将setFillEnabled设置为true),但是还是建议用 property animation去取代补间动画。

             具体到类是 AlphaAnimation ScaleAnimation RotateAnimation TranslateAnimation,都是继承的Animation这个类,还有个动画集合类 AnimationSet,可以通过addAnimation的方法将几个补间动画 一起执行,无法设置动画执行的顺序。其中关于ScaleAnimation

和RotateAnimation 有几个参数需要说明下,就是int pivotXType,float pivotX,int pivotYType, float pivotY,其中pivotX和pivotY确定了动画缩放或者旋转的中心点,pivotXType和pivotYType有Animation.ABSOLUTE、Animation.RELATIVE_TO_SELF和Animation.RELATIVE_TO_PARENT

三种类型,Animation.ABSOLUTE:具体的坐标值,指绝对的屏幕像素单位;Animation.RELATIVE_TO_SELF:相对自己的坐标值,0.1f是指自己的坐标值乘以0.1;Animation.RELATIVE_TO_PARENT:相对父容器的坐标值,0.1f是指父容器的坐标值乘以0.1,我自己大多是

用Animation.RELATIVE_TO_SELF这种类型,比如当pivotXType和pivotYType都是Animation.RELATIVE_TO_SELF的时候,pivotX和pivotY都等于0.5时就表示动画从组件的中心点开始缩放或者旋转。

 

         property animation:

            属性动画:属性动画与 补间动画最大的区别就是它是真正的改变了view的属性,而且属性动画不止适用于view,还可以应用于任何对象,Property Animation只是表示一个值在一段时间内的改变,当值改变时要做什么事情完全是你自己决定的。

           具体类是ValueAnimator和ObjectAnimator这两个类,其中ObjectAnimator是继承ValueAnimator的。实际应用中一般都会用ObjectAnimator来产生某一对象的动画,但用ObjectAnimator有一定的限制,要求动画作用的对象提供该属性的get和set方法,目前用的比较多的是

alpha、scaleX、scaleY、rotation、rotationX、rotationY、translationX、translationY、X、Y和backgroundColor,这些属性基本能够满足一般的动画需求。使用示例如下:

           ObjectAnimator animator = ObjectAnimator.ofFloat(view, "alpha", 0.3f);第1个参数需要进行动画的view,第2个参数是需要改变的属性名,第3个参数其实是一个可变参数数组,比如这个例子就是view由当前的透明度变化到0.3f,如果是ObjectAnimator.ofFloat(view, "alpha", 0.3f,0.9f)

则表示view的透明度先直接变成0.3f,从0.3f才开始动画变到0.9f。之后再调用animator.start()方法即开始动画,这其中可以设置多个动画的相关参数,常用的有setDuration设置动画周期,addListener增加动画监听器,cancel()停止动画,end()结束动画,setRepeatCount()设置动画

重复的次数,如果为-1或者ObjectAnimator.INFINITE则表示一直循环进行动画,setRepeatMode()表示设置动画的模式,模式有ObjectAnimator.RESTART:重新执行动画  ObjectAnimator.REVERSE:反向执行动画。setStartDelay()设置动画执行的延时时间。

          同补间动画一样,属性动画里面同样有个动画集合类AnimatorSet用来多种动画同时执行,我认为比 补间动画的AnimationSet(注意两个不是一个类,一个是Animation ,一个是Animator)更好的地方就是AnimatorSet可以控制动画的执行顺序。

AnimatorSet.playSequentially()方法是顺序执行动画,AnimatorSet.playTogether()是同时执行动画。还有play().with/after/before的方法来控制动画的执行的顺序,但我用的时候感觉最好是作用于不同view的animator,如果是同一个view的animator感觉顺序是乱的。

         如果要同时对1个view进行多种动画的组合其实还有两种方法,第一种就是使用PropertyValuesHolder类。查看PropertyValuesHolder类的api可以发现其实PropertyValuesHolder的方法与ObjectAnimator很类似。PropertyValuesHolder可以作为ObjectAnimator.ofPropertyValuesHolder方法中

的一个可变参数,示例如下:

        PropertyValuesHolder alphaHolder = PropertyValuesHolder.ofFloat("alpha", 0.3f);

        PropertyValuesHolder scaleHolder = PropertyValuesHolder.ofFloat("scaleX", 1.5f);

        PropertyValuesHolder rotationHolder = PropertyValuesHolder.oInt("rotation", 360);

        PropertyValuesHolder translationHolder = PropertyValuesHolder.ofInt("translationY", -100);

        ObjectAnimator objectAnimator = ObjectAnimator.ofPropertyValuesHolder(btSet, alphaHolder, scaleHolder, rotationHolder, translationHolder);

        objectAnimator.start();

        第2种方法就是使用ViewPropertyAnimator类,ViewPropertyAnimator是API level 12 引进的,它是用来做针对View对象的多个属性动画功能,如果要同时变换一个View的多个属性的话,ViewPropertyAnimator提供了一种更方便和更适合的方法。

 而且由于多个属性的invalidate方法调用统一管理,而不是之前的分别调用,所以还会有一些性能优化。ViewPropertyAnimator的对象View.animate()直接获取,查看源码可以发现这其实是一个单例方法。

ViewPropertyAnimator实现上面的示例的动画则 view.animate().alpha(0.3f).scaleX(1.5f).rotation(360).translationY(-100).start(),更为简洁。

              其实ObjectAnimator里面还有两个比较重要的方法setInterpolator和setEvaluator。

              setInterpolator是设置动画的插值器,可以改变动画的动画绘制的速率,android里面有很多插值器,都是实现了Interpolator这个接口,里面只需要实现public float getInterpolation(float input)这个方法.

网上看到一个对interpolator解释很形象的说明:现在小明去买酱油,规定时间是1个小时到达,里程是1 公里;现在小明心里唯恐无法达到,所以先跑起来了,但因为体力消耗所以逐渐的慢下来了;然后成功到达。这样的一个过程中把小明逐渐慢下来的这个过程抽象出 来也就是 Interpolator  的工作;

当然 Interpolator 也可以控制小明先慢慢热身然后越跑越快最后达到。这个方法中 float input的参数的范围是0到1,当动画开始时为0,当动画结束时为1,我的理解就是一个与时间相关的系数,比如动画周期是1000毫秒,当动画执行到500毫秒时,这个方法出入的input就是0.5。

android官方提供了几种插值器,http://my.oschina.net/banxi/blog/135633 这篇文章介绍的很详细,每个插值器就是实现这个public float getInterpolation(float input)  方法中的算法不一样而已。

我使用的比较多的场景就是在改变焦点框的大小的时候 在这个方法里面不停的设置的焦点框的layoutparams。

@Override

    public float getInterpolation(float input) {

        if (focusView != null) {

            RelativeLayout.LayoutParams layoutParams = (LayoutParams) focusView.getLayoutParams();

            switch (focusSizeChange) {

            case 1:

                layoutParams.width = (int) (focusViewWidth - FOCUS_RATIO_WIDTH * input);//focusViewWidth是焦点框动画前的宽度,FOCUS_RATIO_WIDTH是焦点框变化前后的宽度的差值

                layoutParams.height = (int) (focusViewHight - FOCUS_RATIO_HEIGHT * input);//focusViewHight 是焦点框动画前的高度,FOCUS_RATIO_HEIGHT是焦点框变化前后的高度的差值

                break;

            case -1:

                layoutParams.width = (int) (focusViewWidth + FOCUS_RATIO_WIDTH * input);

                layoutParams.height = (int) (focusViewHight + FOCUS_RATIO_HEIGHT * input);

                break;

            default:

                break;

            }

            focusView.setLayoutParams(layoutParams);

        }

        return input;

    }

 

                     setEvaluator方法是设置view的属性计算器。android官方提供了3个evaluator,IntEvaluator:属性的值类型为int;FloatEvaluator:属性的值类型为float;ArgbEvaluator:属性的值类型为十六进制颜色值

ObjectAnimator中常用的用来设置view的背景,示例如下:

        ObjectAnimator colorAnim = ObjectAnimator.ofInt(btColor, "backgroundColor", CYAN, BLUE, RED);

        colorAnim.setEvaluator(new ArgbEvaluator());

        colorAnim.setRepeatCount(ValueAnimator.INFINITE);

        colorAnim.setRepeatMode(ValueAnimator.REVERSE);

        colorAnim.setDuration(3000);

        colorAnim.start();

 

                    上面这段代码的效果是view的背景会从青色逐渐变为蓝色再逐渐变为红色。其实setEvaluator方法用的比较多的是在ValueAnimator类中,ValueAnimator是需要指定属性,但是不需要操作的对象的属性一定要有getter和setter方法,

这里就是需要在setEvaluator方法中实现一个TypeEvaluator接口,属性对象由 valueAnimator.setObjectValues方法实现,ValueAnimator必须加入addUpdateListener监听器,在监听器里面不停的更新view的属性。

网上较多的一个实现图片抛物线动画的例子如下:

          ValueAnimator valueAnimator = new ValueAnimator();

         valueAnimator.setObjectValues(new PointF(0, 0));

         valueAnimator.setTarget(ivBoll);

         valueAnimator.setDuration(5000);

         valueAnimator.setEvaluator(new TypeEvaluator<PointF>() {

 

            @Override

            public PointF evaluate(float fraction, PointF startValue, PointF endValue) {//fraction 这个参数的值也是从0到1,我感觉与插值器里面的参数是一个意思,都是与时间相关的系数

                PointF p = new PointF();

                p.x = 1000 * fraction ;

                p.y = 590 * fraction *fraction;

                return p;

            }

        });

        valueAnimator.addUpdateListener(new AnimatorUpdateListener() {

 

            @Override

            public void onAnimationUpdate(ValueAnimator animation) {

                PointF p = (PointF) animation.getAnimatedValue();

                ivBoll.setX(p.x);

                ivBoll.setY(p.y);

            }

        });

        valueAnimator.start();

 

         到这里属性动画就介绍的差不多了,有了属性动画后,补间动画就基本很少使用了,但是还有一个地方还需要使用,就是布局动画里面,就是viewgroup里面添加view或者删除view时候的动画。使用比较多的场景就是在

adapterview、listview和gridview中。这里我们需要获取一个LayoutAnimationController对象,LayoutAnimationController可以控制子view进行动画的顺序,setOrder方法里面有3种类型:

LayoutAnimationController.ORDER_RANDOM-随机 ,LayoutAnimationController.ORDER_REVERSE-逆序  LayoutAnimationController.ORDER_NORMAL-顺序

示例如下:

private LayoutAnimationController getTopListAnim() {

       AnimationSet set = new AnimationSet(true);

        Animation animationAlpha = new AlphaAnimation(0.0f, 1.0f);

        animationAlpha.setDuration(470);

        set.addAnimation(animationAlpha);

        Animation animation = new TranslateAnimation(Animation.RELATIVE_TO_SELF, 0.0f, Animation.RELATIVE_TO_SELF, 0.0f, Animation.RELATIVE_TO_SELF,

                -3.0f, Animation.RELATIVE_TO_SELF, 0.0f);

        animation.setDuration(470);

        set.addAnimation(animation);

        LayoutAnimationController controller = new LayoutAnimationController(set, 0.5f);//第1个参数是动画类,第2个参数是指上一个子view动画完成后,下一个子view进行动画的延时时间

        return controller;

listview或者gridview使用的时候    gridview.setLayoutAnimation(getTopListAnim()); adapter.notifyDataSetChanged();

当然除了上述的3种排序之外,如果需要更为复杂的显示子view的顺序,那我们就需要继承LayoutAnimationController类并实现protected int getTransformedIndex(AnimationParameters params)这个方法

示例如下:

class MyLayoutAnimationController extends LayoutAnimationController {

        public static final int ORDER_CUSTOM = 7;

       private int row;//gridview的行数

        public MyLayoutAnimationController(Animation animation, float delay) {

            super(animation, delay);

            // TODO Auto-generated constructor stub

        }

        public MyLayoutAnimationController(Animation animation) {

            super(animation);

            // TODO Auto-generated constructor stub

        }

        public MyLayoutAnimationController(Context context, AttributeSet attrs) {

            super(context, attrs);

            // TODO Auto-generated constructor stub

        }

        @Override

        protected int getTransformedIndex(AnimationParameters params) {

            if (getOrder() == ORDER_CUSTOM) {//这里我们实现自己的顺序算法,我实现的是1个gridview从左上延对角线往右下显示子view的算法

                return params.index / row + params.index % row;//params.index是指子view在viewgroup中的索引

            }

            return super.getTransformedIndex(params);

        }

    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值