好的动画对于用户来说,是非常受欢迎的,可以为你的app带来人气。不管移动开发还是网站开发都会有动画,android作为移动开发的老大,当然也是有很炫的动画哦,在android上动画主要分为两种:传统动画与属性动画,在这里呢,我们主要关注属性动画,它相对传统动画,到底有哪些变化呢,既然有了传统动画,为什么谷歌还推出属性动画呢?那么下面我们就来一起探个究竟吧!
先来看使用传统动画实现一个图像平移的效果:
1. 传统动画平移
object_anim_test.xml (首先布局文件都是固定的)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="match_parent">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/qq"
android:id="@+id/qq" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="操作"
android:id="@+id/button"
android:gravity="center"
android:layout_gravity="center" />
</LinearLayout>
主要代码:
private ImageView qq;
private Button button;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.object_anim_test);
qq = (ImageView)findViewById(R.id.qq);
button = (Button)findViewById(R.id.button);
button.setOnClickListener(this);
qq.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.button:
traditionAnim();
break;
case R.id.qq:
Toast.makeText(this,"Clicked qq",Toast.LENGTH_SHORT).show();
break;
}
}
private void traditionAnim() {
TranslateAnimation animation = new TranslateAnimation(0,200,0,0);
animation.setDuration(2000);
animation.setFillAfter(true);
qq.startAnimation(animation);
}
经过实践,我们得出在动画执行完成之后,点击图片,并未弹出Toast,在原来图像的地方点击确弹出了Toast,这如果是用户在交互的话,他肯定会觉得莫名其妙的,这显然是不好的。那么下面我们使用属性动画来替换掉传统动画试一下:
private void objectAnim() { ObjectAnimator.ofFloat(qq,"translationX",0f,200f).setDuration(2000).start();
}
将onclick里面的 traditionAnim()换成objectAnim() 方法,部署执行,我们发现使用属性动画,在新的位置可以点击了,弹出了Toast,这说明属性动画不仅仅是调用了onDraw方法,而且是真正的改变了控件的位置,下面我们可以得出:
(1)传统动画,只是调用onDraw方法,控件并未真正的移动过去,因此在新的位置并不能响应点击事件,缺陷之一,所以传统动画只适合做界面的动画效果,不适合做动画的交互
(2)属性动画,它是真正的移动了控件的位置,即可以实现动画效果,而且完美的响应了动画交互,且效率更高。
既然是这样那么如何使用属性动画呢?
2.介绍属性动画的使用
public static ObjectAnimator ofFloat(Object target, String propertyName, float... values)
这是属性动画方法源码,第一个参数是表示那个控件,第二个参数表示动画属性(具体属性见下面),第三个参数是个可变参数,表示前面属性的一个变化范围,如上面的平移动画0f,200f,表示从0到200的变化。上面动画里面只有一个平移动画,那如果我们要使用多个动画结合在一起怎么办呢?下面我们介绍几种方式来实现:
方式1:动画异步执行,这些动画会同时执行
ObjectAnimator.ofFloat(qq,"translationX",0f,200f).setDuration(2000).start(); ObjectAnimator.ofFloat(qq,"translationY",0f,200f).setDuration(2000).start(); ObjectAnimator.ofFloat(qq,"rotation",0f,360f).setDuration(2000).start(); ObjectAnimator.ofFloat(qq,"alpha",0.2f,1.0f).setDuration(2000).start();
方式2:封装了属性动画,效率更高
PropertyValuesHolder p1 = PropertyValuesHolder.ofFloat("translationX",0f,200f);
PropertyValuesHolder p2 = PropertyValuesHolder.ofFloat("translationY",0f,200f);
PropertyValuesHolder p3 = PropertyValuesHolder.ofFloat("rotation",0f,360f);
PropertyValuesHolder p4 = PropertyValuesHolder.ofFloat("alpha",0f,1f);
ObjectAnimator.ofPropertyValuesHolder(qq,p1,p2,p3,p4).setDuration(2000).start();
方式3:
ObjectAnimator anim1 = ObjectAnimator.ofFloat(qq, "translationX", 0f, 200f);
ObjectAnimator anim2 = ObjectAnimator.ofFloat(qq, "translationY", 0f, 200f);
ObjectAnimator anim3 = ObjectAnimator.ofFloat(qq, "rotation", 0f, 360f);
ObjectAnimator anim4 = ObjectAnimator.ofFloat(qq, "alpha", 0.3f, 0.9f);
AnimatorSet set = new AnimatorSet();
set.setDuration(2000);
set.playTogether(anim1,anim2,anim3,anim4); //动画异步执行
set.start();
对于第三种方式使用非常的灵活,里面提供了一些非常奇妙的效果,如:
set.playSequentially(anim2,anim1,anim4,anim3); //按照动画的顺序同步执行,也就是执行完上一个动画之后才执行下一个动画,依次执行
set.play(anim2).after(anim4); //动画anim2在动画anim4执行之后才执行,
set.play(anim3).with(anim1); //动画anim3,anim1,anim4异步执行
//anim4动画与anim3异步执行完成之后anim2余anim1异步执行
set.play(anim2).after(anim4); //anim4动画先于anim2执行,也就是后面的动画先于前面的动画执行
set.play(anim3).before(anim1); //anim3先于anim1执行,也就是前面的动画先于后面的动画执行
使用这些可以制作出无比炫的动画。
传统动画有动画监听,当然属性动画也有监听,而且涉及的非常的友好,下面介绍属性动画监听:
3.属性动画监听
方式1:监听属性动画,需要重写4个方法
animator.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
Toast.makeText(ObjectAnimatorActivity.this,"anim end",Toast.LENGTH_SHORT).show();
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
});
方式2:相对于方式1,我们可以只关注我们自己关心的方法,而不需要全部重写
animator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
Toast.makeText(ObjectAnimatorActivity.this,"anim end",Toast.LENGTH_SHORT).show();
super.onAnimationEnd(animation);
}
});
涉及的够友好吧,我们只需实现我们想要的方法即可,这样呢,我们就可以对属性动画进行监听了。
最后,附上属性动画的常用属性:
* translationX/translationY
* X/Y
* rotation/rotationX/rotationY
* scaleX/scaleY
* alpha