Android必备技能之属性动画

      今天写这篇文章的冲动来源于前段时间的面试,那是一场自虐的面试啊。当时在南大参加苏州一家创业公司的面试,薪资过万,要求当然也贼高,问了好多一脸懵逼的问题,例如多线程具体实现方式有哪些,如何实现?gc的一些机制等等,当然,也被问到了有没有经常用动画效果,一般用什么动画?菜鸟的我当然只知道frame和tween两种啦,实现方式可以通过代码编写和xml文件实现,他又问到我会不会属性动画,当时真是一脸雾水,属性动画?什么鬼?《第一行代码》里有这个吗?面试完真想找个洞钻进去,无地自容啊。好了,闲话少扯了,下面步入正题吧。

在android3.0之前,我们常用的动画就是逐帧动画(frame-by-frame animation)和补间动画(tweened animation)两种,但是这两种动画有着很大的缺陷:

  • 无法对非view的对象进行操作,比如值,坐标点之类的
  • 只有四种动画效果(淡入淡出、移动、旋转、缩放),功能局限
  • 仅仅改变了view的显示效果,并没有根本上改变view的位置等属性
1.举个例子看一下传统动画的缺陷之处:

首先,在activity'布局文件中加入一个textview和一个按钮,按钮用于控制文本的动画效果

布局文件如下:

xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:gravity="center"
    tools:context="test.myanimatortest.MainActivity">

    <TextView
        android:id="@+id/texts"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Everyday must be value for you."
        android:textSize="18sp"/>
    <Button
        android:id="@+id/anim_text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="文本动画"
        android:layout_margin="16dp"/>
LinearLayout>
接着,我们在activity中实现一下传统动画中移动效果:

/**
 * 传统动画效果translate
 */
private void oldTranslateAnimation(){
    //在竖直方向移动基于自身大小6倍的位置
    TranslateAnimation ta=new TranslateAnimation(Animation.RELATIVE_TO_SELF,0f,Animation.RELATIVE_TO_SELF,0f
            ,Animation.RELATIVE_TO_SELF,0f,Animation.RELATIVE_TO_SELF,6f);
    ta.setDuration(2000);
    ta.setFillAfter(true);//空间停留在动画结束的位置
    textview.startAnimation(ta);

}
方法很简单,不做叙述,用于实现textview的竖直方向平移,注意一点:为了方便观察效果,我们设置setFillAfter属性来保持textview在动画结束的地方

然后,我们给textview和button设置一下点击的监听器,实现:点击textview时可以toast一条信息,点击button可以执行动画效果:


@Override
textview= (TextView) findViewById(R.id.texts);
button= (Button) findViewById(R.id.anim_text);
button.setOnClickListener(this);
textview.setOnClickListener(this);
public void onClick(View v) { switch (v.getId()){ case R.id. anim_text: //传统的移动效果动画 oldTranslateAnimation(); break; case R.id. texts: Toast. makeText(MainActivity. this, "我是textview",Toast. LENGTH_SHORT).show(); break; }} 最后,让我们运行一下看看效果吧:

Android必备技能之属性动画_第1张图片


从动态效果图可以看出:我们textview在经过传统动画移动后,仅仅是绘制的显示效果,textview其实仍在初始位置,并没有发生改变。

所以,在android3.0之后,谷歌推出属性动画(property animation)这一强大的动画,解决了之前传统动画的不足之处,更加灵活,不再局限于四种效果,它实际上是一种对值的不断操作的机制,实现了真正的动画效果,不再止于表面文章!

下面我们开始属性动画的详细学习:

1.核心类ValueAnimator

  • 介绍:
ValueAnimator是属性动画中至关重要的一个类,因为属性动画的实现是通过不断对值进行操作完成的,初始值向结束值过渡的过程是通过ValueAnimator来负责计算实现的,它使用一种时间循环机制来计算两值之间的动画过渡。同时,ValueAnimator还负责管理动画的执行次数、模式以及监听器的实现。

  • 用法:
实现:将一个值从0过渡到6,执行时间为0.3s,实现代码如下:

/**
 * 将一个值从0过渡到3,打印出值变化过程
 */
private void valueAnimationUsage() {
    //ofxxx()方法中可以传入多个参数,不断过渡变化值
    ValueAnimator animator=ValueAnimator.ofInt(0,6);
    animator.setDuration(300);
    animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            int currentValue= (int) animation.getAnimatedValue();//获取当前的数据value
            Log.d("MainActivity","当前数据为:"+currentValue);
        }
    });
    animator.start();//启动动画
}
我们通过ofxxx(),如ofFloat(),ofInt()等方法传入值实现动画效果,并且可以传入多个值,此外,为了便于观察值之间的过渡效果,我们添加了一个ValueAnimator.AnimatorUpdateListener来监听数值的变化,点击按钮后,查看log信息如下:

Android必备技能之属性动画_第2张图片

数值的确是在慢慢变化,从0变化到6

2.ObjectAnimator类

  • 介绍:

属性动画中最常用的当属于ObjectAnimator这个类了,ValueAnimator虽然也经常用到,但是更多的是在我们看不见的地方,不像ObjectAnimator这样直观一点,

ObjectAnimator可以对任意对象的属性进行动画操作,比如常用的alpha、translationX、scaleX、rotation等等。

  • 用法:

实现:将文本textview先从不透明变为透明,再变为不透明:

代码实现如下:

/**
 * 文本透明度改变的动画,透明度从1-0-1
 */
private void textAlphaAnimation() {
    ObjectAnimator anim=ObjectAnimator.ofFloat(textview,"alpha",1f,0f,1f);
    anim.setDuration(3000);
    anim.start();
}
效果图如下:

Android必备技能之属性动画_第3张图片

这里的ofFolat()中传入的参数与使用ValueAnimator时是有区别的,这里的第一个参数是我们要操作的对象,即textview,第二个参数是设置改变它的属性,即透明度,后面就是透明度的变化值了,代码还是很简单的,不做过多叙述了,类似的还有旋转,移动,缩放效果,例如我们实现一下移动效果:

/**
 * 实现文本从初始位置向左移动直至消失,然后再回到初始位置的动画
 */
private void textTranslationAnimation() {
    float textLength=textview.getWidth();//获取文本的宽度
    ObjectAnimator anim=ObjectAnimator.ofFloat(textview,"translationX",0,-textLength,0);
    anim.setDuration(5000);
    anim.start();
}
textLength是文本textview的宽度,我们此处采用的是水平移动,效果图就不贴了,很简单的效果

那么我们可以将以上两种效果结合起来使用吗,实现文本一开始从屏幕外面平移过来并且透明度逐渐从0变为1,答案是肯定的,这是我们下面要讲的内容

3.AnimatorSet(组合动画)

  • 介绍:
独立动画实现的是比较简单的效果,当我们需要复杂效果时,官方为我们提供了AnimatorSet这个类来实现,它提供了play()方法传入Animator对象,然后可以调用以下方法:

  • after(Animator anim)   将现有动画插入到传入的动画之后执行
  • after(long delay)   将现有动画延迟指定毫秒后执行
  • before(Animator anim)   将现有动画插入到传入的动画之前执行
  • with(Animator anim)   将现有动画和传入的动画同时执行
也就是说,通过使用上面方法,我们可以设置动画的执行顺序以及在执行动画a的同时还可以执行动画b,很强大是吗,下面我们通过简单的例子实现一下看看:

  • 用法:
/**
 * 文本的组合动画,实现文本移动的时候改变透明度,比较常用、实用的功能:
 * 文本从无到有的展现给用户
 */
private void textSetAnimation() {
    ObjectAnimator translateIn = ObjectAnimator.ofFloat(textview, "translationX", -800f, 0f);
    ObjectAnimator alphaChange = ObjectAnimator.ofFloat(textview, "alpha", 0f, 1f);
    AnimatorSet animSet = new AnimatorSet();
    animSet.play(translateIn).with(alphaChange);
    animSet.setDuration(5000);
    animSet.start();
}
如代码所示,里面先定义了两个动画对象,然后通过AnimationSet对它们进行管理,指定它们的执行顺序。

运行一下,效果如下:

Android必备技能之属性动画_第4张图片

这个效果还是经常用到的,用户体验效果会好些。

4.Animator监听器

  • 介绍:
我们可以使用animator监听器监听动画事件,我们可以监听动画的开始,结束,重复,取消操作,并在相关状态进行一些逻辑处理。Animator类中提供了addListener()方法去监听动画事件,传入AnimatorListener,它为我们提供了四个方法:

onAnimationStart();//动画开始时调用

onAnimationEnd();//结束时调用

onAnimationRepeat();//重复时调用

onAnimationCancel();//取消时调用

如果不想实现以上所有方法,而是只需要实现某个方法时,我们可以在addListener()中传入AnimatorListenerAdapter,比如我们有这样一个需求:textview动画实现了从显示到消失的过程,即最终的alpha为0,textview被隐藏,成为透明的了,但是控件并没有真正消失,只是没有显示而已,那么为了节约空间,我们可以在动画结束时让textview内存释放掉,可以这样实现:

  1.  @Override  
  2.             public void onAnimationEnd(Animator animation)  
  3.             {  
  4.                 
  5.                 ViewGroup parent = (ViewGroup) textview.getParent();  
  6.                 if (parent != null)  
  7.                     parent.removeView(textview);  
  8.             }  
这样,就体现了动画监听的好处所在,好了今天就先到这里,下一篇文章将会记录xml方式编写属性动画,以及实现属性动画的一些高级技巧。

补充:本文仅作学习记录和供大家参考,转载请附上原文地址,如有不足和改进之处请提出,谢谢,另外感谢以下文章作者的宝贵使用经验总结!

参考文章:

http://blog.csdn.net/guolin_blog/article/details/43536355

http://blog.csdn.net/lmj623565791/article/details/38067475

http://www.cnblogs.com/kissazi2/p/4249213.html


你可能感兴趣的:(android,animator,动画,属性动画)