Android中动画

在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动画不存在这个问题

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值