码迷,mamicode.com
首页 > 移动开发 > 详细

Android:属性动画详解

时间:2015-06-16 16:44:36      阅读:118      评论:0      收藏:0      [点我收藏+]

标签:动画   android   

(一)简介

属性动画是Android 3.0中提供了新功能,便于对任意元素进行“平滑的过渡”。众所周知,Android 之前提供的补间动画如AlphaAnimation、TranslateAnimation等都只能应用在View上,并且几乎没有任何可扩展的地方。并且,使用原来的动画无法实现颜色渐变效果,算是一个遗憾。

属性动画彻底打破了这种设计方式,不再将这些动画强制的放在View上,而是仅仅产生一系列的值,由开发人员自行使用这些值。例如,属性动画可产生1~0平滑过渡的值,把这些值应用在View的alpha上就可以实现透明度渐变了。

同时,属性动画可以直接用来改变View的属性。例如,不断的setTranslationX,便可实现水平方向的平移。

(二)代码演示

1.ValueAnimator:产生某个范围内平滑过渡的值。

//属性动画,0~1渐变
    public void simpleValueAnimator(View view) {
        ValueAnimator anim = ValueAnimator.ofFloat(0f, 1f);
        anim.setDuration(300);
        //动画过程的监听
        anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                //回调方法在主线程执行
                float currentValue = (float) animation.getAnimatedValue();
                Log.d(TAG, "current value is " + currentValue);
            }
        });
        anim.start();
    }
(1)该方法可以通过设置多个值来实现更复杂的“平滑过渡”,例如实现0~5~3~10的过渡效果:
ValueAnimator anim = ValueAnimator.ofFloat(0f, 5f, 3f, 10f);
(2)设置启动延时、重复次数、重复模式:

//设置启动延时
        anim.setStartDelay(1000);
        //设置重复次数(也可以设置成无限次数)
        anim.setRepeatCount(3);
        //设置重复模式:重新执行动画(也可以设置成倒序)
        anim.setRepeatMode(ValueAnimator.RESTART);
(3)监听动画开始、结束、重复状态:

//监听动画的状态(开始/结束/重复/取消)
        anim.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationStart(Animator animation) {
                super.onAnimationStart(animation);
                Log.d(TAG, "onAnimationStart");
            }

            @Override
            public void onAnimationRepeat(Animator animation) {
                super.onAnimationRepeat(animation);
                Log.d(TAG, "onAnimationRepeat");
            }

            @Override
            public void onAnimationEnd(Animator animation) {
                super.onAnimationEnd(animation);
                Log.d(TAG, "onAnimationEnd");
            }
        });
2.ObjectAnimator:平滑的改变任意对象的属性值。

(1)平滑改变TextView的不透明度:

public void changeAlphaValue(View view) {
        TextView textView = (TextView) findViewById(R.id.main_text1);
        //ObjectAnimator继承自ValueAnimator
        //animator会调用textView的setAlpha方法。如果该方法不存在则会出现警告异常。
        ObjectAnimator animator = ObjectAnimator.ofFloat(textView, "alpha", 1f, 0f, 1f);
        animator.setDuration(3000);
        animator.start();
    }
该动画并非直接改变textView的alpha属性(事实上,textView甚至它的父组件View都没有alpha属性),而是调用textView的setAlpha方法,然后传入1~0~1平滑渐变的值作为参数,从而实现了不透明度渐变效果。

类似的,可以通过传递参数rotation、translationX(translationY)等实现旋转、平移等效果。

3.使用AnimatorSet将各个动画进行组合:

public void animatorSet(View view) {
        TextView textView = (TextView) findViewById(R.id.main_text1);
        ObjectAnimator moveIn = ObjectAnimator.ofFloat(textView, "translationX", -500f, 0f);
        ObjectAnimator rotate = ObjectAnimator.ofFloat(textView, "rotation", 0f, 360f);
        ObjectAnimator fadeInOut = ObjectAnimator.ofFloat(textView, "alpha", 1f, 0.2f, 1f);

        //先平移,然后在旋转的同时进行alpha渐变
        AnimatorSet animSet = new AnimatorSet();
        animSet.play(rotate).with(fadeInOut).after(moveIn);
        animSet.setDuration(5000);
        animSet.start();
    }
animSet.play会产生一个Animator.Builder对象,然后可以使用with,after,before等方法进行动画叠加。

4.自定义Evaluator,实现任意两个对象之间的“平滑过渡”。

ValueAnimator的ofInt,ofFloat方法很简单,无非是产生一些平滑过渡的数值。不过,ValueAnimator还有一个ofObject方法,可以实现两个Object之间的平滑过渡。显然,系统不可能知道应该怎么过渡,因此需要我们指定它。

例如定义了一个类表示点的坐标:

public class PointBean {
    private float x;
    private float y;

    public PointBean(float x, float y) {
        this.x = x;
        this.y = y;
    }

    public float getX() {
        return x;
    }

    public void setX(float x) {
        this.x = x;
    }

    public float getY() {
        return y;
    }

    public void setY(float y) {
        this.y = y;
    }
}
然后,我们希望实现两个点之间的平滑过渡(通过它就可以实现View的平移了),就需要定义两个PointBean之间是如何过渡的。当然此处的实现很简单:

public class PointEvaluator implements TypeEvaluator<PointBean> {
    @Override
    public PointBean evaluate(float fraction, PointBean startValue, PointBean endValue) {
        float x = startValue.getX() + fraction * (endValue.getX() - startValue.getX());
        float y = startValue.getY() + fraction * (endValue.getY() - startValue.getY());
        return new PointBean(x, y);
    }
}
参数fraction表示动画完成度(0.0~1.0的一个值),startValue表示开始点,endValue表示结束点,该方法需要返回从startValue过渡到endValue、完成比例是fraction时的结果。
然后,通过两个PointBean的过渡实现平移效果(此处仅为示意,实际场景中可以直接使用ObjectAnimator):

ValueAnimator animator = ValueAnimator.ofObject(new PointEvaluator(), startPoint, endPoint);
        animator.setDuration(2000);
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                PointBean current = (PointBean) animation.getAnimatedValue();
                imageView.setTranslationX(current.getX());
                imageView.setTranslationY(current.getY());
            }
        });
        animator.start();
5.实现颜色渐变

与上述内容相似,实现红色~绿色~蓝色的渐变:

ValueAnimator animator = ValueAnimator.ofObject(new ColorEvaluator(), "#ffff0000", "#ff00ff00", "#ff0000ff");
        animator.setDuration(5000);

        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                String currentColor = (String) animation.getAnimatedValue();
                textView.setBackgroundColor(Color.parseColor(currentColor));
            }
        });
        animator.start();
显然此处的重点是ColorEvaluator,即指定颜色值是如何渐变的。例如, #ffff0000是如何过渡到#ff00ff00的。
public class ColorEvaluator implements TypeEvaluator<String> {
    //仅支持AARRGGBB模式
    @Override
    public String evaluate(float fraction, String startValue, String endValue) {
        if (!startValue.startsWith("#") || !endValue.startsWith("#")) {
            throw new IllegalArgumentException("color must started with '#'.");
        }

        if (startValue.length() != 9 || endValue.length() != 9) {
            throw new IllegalArgumentException("startValue and endValue must be '#AARRGGBB'.");
        }

        int start_a, start_r, start_g, start_b;
        int end_a, end_r, end_g, end_b;

        //start
        start_a = getIntValue(startValue, 1, 3);
        start_r = getIntValue(startValue, 3, 5);
        start_g = getIntValue(startValue, 5, 7);
        start_b = getIntValue(startValue, 7, 9);

        //end
        end_a = getIntValue(endValue, 1, 3);
        end_r = getIntValue(endValue, 3, 5);
        end_g = getIntValue(endValue, 5, 7);
        end_b = getIntValue(endValue, 7, 9);

        return "#" + getHexString((int) (start_a + fraction * (end_a - start_a)))
                + getHexString((int) (start_r + fraction * (end_r - start_r)))
                + getHexString((int) (start_g + fraction * (end_g - start_g)))
                + getHexString((int) (start_b + fraction * (end_b - start_b)));
    }

    //从原始#AARRGGBB颜色值中指定位置截取,并转为int.
    private int getIntValue(String hexValue, int start, int end) {
        return Integer.parseInt(hexValue.substring(start, end), 16);
    }

    private String getHexString(int value) {
        String a = Integer.toHexString(value);
        if (a.length() == 1) {
            a = "0" + a;
        }

        return a;
    }
}
6.设置Interpolator,控制动画进行的方式,如匀速、逐渐加速、逐渐减速或先加速后减速等效果。此处和传统的动画很相似。同样,可以自定义Interpolator的实现。

anim.setInterpolator(new AccelerateInterpolator());  //逐渐加速的动画
7.ViewPropertyAnimator:使用属性动画为View设置动画效果的一种简便方式。

testImageView.animate().setDuration(2000).alpha(0.3f).rotationBy(360).yBy(160);
上述代码表示将testImageView的不透明度渐变至0.3,同时旋转360度、向下移动160px。

这里的方法都有两种形式,如rotation(360)表示旋转至360度的位置(不管起始状态是多少度,都旋转至360度),而rotationBy(360)表示旋转360度(如果起始位置不是0度,则结束时依然不是0度)。








Android:属性动画详解

标签:动画   android   

原文地址:http://blog.csdn.net/books1958/article/details/46518797

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!