Android属性动画学习笔记(一)

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值