Android中动画

来源:互联网 发布:家常菜做法知乎 编辑:程序博客网 时间:2024/06/01 23:05

在Api11(android3.0)之前,动画分两类:补间动画(Tween Animation)和帧动画(Frame Animation)

Api11(Android3.0)新加入了属性动画,动画分类:

                                                        1>View动画(补间动画)

                                                         2> 帧动画【其实帧动画也可归为View动画之一】

                                                         3>属性动画  

View动画

view动画通过对场景里的对象不断做图像变换(平移[translate]、旋转[rotate]、缩放[scale]、透明度[alpha])从而产生动画效果,它是一种渐近式动画,并且view动画支持自定义。


View动画的四种变换效果对应着Animation的四个类:TranslateAnimation、ScaleAnimation、RotateAnimation、AlphaAnomation--->对应标签分别:<translate>、<scale>、<rotate>、<alpha>


                                                          view动画四种变换

名称标签子类效果平移动画<translate>TranslateAnimation移动view缩放动画<scale>ScaleAnimation放大或缩小view旋转动画<rotate>RotateAnimation旋转view透明度动画<alpha>AlphaAnomation改变view的透明度

这四种动画可以通过xml来定义,也可以通过代码来动态创建【对于View动画来说,用xml定义比较方便些,可读性比较好】


好了,那就先来了解一下view动画的一些属性:

<set>表示动画集合,对应AnimationSet集合类,它可以包含若干个动画,并且它的内部是可以嵌套其他动画集合的,它的两个属性含义如下:

android:interpolator
表示动画集合所采用的插值器,插值器影响动画的速度,比如非匀速动画就需要通过插值器来控制动画的播放过程。这个属性可以不指定,默认@android:anim/accelerate_decelerate_interpolator,即加速减速插值器。
Accelerate_Decelerate_Interpolator 在动画开始与结束的地方速率改变比较慢,在中间的时候加速(加速减速插值器:动画两头慢中间快)Decelerate_Interpolator 在动画开始的地方快然后慢(减速插值器:动画越来越慢)Accelerate_Interpolator  在动画开始的地方速率改变比较慢,然后开始加速(加速插值器:动画越来越快)Linear_Interpolator   以常量速率改变(线性插值器:匀速动画)Anticipate_Interpolator 开始的时候向后然后向前甩Anticipate_Overshoot_Interpolator 开始的时候向后然后向前甩一定值后返回最后的值Bounce_Interpolator   动画结束的时候弹起Cycle_Interpolator 动画循环播放特定的次数,速率改变沿着正弦曲线Overshoot_Interpolator    向前甩一定值后再回到原来位置
android:shareInterpolator
表示集合中的动画是否和集合共享同一个插值器,如果集合不指定插值器,那么子动画就需要单独指定所需的插值器或者使用默认值

一些属性介绍:

fromXDelta:动画起始时 X坐标上的移动位置
toXDelta:动画结束时 X坐标上的移动位置
fromYDelta:动画起始时Y坐标上的移动位置
toYDelta:动画结束时Y坐标上的移动位置  


fromDegrees:旋转偏移的开始角度
toDegrees:旋转偏移的结束角度
pivotXType:指定X轴的旋转模式,可以取值Animation.ABSOLUTE(直接以屏幕为像素单位),
Animation.RELATIVE_TO_SELF(以自身为参照物),Animation.RELATIVE_TO_PARENT(相对于父容器)。
pivotXValue:指定旋转中心距离父容器左顶点的X距离
pivotYType:指定Y轴的旋转模式,可以取值Animation.ABSOLUTE,Animation.RELATIVE_TO_SELF,Animation.RELATIVE_TO_PARENT。
pivotYValue:指定旋转中心距离父容器上顶点的Y距离


fromAlpha:开始的透明度(1表示完成不透明,0表示完全透明
toAlpha: 结束的透明度


fromXScale:动画起始时 X坐标上的伸缩尺寸   
toXScale:动画结束时 X坐标上的伸缩尺寸   
fromYScale:动画起始时Y坐标上的伸缩尺寸   
fromYScale:动画结束时Y坐标上的伸缩尺寸   
pivotXType:指定X轴的伸缩模式,可以取值Animation.ABSOLUTE,Animation.RELATIVE_TO_SELF,Animation.RELATIVE_TO_PARENT。
pivotXValue:动画相对于物件的X坐标的开始位置  
pivotYType:指定Y轴的伸缩模式,可以取值Animation.ABSOLUTE,Animation.RELATIVE_TO_SELF,Animation.RELATIVE_TO_PARENT。
pivotYValue:动画相对于物件的Y坐标的开始位置 



下面来看一个怎样用xml方式实现:


创建好后来编辑一下文件内容,【当然这几种变换方式可以单独使用也可以混合使用】

<?xml version="1.0" encoding="utf-8"?><set xmlns:android="http://schemas.android.com/apk/res/android"    android:fillAfter="true"    >    <translate        android:duration="100"        android:fromXDelta="0"        android:fromYDelta="0"        android:toXDelta="100"        android:toYDelta="100"        android:interpolator="@android:anim/linear_interpolator"        />    <alpha        android:duration="100"        android:fromAlpha="1"        android:toAlpha="0"        /></set>

再在布局文件创建一个button

<Button        android:id="@+id/tran"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:text="动画测试"/>

最后在Activity中引入动画xml文件并启动

 Animation animation= AnimationUtils.loadAnimation(this,R.anim.viewanim); tranButton.startAnimation(animation);

ok,这样就实现了!!!


上面使用xml文件来加载的,当然也可以用java代码来实现

AlphaAnimation alphaAnimation=new AlphaAnimation(1,0);                alphaAnimation.setFillAfter(true);                alphaAnimation.setDuration(100);                tranButton.startAnimation(alphaAnimation);



view动画也可以用户Activity之间切换效果:

Activity本本身有默认的切换效果,当然我们也可以自定义来实现,主要用到下面这个方法:

overridePendingTransition(int enterAnim,int exitAnim),这个方法必须在startActivity(intent)或者finish()之后被调用才能生效


当Activity启动时,添加自定义切换效果

     Intent intent=new Intent(this,TranActivity.class);     startActivity(intent);     overridePendingTransition(R.anim.enter_anim,R.anim.exit_anim);                

当Activity退出时,添加自定义切换效果

    @Override    public void finish() {        super.finish();        overridePendingTransition(R.anim.enter_anim,R.anim.exit_anim);    }

例如:让Activity切换时呈现淡入淡出效果


<set xmlns:android="http://schemas.android.com/apk/res/android"    android:fillAfter="true"    >    <alpha        android:duration="1000"        android:fromAlpha="0.0"        android:toAlpha="1.0"        android:interpolator="@android:anim/accelerate_interpolator"        /></set>


<set xmlns:android="http://schemas.android.com/apk/res/android"    android:fillAfter="true"    >    <alpha        android:duration="1000"        android:fromAlpha="1.0"        android:toAlpha="0.0"        android:interpolator="@android:anim/decelerate_interpolator"        /></set>

然后再在Activity中引入即可!


View动画还可以在ViewGroup中控制子元素的出场效果


帧动画

帧动画是通过顺序播放一系列图像从而产生动画效果,如果图片过多或者过大易导致OOM。

下面来看下怎样实现帧动画:

首先在drawable文件夹下创建frame.xml文件


<?xml version="1.0" encoding="utf-8"?><animation-list xmlns:android="http://schemas.android.com/apk/res/android"    android:oneshot="false">    <!--oneshot代表着是否只展示一遍,设置为false会不停的循环播放动画  -->    <item android:drawable="@mipmap/p1" android:duration="100"></item>    <item android:drawable="@mipmap/p2" android:duration="100"></item>    <item android:drawable="@mipmap/p3" android:duration="100"></item>    <item android:drawable="@mipmap/p4" android:duration="100"></item>    <item android:drawable="@mipmap/p5" android:duration="100"></item>    <item android:drawable="@mipmap/p6" android:duration="100"></item>    <item android:drawable="@mipmap/p7" android:duration="100"></item>    <item android:drawable="@mipmap/p8" android:duration="100"></item>    <item android:drawable="@mipmap/p9" android:duration="100"></item></animation-list>
设置布局文件两个Button按钮和一个ImageView

<Button        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:onClick="startAnimation"        android:text="开始"        />    <Button        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:onClick="stopAnimation"        android:text="停止"        />
    <!--android:background="@drawable/frame"-->    <ImageView        android:id="@+id/my_img"        android:layout_width="wrap_content"        android:layout_height="wrap_content" />
最后在Activity加载资源文件
 private ImageView imageView;    private AnimationDrawable drawable;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);                imageView=(ImageView) MainActivity.this.findViewById(R.id.my_img);        imageView.setBackgroundResource(R.drawable.frame);        drawable=(AnimationDrawable) imageView.getBackground();    }    //开始    public void startAnimation(View view){        drawable.start();    }    //停止    public void stopAnimation(View view){        drawable.stop();    }

好了,帧动画比较简单一点,但是使用时要注意片过多或者过大易导致OOM。



属性动画  

属性动画是通过动态地改变对象的属性。一般情况下,所有补间动画的内容,都可以通过属性动画实现。

比较常用的几个动画类:ValueAnimator、ObjectAnimator、AnimatorSet(动画集合),其中ObjectAnimator继承ValueAnimator


                类与标签对应关系

类标签ValueAnimator

<animator>
ObjectAnimator
<objectAnimator>
AnimatorSet
<set>


下面举几个简单的例子:

1>让一个button在3秒内,从常规变为全透明,再从全透明变为常规状态

  ObjectAnimator animator=ObjectAnimator.ofFloat(tranButton,"alpha",1f,0f,1f);  animator.setDuration(3000);  animator.start();
2>改变一个对象的背景色属性,典型的情形是改变View的背景色

  ValueAnimator valueAnimator=ObjectAnimator.ofInt(tranButton,"backgroundColor",0xFFFF8080,0xFF8080FF);                valueAnimator.setDuration(3000);                valueAnimator.setEvaluator(new ArgbEvaluator());                valueAnimator.setRepeatCount(ValueAnimator.INFINITE);//无限重复                valueAnimator.setRepeatMode(ValueAnimator.RESTART);//重复模式:反向                valueAnimator.start();
3>AnimatorSet,5秒之内对view进行平移、旋转、缩放、透明度改变

    AnimatorSet set=new AnimatorSet();                set.playTogether(                 ObjectAnimator.ofFloat(tranButton,"rotationX",0,360),                 ObjectAnimator.ofFloat(tranButton,"rotationY",0,180),                 ObjectAnimator.ofFloat(tranButton,"rotation",0,-90),                 ObjectAnimator.ofFloat(tranButton,"translationX",0,90),                 ObjectAnimator.ofFloat(tranButton,"translationY",0,90),                 ObjectAnimator.ofFloat(tranButton,"scaleX",1,1.5f),                 ObjectAnimator.ofFloat(tranButton,"scaleY",1,0.9f),                 ObjectAnimator.ofFloat(tranButton,"alpha",1,0.2f,1f)                 );                set.setDuration(5000).start();

当然除了用代码实现之外,也可以用xml文件来实现:

在res/下创建animator文件夹



<set xmlns:android="http://schemas.android.com/apk/res/android"    android:ordering="together">    <!--together:表示集合中的子动画同时播放        sequentially:表示集合中的子动画按照前后顺序依次播放        -->    <objectAnimator        android:duration="2000"        android:valueFrom="-500"        android:valueTo="0"        android:propertyName="translationX"        android:valueType="floatType"        /></set>

Animator animator = AnimatorInflater.loadAnimator(MainActivity.this,R.animator.test_file);                animator.setTarget(tranButton);                animator.start();


好了,两种方式都已介绍完毕,但在实际开发中还是用代码来实现比较简单、方便些,因为有些时候属性的起始值可能不确定,用代码实现会灵活些!!!


附:一些属性介绍:

android:propertyName  表示属性动画作用对象的属性名称
android:valueType  表示propertyName 所指定的属性类型,有intType(整型)、floatType(浮点型)两个类型,但是如果propertyName指定的属性名表示颜色,则不用指定valueType,系统会自动处理
android:valueFrom  表示属性的起始值
android:valueTo   表示属性的结束值
android:duration    动画的时长
android:startOffset 表示动画的延迟时间,动画开始后,需要延迟多少毫秒之后才会真正执行播放
android:repeatCount 表示动画的重复次数---默认值为0,-1表示无限循环/"infinite":表示无限循环
android:repeatMode  表示动画的重复模式--- 值"reverse":表示反向  "restart":表示重新启动
属性动画的监听器
使用监听器监听动画的播放过程,我们只需要去实现这个AnimatorListener就可以监听动画的各种事件了。
animator.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) {//动画在重复执行时调用                    }
                });

但是很多时候我们不需要同时实现这么多方法,只需要用到一两个就可以了,这个时候我们可以这样做(可以勾选自己需要的方法):
animator.addListener(new AnimatorListenerAdapter() {                    @Override                    public void onAnimationStart(Animator animation) {                        super.onAnimationStart(animation);                    }                });
动画使用的一些注意事项:
 1>帧动画,当图片数量过且图片较大时,易OOM
 2>View动画是对View的影像做动画,View的真正状态并没有改变,因此有时候会出现动画完成后View无法隐藏,即setVisbility(View.GONE)失效了,这时只用调用view.clearAnimation()清除View动画即可解决
 3>属性动画有一类无限循环的动画,这类动画要在Activity退出时及时停止,否则将导致Activity无法释放。view动画不存在这个问题

原创粉丝点击