Android动画


  在Android动画实现中有两个框架:Animation 和 Animator,Animator是在Android4.0中添加的一个动画框架。

  Animation框架定义了透明度,旋转,缩放和位移几种常见的动画,而且控制的是一个整个View动画。通过不断调用onDraw方法去重绘界面,会很耗费GPU资源。

  在Animator框架中使用最多的是AnimatorSet和ObjectAnimator配合,使用ObjectAnimator进行更精细化控制,只控制一个对象的一个属性值,多个ObjectAnimator组合到AnimatorSet形成一个动画。

  使用Animation有一个很大的问题相信很多人也遇见过,比如写一个ImageView,给它添加一个点击事件,弹出Toast,然后对ImageView做一个很简单的动画效果。动画效果很完美,然后点击ImageView发现没有弹出Toast,点击开始位置,Toast弹出,这就很尴尬了。Animation只是重绘了动画,改变了ImageView的显示位置,但对于事件监听的位置却没有改变,所以Animation不适合做具有交互功能的动画效果。

  所以还是学习Animator动画,紧跟Google爸爸的潮流。

Animator

ObjectAnimator使用


  ObjectAnimator类是在Animator动画中最常使用到的一个类。

       //Animation旧版动画实现方法,只是不断调onDraw方法重绘,事件监听等还是在原地
       TranslateAnimation animation = new TranslateAnimation(0, 200, 0, 0);
       animation.setDuration(1000);
       animation.setFillAfter(true);
       mImageView.startAnimation(animation);
        //Animator既更改了图像的位置,又更改了事件监听的位置
        ObjectAnimator.ofFloat(mImageView, "translationX", 0F, 200F).setDuration(1000).start();


  上面两端代码实现的是同一个动画效果,将ImageView向右移动200,Animator的代码感觉会更简洁一些。ofFloat()中的四个参数分别为要操作的对象、要改变的属性、起始位置、结束位置。

常见属性

   alpha 透明度

   rotation z轴旋转

   rotationX x轴旋转

   rotationY y轴旋转

   translationX x水平偏移

   translationY y水平偏移

   ScaleX x轴缩放

   ScaleY y轴缩放

多个动画

        //几个操作会同时进行
        ObjectAnimator.ofFloat(mImageView, "translationY", 0F, 200F).setDuration(1000).start();
        ObjectAnimator.ofFloat(mImageView, "rotation", 0F, 360F).setDuration(1000).start();
        ObjectAnimator.ofFloat(mImageView, "translationX", 0F, 200F).setDuration(1000).start();


  有多个动画时,动画效果会是同时执行。当然这种情况Google也考虑到了,提供了另一种方式PropertyValuesHolder来完成上面的效果,并进行了一些优化

        //PropertyValuesHolder中Google做了一定优化
        PropertyValuesHolder p1 = PropertyValuesHolder.ofFloat("translationY", 0F, 200F);
        PropertyValuesHolder p2 = PropertyValuesHolder.ofFloat("rotation", 0F, 360F);
        PropertyValuesHolder p3 = PropertyValuesHolder.ofFloat("translationX", 0F, 200F);
        ObjectAnimator.ofPropertyValuesHolder(mImageView, p1, p2, p3).setDuration(1000).start();

动画顺序控制


  如果我们想将多个动画融合在一起,做成一个动画集合,一个执行完后另一个开始,可以使用AnimatorSet。

        //强大的动画顺序控制能力
        ObjectAnimator o1 = ObjectAnimator.ofFloat(mImageView, "translationY", 0F, 200F);
        ObjectAnimator o2 = ObjectAnimator.ofFloat(mImageView, "rotation", 0F, 360F);
        ObjectAnimator o3 = ObjectAnimator.ofFloat(mImageView, "translationX", 0F, 200F);
        AnimatorSet set = new AnimatorSet();
        set.play(o1).with(o3);
        set.play(o2).after(o1);
        // set.playTogether(o1, o2, o3);  //同时
        set.setDuration(1000);
        set.start();


  这样的一段代码使用AnimatorSet使用with让o1动画和o3动画同时执行,使用after让o2动画在o1、o3执行结束后再执行。AnimatorSet拥有强大的动画顺序控制能力。

动画监听


  我们可以为动画添加监听,在动画的各个时期做对应的操作。

        //添加动画监听
        o2.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {
                Toast.makeText(MainActivity.this, "Animation Start", Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onAnimationEnd(Animator animation) {
                Toast.makeText(MainActivity.this, "Animation End", Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onAnimationCancel(Animator animation) {

            }

            @Override
            public void onAnimationRepeat(Animator animation) {

            }
        });


  一般我们会使用其中的onAnimationStart和onAnimationEnd来判断动画是否开始、是否结束,而剩下的的两种就很少使用了。不想有这么多方法出现,我们可以使用另外一种添加监听的方法。

        //可以根据需求选择回调函数
        o2.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                super.onAnimationEnd(animation);
                Toast.makeText(MainActivity.this, "onAnimationEnd", Toast.LENGTH_SHORT).show();
            }
        });


  我只想要动画结束的监听就可以像上面一样,更简洁方便。

卫星菜单Demo


  效果图

  


  如果上面的动态效果图看不了


  


  每一个弹出的菜单都是一张图片,我们只需要将几张图片重叠放在一起,然后给除了最上面图片的所有图片添加一个向上的动画,移动的长度不同就可以达到弹出菜单的效果了。

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_animator);
        rl = (RelativeLayout) findViewById(R.id.rlativeLayout);
        im = (ImageView) findViewById(R.id.imageView_red);
        //找到每张图片,添加事件监听,并将ImageView对象存入一个List中
        for (int i = 0; i < ImageRes.length; i++) {
            ImageView imageView = (ImageView) findViewById(ImageRes[i]);
            imageView.setOnClickListener(this);
            ImageViewList.add(imageView);
        }
    }
private void startAnimator() {
        //确定启始的位置,Y轴是界面的高度
        int height = rl.getHeight();
        for (int i = 1; i < ImageRes.length; i++) {
            //分别对每个ImageView对象添加动画,在Y轴上向上移动 i*150,让每个图标之间相差150
            ObjectAnimator animator = ObjectAnimator.ofFloat(ImageViewList.get(i), "translationY", height, -i * 150);
            animator.setDuration(1000);
            animator.addListener(new AnimatorListenerAdapter() {
                @Override
                public void onAnimationEnd(Animator animation) {
                    //动画结束后可点击
                    im.setClickable(true);
                }

                @Override
                public void onAnimationStart(Animator animation) {
                    //动画开始后不可点击
                    im.setClickable(false);
                }
            });
            //差值器,使用不同的差值器作出不同的效果
            animator.setInterpolator(new AccelerateDecelerateInterpolator());
            animator.setStartDelay(i * 300);
            animator.start();
        }
    }


  结束的动画和startAnimator()基本相同,方向相反就可以了。

ValueAnimator


  数值发生器,可以实现很多很灵活的动画效果。动画效果都是通过ValueAnimator计算得出来的。ObjectAnimator就继承与ValueAnimator。

  下面代码实现了点击按钮,按钮上会在10秒的时间里从0显示到100,由于使用差值器,在动画过程中数字变化前后慢,中间快

public void Count(View view) {
        final Button button = (Button) view;
        ValueAnimator animator = ValueAnimator.ofInt(0, 100);
        animator.setDuration(10000);
        animator.setInterpolator(new AccelerateDecelerateInterpolator());
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                Integer val = (Integer) animation.getAnimatedValue();
                button.setText("" + val);
            }
        });
        animator.start();
    }


  我们可以通过类似的方式自己定义各种动画效果。


  代码地址

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值