第3.3.2节 动画
动画总共有三种:drawable动画、视图动画、属性动画。其中drawable动画、视图动画提供了最佳的兼容性,但是他们只能使用在视图上。从android 3.0开始,属性动画框架是创建动画的首选方法。这个框架去除了视图动画的局限性,可以为任何对象,而不仅仅是视图,创建动画。
1. drawable动画
drawable动画是Android上最简单的动画,顺序展示了一系列的drawable。帧动画,就像GIF图片,通过一系列Drawable依次显示来模拟动画的效果。
1.1 创建3个xml文件(drawable动画)这里我只贴一个 black_bg.xml
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" > <!-- 形状是由layout中的布局文件来实现的,这里只做修饰 --> <!-- 实心 --> <solid android:color="#000000"/> <!-- 渐变 --> <gradient android:startColor="#000000" android:endColor="#000000" android:centerColor="#000000" android:angle="90" /> <!-- 描边 --> <stroke android:width="2dp" android:color="#dcdcdc" /> <!-- 圆角 --> <corners android:radius="2dp" /> <padding android:left="10dp" android:top="10dp" android:right="10dp" android:bottom="10dp" /> </shape>
1.2 创建动画播放是帧顺序,3个XML文件按照如下顺序进行播放,animat.xml
<?xml version="1.0" encoding="utf-8"?> <animation-list xmlns:android="http://schemas.android.com/apk/res/android" > <item android:drawable="@drawable/black_bg" android:duration="50" /> <item android:drawable="@drawable/blue_bg" android:duration="50" /> <item android:drawable="@drawable/white_bg" android:duration="50" /> </animation-list>
1.3 创建framework层的视图,也就是我们的界面,这里用到了button,main.xml
<Button android:id="@+id/button1" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" android:text="Button" android:background="@drawable/animat" />
1.4 让我们自由操作动画 MainActivity.class
public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); final Button btn = (Button) this.findViewById(R.id.button1); btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub AnimationDrawable ad = (AnimationDrawable) btn.getBackground(); ad.setOneShot(true); ad.stop(); ad.start(); } }); } }
2. 视图动画
视图动画又称补间动画,极大的方便了用户实现View的动作,用户只需给出两个关键帧,系统则会通过一些算法将给定属性值在给定的时间内在两个关键帧间渐变。
优点:操作方便,实现视图的动作效果,提高用户的体验。
缺点:由于是视图动画,不能在不是视图的动画中使用,这时候你将自己从新定义;它仅仅在一个默认的属性集上运作,不会影响其它属性;无论你如何动作,最后动画结束视图还会回到先前的位置。
2.1 在res下创建文件夹anim,在新建一个xml文件,silde.xml
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android"> <!-- Translate 移动视图 --> <!-- Scale,改变视图尺寸 --> <!-- Rotate,翻转视图 --> <!-- Alpha,改变视图透明度 --> <translate android:duration="500" android:toYDelta="150%" android:toXDelta="50%"/> </set>
2.2 依然借助button,main.xml
<Button android:id="@+id/button1" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" android:text="Button" android:background="@drawable/blue_bg" />
2.3 让我们自由操作动画 MainActivity.class
public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); final Button btn = (Button) this.findViewById(R.id.button1); final Animation animation=AnimationUtils.loadAnimation(MainActivity.this, R.anim.silde); btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub btn.startAnimation(animation); } }); animation.setAnimationListener(new AnimationListener() { @Override public void onAnimationStart(Animation animation) { // TODO Auto-generated method stub } @Override public void onAnimationRepeat(Animation animation) { // TODO Auto-generated method stub } @Override public void onAnimationEnd(Animation animation) { // TODO Auto-generated method stub Toast.makeText(MainActivity.this, "end", Toast.LENGTH_LONG).show(); } }); } }
总结:视图动画操作也是非常简单的,看着比drawable都简单,非常的方便。
3. 属性property动画
Android 3.0引入了成为属性动画的动画框架。这个框架可以让你改变任何对象,而不仅仅是视图,它实际改变一个对象的值,而不仅仅是它的绘制方式。
在Property Animation中,可以对动画应用以下属性:
- Duration:动画的持续时间
- TimeInterpolation:属性值的计算方式,如先快后慢
- TypeEvaluator:根据属性的开始、结束值与TimeInterpolation计算出的因子计算出当前时间的属性值
- Repeat Country and behavoir:重复次数与方式,如播放3次、5次、无限循环,可以此动画一直重复,或播放完时再反向播放
- Animation sets:动画集合,即可以同时对一个对象应用几个动画,这些动画可以同时播放也可以对不同动画设置不同开始偏移
- Frame refreash delay:多少时间刷新一次,即每隔多少时间计算一次属性值,默认为10ms,最终刷新时间还受系统进程调度与硬件的影响
3.1 valueAnimator
所有属性动画的基类是ValueAnimator。该类需要一个开始值,结束值,持续时间,并且在每一个时间步骤中它都会计算出一个新值,动画的时间步骤由动画线程的速度决定。ValueAnimator封装了一个Interpolator计算时间和TypeAnimator计算属性值。
ValueAnimator animation = ValueAnimator.ofFloat(0f, 1f); animation.setDuration(1000); animation.start();
这里创建了一个动画,设置运行1000ms,以浮点值0开始,到浮点值1结束。注意这里的ofFloat()方法就是使用浮点的TypeAnimator。
这个代码现在没有任何用途。这里ValueAnimator计算的值还没有被使用。我们可以登记一个AnimatatorListener和一个ViewAnimator.AnimatorUpdateListener来监听动画事件。但是这并不方便,Android为了更加方便使用了ObjectAnimator。
3.2 objectAnimator
继承自ValueAnimator,要指定一个对象及该对象的一个属性,当属性值计算完成时自动设置为该对象的相应属性,即完成了Property Animation的全部两步操作。实际应用中一般都会用
- 对象应该有一个setter函数:set<PropertyName>(驼峰命名法)
- 如上面的例子中,像ofFloat之类的工场方法,第一个参数为对象名,第二个为属性名,后面的参数为可变参数,如果values…参数只设置了一个值的话,那么会假定为 目的值,属性值的变化范围为当前值到目的值,为了获得当前值,该对象要有相应属性的getter方法:get<PropertyName>
- 如果有getter方法,其应返回值类型应与相应的setter方法的参数类型一致。
如果上述条件不满足,则不能用ObjectAnimator,应用ValueAnimator代替。ObjectAnimator来改变某一对象的某一属性,但用ObjectAnimator有一定的限制,要想使用ObjectAnimator,应该满足以下条件:
tv=(TextView)findViewById(R.id.textview1); btn=(Button)findViewById(R.id.button1); btn.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { ObjectAnimator oa=ObjectAnimator.ofFloat(tv, "alpha", 0f, 1f); oa.setDuration(1000); oa.start(); } });
3.3 AnimationSet
我想大家该疑惑了,我光介绍类也不给点实际的例子,好吧,例子来了。AnimationSet把属性动画做成了集合。这里还用上面的button。
原图
放大下移,逐渐消失
程序比上面还简单:MainAcitvity.class
public class MainActivity extends Activity { @SuppressLint("NewApi") @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); final Button btn = (Button) this.findViewById(R.id.button1); final AnimatorSet set = new AnimatorSet();//实例化set final ObjectAnimator alpha = ObjectAnimator.ofFloat(btn, View.ALPHA, 0f);//透明度 final ObjectAnimator silde = ObjectAnimator.ofFloat(btn, View.TRANSLATION_Y, 100f); final ObjectAnimator scale = ObjectAnimator.ofFloat(btn, View.SCALE_X, 2f); btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub set.play(alpha).with(silde).after(scale); set.setDuration(1000); set.start(); } }); } }
这里我就不再写main.xml文件了,上面已经有了,真是越来越简单啊……有人说我这样写是不是通用性就差了,错了,我们也可以在xml文件中实现上述功能:
(1)在res文件夹下新建animator目录 animation.xml
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" > <objectAnimator android:duration="1000" android:propertyName="scalex" android:valueTo="2" android:valueType="floatType"> </objectAnimator> <objectAnimator android:duration="1000" android:propertyName="translationY" android:valueTo="100" android:valueType="floatType"> </objectAnimator> <objectAnimator android:duration="1000" android:propertyName="alpha" android:valueTo="0" android:valueType="floatType"> </objectAnimator> </set>
(2)在MainAcitvity.class中使用
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); final Button btn = (Button) this.findViewById(R.id.button1); final AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(MainActivity.this, R.animator.animation); btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub set.setTarget(btn); set.start(); } }); }
3.4 最后一个ViewPropertyAnimator
ObjectAnimator固然强大,也包含了几乎所有的功能,但是每个都需要提供详尽的API。也微微有点麻烦,最简洁的办法:
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); final Button btn = (Button) this.findViewById(R.id.button1); btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub btn.animate().x(200).y(200).alpha(0f); } }); }
这里只用了一句话btn.animate().x(200).y(200).alpha(0f);其余什么都不用。总结:属性动画增加了动画的功能,是动画变得更加的容易,更加的强大,不过在为了考虑很多3.0以前系统的用户,有时候也还是要用视图动画,但是属性动画必定是以后主要要使用的。
4. 总结
动画的使用在于我们多多lianxi,有问题可以给我留言。