Android动画简介
在3.0之前,Android给我们提供了两种动画模式,补间动画(Tween Animation,也叫View Animation)和逐帧动画(Frame Animation,也叫Drawable Animation)。
逐帧动画,就是类似gif,把很多张图片连续播放出来。
补间动画,可以实现View的淡入淡出、缩放、平移、旋转四种效果。对于一般的动画效果,其实补间动画是可以满足的,但是它还有几个致命的缺点。第一个是只能用在View上。第二个,动画过后,实际上只是View绘制的改变,而View的实际属性并没有改变。比如把一个按钮从区域A平移到了区域B,平移过后我们看到的按钮是移动到了区域B,但这时候去点击区域B上的按钮,并不会触发按钮的点击时间,而去点击按钮原来的区域A,反而会触发点击事件。第三个,它只支持前面说的淡入淡出、缩放、平移、旋转四种效果,如果我们想实现其他效果就不行了。
针对以上问题,Android在3.0开始引入了属性动画(Property Animation)。它的实现原理就是通过不断的修改目标对象的某一个属性,以此来实现动画的效果,也正因如此,它完美的解决了补间动画存在的几个问题。
我打算分两篇来记录一下属性动画的用法。这篇文章主要介绍属性动画的基础用法。更高阶的用法将记录在下一篇文章中。
ValueAnimator
ValueAnimator是属性动画最核心的一个类,包含属性动画的所有核心功能。我们在使用ValueAnimator时,一般需要两个步骤:
1.计算属性值
2.根据属性值的改变进行相应操作
ValueAnimator帮我们完成了第一个步骤,而我们要去做第二个步骤。具体我们可以这样:
ValueAnimator animator = ValueAnimator.ofFloat(0f, 1f);
animator.setDuration(500);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float currentValue = (float) animation.getAnimatedValue();
Log.d("TAG", "current value is:" + currentValue);
}
});
animator.start();
我们想把一个值在500毫秒内从0过度到1,在我们设置了初始值,结束值和持续时间后,ValueAnimator会帮我们完成这个过度。而在这个过程中,每一次值变化后,我们需要做哪些操作,就要我们自己来根据不同的情况去完成了。给animator添加一个UpdateListener,通过onAnimationUpdate()的回调,我们可以拿到当前的值,用这个值来做我们需要做的事情。
ObjectAnimator
ObjectAnimator是从ValueAnimator继承的,所以ValueAnimator的用法同样适用于ObjectAnimator。然而平时我们更多应用的可能是ObjectAnimator,因为它可以指定某一对象的某一属性,在计算完该属性的变化后,将计算后的值应用在该属性上,也就是完成了上面说的ValueAnimator中的两个步骤(帮我们在步骤2中将变化后的值应用在该属性上)。看看下面用法:
ObjectAnimator animator = ObjectAnimator.ofFloat(textview, "alpha", 1f, 0f);
animator.setDuration(1000);
animator.start();
我们在1000毫秒内将一个textview的透明度(alpha)从1变成0,这样就完成了1秒内将一个textview渐隐的动画效果。
看一下ofFloat()的参数,第一个参数就是我们的目标对象,第二个参数就比较有意思了,是我们要修改的该对象的属性值,是一个字符串类型的参数。这个字符串是怎么来的呢?是Textview的某个属性吗?这里就不卖关子了,我们看一下View的源码就会发现,它有一个setAlpha()的方法,我们正是通过这个方法来设置了这个textview的透明度。也正因此,ObjectAnimator的使用也是有几个限制条件的:
1.对象应该有一个setter函数
2.如上面的例子中,像ofFloat之类的工场方法,第一个参数为对象名,第二个为属性名,后面的参数为可变参数,如果values…参数只设置了一个值的话,那么会假定为目的值,属性值的变化范围为当前值到目的值,为了获得当前值,该对象要有相应属性的getter方法
3.如果有getter方法,其应返回值类型应与相应的setter方法的参数类型一致
同理我们可以通过这个方法来修改这个textview的旋转角度(rotation)、横向位移(translationX)、横向缩放(scaleX)等等属性。
说了这么多来一个小例子吧。我想要实现这样一种效果,界面上有一个按钮,点击之后,从屏幕左侧飞入一个textview,到达中间位置后旋转一圈同时透明度从1变为0再变为1,之后再以更快的速度从右侧飞出。
布局文件:
<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"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.administrator.animatortest.MainActivity">
<Button
android:id="@+id/btn_start_animation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Start"
/>
<TextView
android:id="@+id/tv_animator"
android:layout_centerInParent="true"
android:visibility="gone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Animator Test!!"/>
</RelativeLayout>
Activity:
public class MainActivity extends Activity{
private TextView tv;
private Button btn;
private ObjectAnimator animator;
private AnimatorSet animatorSet;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv = (TextView) findViewById(R.id.tv_animator);
btn = (Button) findViewById(R.id.btn_start_animation);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
ObjectAnimator moveIn = ObjectAnimator.ofFloat(tv, "translationX", -1000f, 0f);
moveIn.setDuration(2000);
ObjectAnimator rotate = ObjectAnimator.ofFloat(tv, "rotation", 0f, 360f);
rotate.setDuration(3000);
ObjectAnimator alpha = ObjectAnimator.ofFloat(tv, "alpha", 1f, 0f, 1f);
alpha.setDuration(3000);
ObjectAnimator moveOut = ObjectAnimator.ofFloat(tv, "translationX", 0f , 1000f);
moveOut.setDuration(1000);
animatorSet = new AnimatorSet();
animatorSet.play(rotate).with(alpha).after(moveIn).before(moveOut);
animatorSet.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
animatorSet.start();
}
});
tv.setVisibility(View.VISIBLE);
animatorSet.start();
}
});
}
}
效果动画就不贴啦(因为我不会= =)。基础用法篇就到这里了~
参考大神文章:
http://blog.csdn.net/guolin_blog/article/details/43536355
http://www.cnblogs.com/angeldevil/archive/2011/12/02/2271096.html