android动画的使用(上-基本用法)
2017-02-22 10:14
525 查看
动画介绍
要开发一个优秀的app,除了功能强大以外,还得有优秀的UI设计,那么,掌握自定义View以及动画是非常有必要的,今天就来讲讲动画的使用。Android的动画可以分为三种:View动画、帧动画和属性动画。
动画介绍
View动画
xml中定义View动画
完全用代码创建View动画
View动画监听器
自定义动画
帧动画
属性动画
ValueAnimator
xml实现ValueAnimator
代码实现ValueAnimator
ObjectAnimator
xml实现ObjectAnimator
代码实现ObjectAnimator
AnimatorSet
xml实现AnimatorSet
代码实现AnimatorSet
PropertyValueHolder
animate方法
属性动画的监听器
总结
View动画
View动画又叫做补间动画,它有四种默认动画效果:平移(Translate)
缩放(Scale)
旋转(Rotate)
透明度(Alpha)
同时,它支持自定义动画,这个我们后面会将。
使用View动画也非常简单,主要有2种使用方式:
1. 在xml中定义动画,在代码中调用;
2. 完全用代码来写。
我们先来看下第一种使用方式
xml中定义View动画
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" android:fillAfter="true" android:duration="5000" android:interpolator="@android:anim/accelerate_decelerate_interpolator" android:shareInterpolator="true"> <alpha android:fromAlpha="0.5" android:toAlpha="1"> </alpha> <scale android:fromXScale="1" android:fromYScale="1" android:pivotX="0" android:pivotY="0" android:toXScale="2" android:toYScale="2"> </scale> <translate android:fromXDelta="0" android:fromYDelta="0" android:toXDelta="100" android:toYDelta="100"> </translate> <rotate android:fromDegrees="0" android:pivotX="0" android:pivotY="0" android:toDegrees="360"> </rotate> </set>
set标签用于一系列动画组合,在后面的属性动画里我们也会用到。其中
android:duration代表动画时长;
android:fillAfter表示动画结束后View是否停留在结束位置,true表示停留在结束位置;
android:interpolator是指插值器,我们后面再讲;
android:shareInterpolator表示所有动画是否共享一个插值器,true表示共享,false表示不共享,这时需要自己给每个动画设置插值器。
关于set标签有2个属性是需要注意的:
android:repeatMode有restart和reverse,分别表示连续重复和逆向重复。
android:repeatCount表示重复的次数。
这两个属性一定要注意,在xml的set中使用是无效的,在单独的View动画中使用是有效的。
在代码中要调用这个动画也非常简单:
Animation animation = AnimationUtils.loadAnimation( AnimationActivity.this, R.anim.test_animation); v.startAnimation(animation);//v此时代表一个button
下面看看效果:
就两行代码即可使用,如果是单独一个一个写animation而不是用set标签的,调用起来也非常方便,代码如下:
AnimationSet animationSet = new AnimationSet(true); Animation anim1 = AnimationUtils.loadAnimation(AnimationActivity.this, R.anim.test_animation_alpha); animationSet.addAnimation(anim1); Animation anim2 = AnimationUtils.loadAnimation(AnimationActivity.this, R.anim.test_animation_translate); animationSet.addAnimation(anim2); animationSet.setDuration(2000); animationSet.setFillAfter(true); v.startAnimation(animationSet);
下面看看完全用代码如何写。
完全用代码创建View动画
直接上代码了:AnimationSet animationSet = new AnimationSet(true); AlphaAnimation anim1 = new AlphaAnimation(0.5f, 1f); animationSet.addAnimation(anim1); TranslateAnimation anim2 = new TranslateAnimation(0f, 300f, 0f, 300f); animationSet.addAnimation(anim2); ScaleAnimation anim3 = new ScaleAnimation(1f, 2f, 1f, 2f, Animation.RELATIVE_TO_SELF, 0f, Animation.RELATIVE_TO_SELF, 0f); animationSet.addAnimation(anim3); animationSet.setDuration(2000); animationSet.setFillAfter(true); v.startAnimation(animationSet);
效果我就不展示了,其中要注意的是ScaleAnimation和RotateAnimation有一个旋转轴点的概念pivotX和pivotY,默认的旋转点都是控件的(0,0)处,上面代码我使用的就是左上角即(0,0)的点,具体效果大家可以自己去试试。
View动画监听器
AnimationListener,主要监听View动画的开始、重复以及结束这三个过程,使用也非常简单,如下代码所示:animationSet.setAnimationListener(new AnimationListener() { @Override public void onAnimationStart(Animation animation) { Toast.makeText(AnimationActivity.this, "动画开始了", Toast.LENGTH_SHORT).show(); } @Override public void onAnimationRepeat(Animation animation) { // TODO Auto-generated method stub } @Override public void onAnimationEnd(Animation animation) { Toast.makeText(AnimationActivity.this, "动画结束了", Toast.LENGTH_SHORT).show(); } });
自定义动画
创建自定义动画非常简单,只需要实现applyTransformation和initialize方法即可。在applyTransformation中完成自己想要实现的效果,在initialize中做一些初始化操作。下面我们来看下这两个方法。
* @param width Width of the object being animated * @param height Height of the object being animated * @param parentWidth Width of the animated object's parent * @param parentHeight Height of the animated object's parent */ public void initialize(int width, int height, int parentWidth, int parentHeight){ }
介绍都有,四个参数,子控件长宽和父控件长宽。
* @param interpolatedTime The value of the normalized time (0.0 to 1.0) * after it has been run through the interpolation function. * @param t The Transformation object to fill in with the current * transforms. */ protected void applyTransformation(float interpolatedTime, Transformation t) { }
第一个参数interpolatedTime为0.0~1.0的递增值,随着动画执行时间逐渐增大;而t可以用来获取初始变换矩阵Matrix,我们就是根据这个矩阵值的改变来进行动画的,并且往往会使用到Camera这个类来执行一些3D效果,下面我们看下代码实现。
/** * Created by bellnett on 2017/2/24. */ public class CustomAnimation extends Animation { private Camera mCamera; private float mCenterHeight; private float mCenterWdith; @Override public void initialize(int width, int height, int parentWidth, int parentHeight) { super.initialize(width, height, parentWidth, parentHeight); mCamera = new Camera(); setFillAfter(true); mCenterHeight = height / 2; mCenterWdith = width / 2; } @Override protected void applyTransformation(float interpolatedTime, Transformation t) { super.applyTransformation(interpolatedTime, t); Matrix matrix = t.getMatrix(); mCamera.save(); mCamera.translate(0,0,interpolatedTime * 300); mCamera.rotateY(interpolatedTime * 360); mCamera.getMatrix(matrix); mCamera.restore(); /* 以高度的中心点作为旋转中心 */ matrix.preTranslate(0,-mCenterHeight); matrix.postTranslate(0,mCenterHeight); } }
主要做了2个操作,一个是向Z轴平移了300,另一个是绕Y轴旋转360度,至于这个camera的类,它的坐标系是3D坐标,这里就不介绍了,感兴趣的可以自己去研究。要注意的还有最后两行代码,还记得之前我们说过,scale和rotate动画的旋转点初始化都是(0,0),这里通过preTranslate和postTranslate将按钮先向上平移一半的高度,等动画结束时再平移回来,这样的效果就相当于围绕(0,height/2)这个点做动画。
使用也非常简单
CustomAnimation customAnimation = new CustomAnimation(); customAnimation.setDuration(2000); customAnimation.setInterpolator(new LinearInterpolator()); view.startAnimation(customAnimation);
效果如下:
帧动画
帧动画的实现也非常简单,归为一下三部:在drawable中实现animation-list
给控件设置背景资源setBackgroundResource
实现AnimationDrawable对象
开启动画
xml代码实现:
<?xml version="1.0" encoding="utf-8"?> <animation-list android:oneshot="false" xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="@drawable/a1" android:duration="1000"></item> <item android:drawable="@drawable/a2" android:duration="1000"></item> <item android:drawable="@drawable/a3" android:duration="1000"></item> </animation-list>
其中oneshot这个属性表示动画的自动执行,false表示循环播放;true表示只执行一次,并且停留在最后一帧上。
调用代码实现:
view.setBackgroundResource(R.drawable.animation_drawable_test); AnimationDrawable animationDrawable = (AnimationDrawable) view.getBackground(); animationDrawable.start();
效果如下:
属性动画
属性动画是在android 3.0即API 11之后才出现的,因此要兼容低版本的android系统,必须使用nineoldandroids这个动画库来兼容,这个兼容库我就不说了,感兴趣的自己去下载试试。属性动画常用的有以下三个类:ValueAnimator、ObjectAnimator以及AniamtorSet,下面我们分别讲解。ValueAnimator
ValueAnimator从字面上看就能知道,它是一个值动画,也就是说,它不会包含具体的动画效果,只是值的变化,具体的动画需要我们根据这个值来做。那么如何使用这个ValueAnimator呢,我们分别从xml和用代码建立来讲解。xml实现ValueAnimator
(1)首先是总布局:<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="TestValueAnimator" android:text="testValueAnimator" android:textAllCaps="false"> </Button> <ImageView android:id="@+id/animatorIv" android:layout_width="50dp" android:layout_height="50dp" android:background="@drawable/a1" /> </LinearLayout>
很简单,一个按钮,一个图,用按钮来完成图的属性动画。
(2) 然后是动画的xml:
<?xml version="1.0" encoding="utf-8"?> <animator xmlns:android="http://schemas.android.com/apk/res/android" android:valueFrom="50" android:valueTo="300" android:valueType="intType" > </animator>
非常简单,值从50~300变化。
(3)下面我们看看在代码中如何调用:
public void TestValueAnimator(final View v) { ValueAnimator valueAnimator = (ValueAnimator) AnimatorInflater .loadAnimator(AnimatorActivity.this, R.animator.test_animator); valueAnimator.setDuration(2000); valueAnimator.setInterpolator(new LinearInterpolator()); valueAnimator.setTarget(iv1); valueAnimator.setRepeatMode(ValueAnimator.REVERSE); valueAnimator.setRepeatCount(2); valueAnimator.start(); valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { int value = (Integer) animation.getAnimatedValue(); iv1.getLayoutParams().width = value; iv1.getLayoutParams().height = value; iv1.requestLayout(); } }); }
(4)看下效果图:
前面说过了,ValueAnimator只是值变化的动画,没有具体的动画效果,因此,必须实现AnimatorUpdateListener这个监听类,来监听值得变化,然后根据值的变化来实现具体的动画,在这个例子中是实现图的长宽变化。
代码实现ValueAnimator
代码实现更加方便,请看如下代码:ValueAnimator valueAnimator = ValueAnimator.ofInt(50,300);
一句代码就能实现之前(2)中定义的动画,而且直接可以使用,不需要再调用AnimatorInflater类的loadAnimator()方法来载入动画。下面的调用和(3)中的一样,就不重复写了。
ObjectAnimator
ObjectAnimator就是可以直接实现属性动画的类了,相比ValueAnimator要使用地更加频繁,更加好用,下面我们看看ObjectAnimator的使用,也是分xml和代码实现。xml实现ObjectAnimator
(1)总布局代码不变,直接上动画的xml实现:<?xml version="1.0" encoding="utf-8"?> <objectAnimator xmlns:android="http://schemas.android.com/apk/res/android" android:propertyName="translationX" android:valueFrom="0" android:valueTo="300" android:valueType="floatType" > </objectAnimator>
有两点要注意:
1. 其中的valueType使用的是浮点数类型,主要是ImageView的setTranslationX方法的参数是浮点数类型的,因此我们要灵活运用。
2. 相比ValueAnimator,ObjectAnimator只比它多了一个android:propertyName参数,至于这个参数怎么填,我们可以根据我们需要设置动画的控件,输入setXXX来查看,后面XXX就是这个属性所填写的值。
(2)代码调用:
ObjectAnimator objectAnimator = (ObjectAnimator) AnimatorInflater .loadAnimator(AnimatorActivity.this, R.animator.test_animator); objectAnimator.setDuration(2000); objectAnimator.setRepeatMode(ValueAnimator.REVERSE); objectAnimator.setRepeatCount(2); objectAnimator.setTarget(iv1); objectAnimator.start();
和ValueAnimator差不多,只是不需要监听AnimatorUpdateListener,就能实现ImageView从0~300的X轴变化。
(3)效果图:
代码实现ObjectAnimator
代码实现也非常的简单:ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(iv1, "translationX", 0f, 300f); objectAnimator.setDuration(2000); objectAnimator.setRepeatMode(ValueAnimator.REVERSE); objectAnimator.setRepeatCount(2); objectAnimator.start();
和ValueAnimator有所不同的是,在使用ofXXX方法时可以直接设定target,而无需调用setTarget()方法了,具体效果和上面的相同。
AnimatorSet
xml实现AnimatorSet
(1)总布局不变,我们看下xml中AnimatorSet的实现,和AnimationSet类似,要注意的是有一个android:ordering属性,它有两个值together和sequentially,前者代表动画一起执行;后者表示动画按顺序执行:<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" android:ordering="together"> <objectAnimator android:propertyName="translationX" android:valueFrom="0" android:valueTo="300" android:valueType="floatType"> </objectAnimator> <objectAnimator android:propertyName="translationY" android:valueFrom="0" android:valueTo="300" android:valueType="floatType"> </objectAnimator> </set>
(2)然后是代码的调用,和ValueAnimator以及ObjectAnimator是一样的,只是没法设置repeatMode和repeatCount了:
AnimatorSet animatorSet = (AnimatorSet) AnimatorInflater.loadAnimator(AnimatorActivity.this, R.animator.test_animator); animatorSet.setDuration(2000); animatorSet.setTarget(iv1); animatorSet.start();
(3)看下效果:
代码实现AnimatorSet
代码实现也很方便:AnimatorSet animatorSet = new AnimatorSet(); animatorSet.setDuration(2000); ObjectAnimator objectAnimator1 = ObjectAnimator.ofFloat(iv1,"translationX",0f,300f); ObjectAnimator objectAnimator2 = ObjectAnimator.ofFloat(iv1,"translationY",0f,300f); animatorSet.playTogether(objectAnimator1,objectAnimator2); animatorSet.start();
效果和上面是一样的,playTogether对应xml中的together;还有一个方法playSequentially对应xml中的sequentially。
PropertyValueHolder
PropertyValueHolder的使用是类似AnimatorSet的,不过它只能同步执行动画,没法按顺序执行动画。所以当要同时执行多个动画的时候,PropertyValueHolder也是个不错的选择。下面看代码:PropertyValuesHolder propertyValuesHolder1 = PropertyValuesHolder.ofFloat("translationX",0f, 300f); PropertyValuesHolder propertyValuesHolder2 = PropertyValuesHolder.ofFloat("translationY",0f, 300f); ObjectAnimator.ofPropertyValuesHolder(iv1, propertyValuesHolder1, propertyValuesHolder2) .setDuration(2000).start();
效果和同步执行的AnimatorSet是一样的,效果图我就不贴了。
animate方法
animate是ViewPropertyAnimator类的一个方法,它支持链式操作,使用上算是属性动画的一种简便方式,请看如下代码:iv1.setPivotX(0f); iv1.setPivotY(0f); iv1.invalidate(); iv1.animate() .scaleX(2f) .scaleY(2f) .alpha(0.5f) .setDuration(2000) .withStartAction(new Runnable() { @Override public void run() { } }) .withEndAction(new Runnable() { @Override public void run() { runOnUiThread(new Runnable() { @Override public void run() { iv1.setAlpha(1.0f); iv1.setScaleX(1f); iv1.setScaleY(1f); } }); } }) .start();
其中要注意的有以下几点:
属性动画默认旋转点是中心点,因此要改变旋转点直接使用setPivotX和setPivotY,然后显示调用以下invalidate。
withStartAction和withEndAction都是API16添加进来的,因此如果要使用这两个方法必须api要在16及以上。
ViewPropertyAnimator也支持AnimatorListener和AnimatorUpdateListener,这个监听器我们在下面会讲。
下面看下效果图:
属性动画的监听器
属性动画一共有2个监听器:AnimatorListener
-AnimatorListenerAdapter
AnimatorUpdateListener
AnimatorListener一共有4个方法,start、end、cancel以及repeat,如果直接实现这个监听器就得重写这4个方法,不过,AnimatorListener提供了一个AnimatorListenerAdapter适配器,如果实现这个适配器的话,就可以有选择的重写以上4个方法。
AnimatorUpdateListener我们在上面讲解ValueAnimator时已经用过了,没看的请翻到上面。
下面看下代码:
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(iv1,"translationX",0f,300f); objectAnimator.setDuration(2000); objectAnimator.setRepeatCount(ValueAnimator.INFINITE); objectAnimator.setRepeatMode(ValueAnimator.REVERSE); objectAnimator.start(); objectAnimator.addListener(new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animation) { } @Override public void onAnimationEnd(Animator animation) { } @Override public void onAnimationCancel(Animator animation) { } @Override public void onAnimationRepeat(Animator animation) { } }); objectAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); } }); objectAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { } });
总结
最后我们总结一下:Animation对应View动画;Animator对应Property动画。
View动画使用之后,按钮的位置改变了,但是点击的位置还是原来的位置;属性动画使用之后,不仅位置改变,连点击的位置也会随着改变。因此,View动画适合做一些视觉效果;属性动画适合做一些交互式动画。
使用旋转和缩放时要注意旋转轴点,View动画默认是(0,0);而属性动画默认是控件的中心点。
帧动画应尽量避免使用,图片一多就容易引起OOM。
不管是View动画还是属性动画,单个动画都可以设置循环模式和循环次数,当多个动画组合时没法直接设置循环模式和循环次数。
相关文章推荐
- Android使用OrmLite数据库框架 之 基本用法
- Android中属性动画1----ObjectAnimator的基本使用(平移,缩放,渐变,旋转)
- Android中属性动画的基本用法
- Android属性动画完全解析(上),初识属性动画的基本用法
- Android属性动画完全解析(上),初识属性动画的基本用法
- Android 属性动画基本用法之代码实现
- Android属性动画的基本用法
- Android属性动画完全解析(上),初识属性动画的基本用法
- Android动画基本使用
- android中handler的一些总结以及使用(一)之handler的基本用法
- Android属性动画完全解析(上),初识属性动画的基本用法
- Android属性动画完全解析(上),初识属性动画的基本用法
- Android属性动画(一)之基本用法
- Android属性动画的基本使用
- android中Service的基本用法和IntentService的使用
- Android属性动画完全解析(上),初识属性动画的基本用法
- Android属性动画完全解析(上),初识属性动画的基本用法
- Android属性动画完全解析(上),初识属性动画的基本用法
- Android属性动画完全解析(上),初识属性动画的基本用法
- Android属性动画完全解析(上),初识属性动画的基本用法