Android动画一

Android动画分为视图动画和属性动画

Android框架定义了透明度、旋转、缩放、位移几种常见动画

一、视图动画

1.1 实现原理

  1、ViewGroup通过drawChild获取View的Animation(动画[ˌænɪˈmeɪʃn])的Transformation(变化、转换[ˌtrænsfəˈmeɪʃn])值
  2、调用canvas.concat(transformToApply.getMatrix()),通过矩阵运算完成动画帧
  3、动画没有完成会一直调用invalidate()

1.2 视图动画种类

  AlphaAnimation(透明度[ˈælfə]) 透明动画
  RotateAnimation 旋转动画
  TranslateAnimation 位移动画
  ScaleAnimation 缩放动画
  AnimationSet 动画集合
  视图动画不具备交互性,响应事件的位置在动画前的地方

1.3 透明度动画

    AlphaAnimation aa = new AlphaAnimation(0, 1);// 从透明到不透明
    aa.setDuration(1000);
    v.startAnimation(aa);

1.4 旋转动画

    // RotateAnimation ra = new RotateAnimation(0, 360, v.getWidth()/2, v.getHeight()/2);// 旋转开始角度结束角度,旋转中心
    RotateAnimation ra = new RotateAnimation(0, 360, RotateAnimation.RELATIVE_TO_SELF, 0.5f ,
            Animation.RELATIVE_TO_SELF, 0.5f);// 旋转开始角度结束角度,旋转中心
    ra.setDuration(1000);
    v.startAnimation(ra);

1.5 平移动画

    TranslateAnimation ta = new TranslateAnimation(0, 200, 0, 300);// x起动到终点 y起点到终点 相对值
    ta.setDuration(1000);
    v.startAnimation(ta);

1.6 缩放动画

    // ScaleAnimation sa = new ScaleAnimation(0, 2, 0, 2);// 缩放倍数 缩放中心
    ScaleAnimation sa = new ScaleAnimation(0, 2, 0, 2, ScaleAnimation.RELATIVE_TO_SELF, 0.5f,
            ScaleAnimation.RELATIVE_TO_SELF, 0.5f);// 以自身为中心
    sa.setDuration(1000);
    v.startAnimation(sa);

1.7 动画集合

    AnimationSet as = new AnimationSet(true);
    as.setDuration(1000);

    AlphaAnimation a = new AlphaAnimation(0, 1);
    a.setDuration(1000);
    as.addAnimation(a);

    TranslateAnimation t = new TranslateAnimation(0, 100, 0, 200);
    t.setDuration(1000);
    as.addAnimation(t);

    v.startAnimation(as);

1.8 动画监听

    // 动画监听
    as.setAnimationListener(new Animation.AnimationListener() {
        @Override
        public void onAnimationStart(Animation animation) {

        }

        @Override
        public void onAnimationEnd(Animation animation) {

        }

        @Override
        public void onAnimationRepeat(Animation animation) {

        }
    });

1.9 运行效果

 

二、属性动画

  Animator动画师,通过这个也可以区分是否属性动画
  与视图动画对应的有AnimatorSet、ObjectAnimator
  ObjectAnimator只控制对象的一个属性
  ObjectAnimator可以自己驱动,调用setFrameDelay(longframeDelay)设置动画帧之间的间隙时间,减少动画过程中频繁绘制,在不影响效果前提下减少cpu资源消耗
  ObjectAnimator通过调用属性的get、set方法来控制一个View的属性值

2.1 ObjectAnimator使用  

  使用静态工厂类返回ObjectAnimator对象,参数包括对象属性名字,属性必须有get、set方法,内部通过java反射机制调用

2.2 属性动画包含的属性值

  属性必须有set、get方法,否则ObjectAnimator无效
  translationX translationY
  rotation rotationX rotationY
  scaleX scaleY
  pivotX pivotY View对象的支点位置,围绕支点进行缩放、变换处理,默认就是View的中心点
  x y 就是左上角坐标和translationX、translationY的累计和
  alpha

2.3 没有get、set方法的解决

  1、通过包装类增加get、set方法

rivate static class WrapperView{
        private View mTarget;

        public WrapperView(View target){
            this.mTarget = target;
        }

        public int getWidth(){
            return mTarget.getLayoutParams().width;
        }

        public void setWidth(int width){
            mTarget.getLayoutParams().width = width;
            mTarget.requestLayout();
        }

    }

    WrapperView wrapper = new WrapperView(view);
    ObjectAnimator animator1 = ObjectAnimator.ofInt(wrapper, "width", 500);
    animator1.setDuration(5000).start();

  2、通过ValueAnimator提供的变化值,自己实现动画效果  

    ObjectAnimator继承自ValueAnimator,那么就通过ValueAnimator提供的值,由调用者控制动画的实现过程
    ValueAnimator本身不提供任何动画效果
    ValueAnimator animator2 = ValueAnimator.ofFloat(0, 100);
    animator2.setTarget(view);
    animator2.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            Float value = (Float) animation.getAnimatedValue();
            System.out.println(value);
        }
    });
    animator2.setDuration(1000).start();

2.4 动画监听

    监听全部事件
    animator.addListener(new Animator.AnimatorListener() {
        @Override
        public void onAnimationStart(Animator animation) {

        }

        @Override
        public void onAnimationEnd(Animator animation) {

        }

        @Override
        public void onAnimationCancel(Animator animation) {

        }

        @Override
        public void onAnimationRepeat(Animator animation) {

        }
    });
    监听部分事件
    animator.addListener(new AnimatorListenerAdapter() {
        @Override
        public void onAnimationEnd(Animator animation) {
            super.onAnimationEnd(animation);
        }
    });

2.5 动画集合

  1、使用PropertyValuesHolder

    PropertyValuesHolder p1 = PropertyValuesHolder.ofFloat("translationX", 300f);
    PropertyValuesHolder p2 = PropertyValuesHolder.ofFloat("scaleX", 1f, 0f, 1f);
    PropertyValuesHolder p3 = PropertyValuesHolder.ofFloat("scaleY", 1f, 0f, 1f);
    ObjectAnimator anim = ObjectAnimator.ofPropertyValuesHolder(view, p1, p2, p3);
    anim.setDuration(1000).start();

  2、使用AnimatorSet

  AnimatorSet可以实现更精确的顺序控制
  playTogether(一起[təˈgeðə(r)]) 同时
  playSequentially(顺序[sɪ'kwenʃəlɪ]) 顺序
  animSet.play().with() 一起执行
  defore()之前
  after() 之后

    ObjectAnimator a1 = ObjectAnimator.ofFloat(view, "translationX", 300f);
    ObjectAnimator a2 = ObjectAnimator.ofFloat(view, "scaleX", 1f, 0f, 1f);
    ObjectAnimator a3 = ObjectAnimator.ofFloat(view, "scaleY", 1f, 0f, 1f);
    AnimatorSet set = new AnimatorSet();
    set.setDuration(1000);
    set.playTogether(a1, a2, a3);
    set.start();

2.6 运行效果

  

 

三、源码

3.1 视图动画

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        findViewById(R.id.button).setOnClickListener(this);
        findViewById(R.id.button2).setOnClickListener(this);
        findViewById(R.id.button3).setOnClickListener(this);
        findViewById(R.id.button4).setOnClickListener(this);
        findViewById(R.id.button5).setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.button:
                AlphaAnimation aa = new AlphaAnimation(0, 1);// 从透明到不透明
                aa.setDuration(1000);
                v.startAnimation(aa);
                break;

            case R.id.button2:
                // RotateAnimation ra = new RotateAnimation(0, 360, v.getWidth()/2, v.getHeight()/2);// 旋转开始角度结束角度,旋转中心
                RotateAnimation ra = new RotateAnimation(0, 360, RotateAnimation.RELATIVE_TO_SELF, 0.5f ,
                        Animation.RELATIVE_TO_SELF, 0.5f);// 旋转开始角度结束角度,旋转中心
                ra.setDuration(1000);
                v.startAnimation(ra);
                break;

            case R.id.button3:
                TranslateAnimation ta = new TranslateAnimation(0, 200, 0, 300);// x起动到终点 y起点到终点 相对值
                ta.setDuration(1000);
                v.startAnimation(ta);
                break;

            case R.id.button4:
                // ScaleAnimation sa = new ScaleAnimation(0, 2, 0, 2);// 缩放倍数 缩放中心
                ScaleAnimation sa = new ScaleAnimation(0, 2, 0, 2, ScaleAnimation.RELATIVE_TO_SELF, 0.5f,
                        ScaleAnimation.RELATIVE_TO_SELF, 0.5f);// 以自身为中心
                sa.setDuration(1000);
                v.startAnimation(sa);
                break;

            case R.id.button5:
                AnimationSet as = new AnimationSet(true);
                as.setDuration(1000);

                AlphaAnimation a = new AlphaAnimation(0, 1);
                a.setDuration(1000);
                as.addAnimation(a);

                TranslateAnimation t = new TranslateAnimation(0, 100, 0, 200);
                t.setDuration(1000);
                as.addAnimation(t);

                v.startAnimation(as);
                // 动画监听
                as.setAnimationListener(new Animation.AnimationListener() {
                    @Override
                    public void onAnimationStart(Animation animation) {

                    }

                    @Override
                    public void onAnimationEnd(Animation animation) {

                    }

                    @Override
                    public void onAnimationRepeat(Animation animation) {

                    }
                });
                break;
        }
    }
}

3.2 属性动画

public class ActivityAnimatorActivity extends Activity implements View.OnClickListener {


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_animator);

        findViewById(R.id.button6).setOnClickListener(this);
        findViewById(R.id.button7).setOnClickListener(this);
        findViewById(R.id.button8).setOnClickListener(this);
        findViewById(R.id.button9).setOnClickListener(this);
        findViewById(R.id.button10).setOnClickListener(this);
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.button6:
                ObjectAnimator animator = ObjectAnimator.ofFloat(
                        view,
                        "translationX",
                        300
                );
                animator.setDuration(300);
                animator.addListener(new Animator.AnimatorListener() {
                    @Override
                    public void onAnimationStart(Animator animation) {

                    }

                    @Override
                    public void onAnimationEnd(Animator animation) {

                    }

                    @Override
                    public void onAnimationCancel(Animator animation) {

                    }

                    @Override
                    public void onAnimationRepeat(Animator animation) {

                    }
                });
                animator.addListener(new AnimatorListenerAdapter() {
                    @Override
                    public void onAnimationEnd(Animator animation) {
                        super.onAnimationEnd(animation);
                    }
                });
                animator.start();
                break;

            case R.id.button7:
                WrapperView wrapper = new WrapperView(view);
                ObjectAnimator animator1 = ObjectAnimator.ofInt(wrapper, "width", 500);
                animator1.setDuration(5000).start();
                break;

            case R.id.button8:
                ValueAnimator animator2 = ValueAnimator.ofFloat(0, 100);
                animator2.setTarget(view);
                animator2.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                    @Override
                    public void onAnimationUpdate(ValueAnimator animation) {
                        Float value = (Float) animation.getAnimatedValue();
                        System.out.println(value);
                    }
                });
                animator2.setDuration(1000).start();

                break;

            case R.id.button9:
                PropertyValuesHolder p1 = PropertyValuesHolder.ofFloat("translationX", 300f);
                PropertyValuesHolder p2 = PropertyValuesHolder.ofFloat("scaleX", 1f, 0f, 1f);
                PropertyValuesHolder p3 = PropertyValuesHolder.ofFloat("scaleY", 1f, 0f, 1f);
                ObjectAnimator anim = ObjectAnimator.ofPropertyValuesHolder(view, p1, p2, p3);
                anim.setDuration(1000).start();
                break;

            case R.id.button10:
                ObjectAnimator a1 = ObjectAnimator.ofFloat(view, "translationX", 300f);
                ObjectAnimator a2 = ObjectAnimator.ofFloat(view, "scaleX", 1f, 0f, 1f);
                ObjectAnimator a3 = ObjectAnimator.ofFloat(view, "scaleY", 1f, 0f, 1f);
                AnimatorSet set = new AnimatorSet();
                set.setDuration(1000);
                set.playTogether(a1, a2, a3);
                set.start();
                break;
        }
    }

    private static class WrapperView{
        private View mTarget;

        public WrapperView(View target){
            this.mTarget = target;
        }

        public int getWidth(){
            return mTarget.getLayoutParams().width;
        }

        public void setWidth(int width){
            mTarget.getLayoutParams().width = width;
            mTarget.requestLayout();
        }

    }

}

  

  

posted @ 2015-12-03 16:53  轻云沉峰  阅读(211)  评论(0)    收藏  举报