今天写这篇文章的冲动来源于前段时间的面试,那是一场自虐的面试啊。当时在南大参加苏州一家创业公司的面试,薪资过万,要求当然也贼高,问了好多一脸懵逼的问题,例如多线程具体实现方式有哪些,如何实现?gc的一些机制等等,当然,也被问到了有没有经常用动画效果,一般用什么动画?菜鸟的我当然只知道frame和tween两种啦,实现方式可以通过代码编写和xml文件实现,他又问到我会不会属性动画,当时真是一脸雾水,属性动画?什么鬼?《第一行代码》里有这个吗?面试完真想找个洞钻进去,无地自容啊。好了,闲话少扯了,下面步入正题吧。
在android3.0之前,我们常用的动画就是逐帧动画(frame-by-frame animation)和补间动画(tweened animation)两种,但是这两种动画有着很大的缺陷:
首先,在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; }} 最后,让我们运行一下看看效果吧:
从动态效果图可以看出:我们textview在经过传统动画移动后,仅仅是绘制的显示效果,textview其实仍在初始位置,并没有发生改变。
所以,在android3.0之后,谷歌推出属性动画(property animation)这一强大的动画,解决了之前传统动画的不足之处,更加灵活,不再局限于四种效果,它实际上是一种对值的不断操作的机制,实现了真正的动画效果,不再止于表面文章!
下面我们开始属性动画的详细学习:
/** * 将一个值从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信息如下:
数值的确是在慢慢变化,从0变化到6
属性动画中最常用的当属于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(); }效果图如下:
这里的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,答案是肯定的,这是我们下面要讲的内容
/** * 文本的组合动画,实现文本移动的时候改变透明度,比较常用、实用的功能: * 文本从无到有的展现给用户 */ 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对它们进行管理,指定它们的执行顺序。
运行一下,效果如下:
这个效果还是经常用到的,用户体验效果会好些。
onAnimationStart();//动画开始时调用
onAnimationEnd();//结束时调用
onAnimationRepeat();//重复时调用
onAnimationCancel();//取消时调用
如果不想实现以上所有方法,而是只需要实现某个方法时,我们可以在addListener()中传入AnimatorListenerAdapter,比如我们有这样一个需求:textview动画实现了从显示到消失的过程,即最终的alpha为0,textview被隐藏,成为透明的了,但是控件并没有真正消失,只是没有显示而已,那么为了节约空间,我们可以在动画结束时让textview内存释放掉,可以这样实现:
补充:本文仅作学习记录和供大家参考,转载请附上原文地址,如有不足和改进之处请提出,谢谢,另外感谢以下文章作者的宝贵使用经验总结!
参考文章:
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