Android属性动画欣赏——ObjectAnimator与动画监听事件

传统动画的局限
传统动画(Animation)只是重绘动画(就是不断的调用相应的方法重绘,会耗费CPU资源),改变其显示位置,但是真正能响应事件的位置还在原处。因此不适宜做具有交互的动画效果,仅仅用来做一些显示性的效果。(包括位移、旋转、缩放、透明度四种动画)

比如将一个ImageView平移一段距离,且在ImageView上加上点击事件,显示的时候图片是平移了的,但是在点击平移后的图片不能响应点击事件,而点击原来的位置却能响应点击事件。


代码演示:
1.布局文件,包括一个按钮触发动画,一个ImageView用来显示动画,且ImageView自带有点击事件,点击之后能弹出一个Toast

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:layout_marginBottom="110dp"
        android:onClick="move"
        android:text="Move" />

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:background="@drawable/ic_launcher" />

</RelativeLayout>

2.代码实现

public class MainActivity extends Activity {
    ImageView iv;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        iv=(ImageView) findViewById(R.id.imageView);
        iv.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                Toast.makeText(MainActivity.this, "Clicked", Toast.LENGTH_SHORT).show();
            }
        });
    }

    public void move(View view) {
        //传统动画
        TranslateAnimation animation=new TranslateAnimation(0,200,0,0);
        animation.setDuration(1000);
        animation.setFillAfter(true);//使ImageView停在动画停止的位置
        iv.startAnimation(animation);

        //三种实现属性动画的途径

        //第一种
//      ObjectAnimator.ofFloat(iv, "translationX", 100F,150F).setDuration(1000).start();//平移
//      ObjectAnimator.ofFloat(iv, "rotation", 0F,180F).setDuration(2000).start();//旋转

        //第二种
//      //谷歌在PropertyValuesHolder类中对动画进行了优化,在使用多个属性动画时,能更加有效率,更加节省系统资源
//      PropertyValuesHolder p1=PropertyValuesHolder.ofFloat("translationX", 100F,200F,150F);
//      PropertyValuesHolder p2=PropertyValuesHolder.ofFloat("rotation", 0F,360F,180F);
//      ObjectAnimator.ofPropertyValuesHolder(iv, p1,p2).setDuration(1000).start();

        //第三种
        //提供了更加丰富的动画控制效果,可以一起显示,也可以按顺序显示,达到更加精细的操作效果
//      ObjectAnimator animator1=ObjectAnimator.ofFloat(iv, "translationX", 0F,200F);
//      ObjectAnimator animator2=ObjectAnimator.ofFloat(iv, "rotation", 0F,180F);
//      ObjectAnimator animator3=ObjectAnimator.ofFloat(iv, "translationY", 0F,200F);
//      AnimatorSet set = new AnimatorSet();
//      set.play(animator1).with(animator3);//animator1与animator3一起显示
//      set.play(animator2).after(animator1);//animator2在显示完animator1之后再显示
//      set.playTogether(animator1,animator2);//一起显示
//      set.playSequentially(animator1,animator2);//按照顺序显示
//      set.setDuration(5000);//记住setDuration要在play以及playXXX方法之后,否则,设置的时间是不起作用的
//      set.setInterpolator(new BounceInterpolator());//设置插值器,BounceInterpolator使得动画具有像小球落在地上回弹一样的效果,也要在play以及playXXX方法之后
//      set.start();


        ObjectAnimator animator=ObjectAnimator.ofFloat((Button)findViewById(R.id.button1), "alpha", 0F,1F); 
        //实现动画的监听
//      animator.addListener(new AnimatorListener() {//监听动画在不同的时间段所需要完成的操作
//          
//          @Override
//          public void onAnimationStart(Animator animation) {
//          }
//          
//          @Override
//          public void onAnimationRepeat(Animator animation) {
//          }
//          
//          @Override
//          public void onAnimationEnd(Animator animation) {
//              Toast.makeText(MainActivity.this, "The End", Toast.LENGTH_LONG).show();
//          }
//          
//          @Override
//          public void onAnimationCancel(Animator animation) {
//          }
//      }); 
        animator.addListener(new AnimatorListenerAdapter() {//便利类,只要实现需要的方法
            @Override
            public void onAnimationEnd(Animator animation) {
                Toast.makeText(MainActivity.this, "The End", Toast.LENGTH_LONG).show();//在动画结束后显示一个Toast
            }
        });
        animator.setDuration(1000);
        animator.start();
    }
}

在使用传统动画的时候,因为在代码中实现了将ImageView停在动画停止的位置,所以在第二次点击按钮的时候,会出现重影(并且点击停止后的机器人图片根本不会有Toast弹出)如下图:
这里写图片描述
源码:http://download.csdn.net/download/qq_22804827/9413534
而属性动画显示的时候,就算在显示的过程中点击机器人图片也会响应点击事件,弹出Toast。


在简单的了解了属性动画之后,实践一下,做一个比较流行的“卫星菜单”,演示效果如下:
这里写图片描述

1.布局文件

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <ImageView 
        android:id="@+id/iv_e"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:paddingLeft="5dp"
        android:paddingTop="5dp"
        android:src="@drawable/e"/>

    <ImageView 
        android:id="@+id/iv_d"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:paddingLeft="5dp"
        android:paddingTop="5dp"
        android:src="@drawable/d"/>

    <ImageView 
        android:id="@+id/iv_c"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:paddingLeft="5dp"
        android:paddingTop="5dp"
        android:src="@drawable/c"/>

    <ImageView 
        android:id="@+id/iv_b"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:paddingLeft="5dp"
        android:paddingTop="5dp"
        android:src="@drawable/b"/>

    <ImageView 
        android:id="@+id/iv_a"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:paddingLeft="2dp"
        android:paddingTop="2dp"
        android:src="@drawable/a"/>

</FrameLayout>

2.代码实现

public class MainActivity extends Activity implements OnClickListener {
    private int[] ivIds = { R.id.iv_a, R.id.iv_b, R.id.iv_c, R.id.iv_d, R.id.iv_e};
    private ImageView[] imageViews = new ImageView[ivIds.length];
    private boolean isOpen;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        for (int i = 0; i < ivIds.length; i++) {
            imageViews[i] = (ImageView) findViewById(ivIds[i]);
            imageViews[i].setOnClickListener(this);
        }
        isOpen=true;
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
        case R.id.iv_a: 
            executeAnim(isOpen);
            isOpen=!isOpen;
            break;
        default:
            Toast.makeText(MainActivity.this, "Clicked", Toast.LENGTH_SHORT).show();
            break;
        }
    }

    private void executeAnim(boolean isOpen) {
        if (isOpen) {
            float defRadius = TypedValue.applyDimension(
                    TypedValue.COMPLEX_UNIT_DIP, 100, this.getResources()
                            .getDisplayMetrics());
            double angle = 30f;
            for (int i = 1; i < 5; i++) {
                double sin = Math.sin(Math.toRadians(angle * (i - 1)));
                double cos = Math.cos(Math.toRadians(angle * (i - 1)));
                int x = (int) (defRadius * sin);
                int y = (int) (defRadius * cos);
                Log.d("坐标", angle + " " + x + " " + y);

                ObjectAnimator animator1=ObjectAnimator.ofFloat(imageViews[i],"X", 0F,x);
                ObjectAnimator animator2=ObjectAnimator.ofFloat(imageViews[i],"Y", 0F,y);
                AnimatorSet set=new AnimatorSet();                              
                set.playTogether(animator1,animator2);
                set.setInterpolator(new BounceInterpolator());//设置插值器,BounceInterpolator使得动画具有像小球落在地上回弹一样的效果
                set.setDuration(5000);
                set.start();
            }
        }
        else {
            for(int i=1;i<5;i++) {
                PropertyValuesHolder p1 = PropertyValuesHolder.ofFloat("X", imageViews[i].getX(),
                        0F);
                PropertyValuesHolder p2 = PropertyValuesHolder.ofFloat("Y", imageViews[i].getY(),
                        0F);
                ObjectAnimator.ofPropertyValuesHolder(imageViews[i], p1, p2)
                        .setDuration(500*i).start();
            }
        }
    }
}

源码与图片素材(在项目的资源文件夹下):
http://download.csdn.net/download/qq_22804827/9413530

  • 13
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值