传统动画的局限
传统动画(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