Android动画(上)--补间动画、帧动画

Android动画分类

Android的动画可以分为三类:补间动画(Tween Animation)、帧动画(Frame Animation)、属性动画(Property Animation)。

三种动画的区别

补间动画又称View动画, 它通过对View对象不断做图形变化(缩放、平移、透明度、旋转)来产生动画效果,是一种渐进式动画。它产生的效果只是视觉上的变化,View的属性并没有发生改变。

帧动画是通过顺序播放一组图片而产生动画效果,但是图片过多过大的时候容易导致内存溢出,而且很占资源。

属性动画通过改变view对象的属性从而达到动画效果。

补间动画

补间动画有缩放、平移、旋转、透明度四种动画效果,分别对应Animation的ScaleAnimation、TranslateAnimation、RotateAnimation、AlphaAnimation这四个子类。

补间动画的使用方式有两种,一种是在res/anim/目录下通过 xml文件来定义动画 后在代码中调用,另一种通过 代码动态直接定义动画 调用。

1.缩放动画

顾名思义缩放动画就是对View进行逐步缩放来达到缩放的动画。

第一种使用方式:

在xml文件中使用的标签为<scale> </>定义缩放动画,然后代码调用。

<?xml version="1.0" encoding="utf-8"?>
<!--fromXScale fromYScale  toXScale toYScale 这几个属性的值是以view的宽高为基准-->
<!--fromXScale="0.5"  toXScale="2.0" 代表从自身宽度的0.5倍放大到自身宽度的2.0倍-->
<!--fromYScale="1.0"  toYScale="2.0" 代表从自身高度的1倍放大到自身高度的2.0倍-->
<!--pivotX,pivotY是缩放中心的坐标  有三种形式-->
<!--第一种固定值,点的坐标等于控件左上角的坐标加上pivotX,pivotY的值-->
<!--第二种以百分号结束 如pivotX="50%",代表缩放基点x的坐标为控件左上角的x坐标加上控件宽度的一半-->
<!--第三种以百分号加p结束 如pivotY="50%p",表示相对于控件的父控件的定位-->
<!--android:interpolator 插值器  用来控制动画的快慢变化-->

<scale xmlns:android="http://schemas.android.com/apk/res/android"
       android:interpolator="@android:anim/accelerate_decelerate_interpolator"
       android:duration="2000"
       android:fromXScale="1.0"
       android:fromYScale="1.0"
       android:pivotX="100"
       android:pivotY="100"
       android:toXScale="2.0"
       android:toYScale="2.0">
</scale>

基点.png

定义好xml动画后,紧接着动态代码中使用AnimationUtils将xml文件加载成一个Animation,然后调用view的startAnimation方法即可。

       Button button =(Button) findViewById(R.id.button);

       Animation scaleAnimation = AnimationUtils.loadAnimation(this, R.anim.scale_animation);
       scaleAnimation .setDuration(2000);//动画持续时长  可在这设置  也可在xml文件中定义
       mScaleAnimation.setFillAfter(true); // 动画结束后保持最后的状态 
       BounceInterpolator bounceInterpolator = new BounceInterpolator();  // 在动画结束时有回弹的插值器
       mAnimation.setInterpolator(bounceInterpolator);// 设置插值器 也可在xml文件中定义

       button.startAnimation(scaleAnimation1);// 开始动画  对button进行缩放
       
第二种使用方式:

代码中直接初始化一个ScaleAnimation对象,查看源码知道构造方法一共有四个,需要解释的是pointXType,pointYType的值一共有三个。

  //源码
    public static final int ABSOLUTE = 0;  // pointType传入该值则对应xml文件中的第一种形式标
    public static final int RELATIVE_TO_SELF = 1; // 相对控件本身的坐标 对应xml文件中 以百分号 %结束
    public static final int RELATIVE_TO_PARENT = 2; //  相对父布局的坐标  对应xml文件中以 %p 结束

    public ScaleAnimation(Context context, AttributeSet attrs) {
    }
    public ScaleAnimation(float fromX, float toX, float fromY, float toY) {
        // 该构造方法 pivotX,pivotY都为零   
    }
    public ScaleAnimation(float fromX, float toX, float fromY, float toY,
            float pivotX, float pivotY) {
        // 该构造方法 会给pivotType 赋默认值 ABSOLUTE    绝对坐标 
        mPivotXType = ABSOLUTE;
        mPivotYType = ABSOLUTE;
        省略 .....
    }
    public ScaleAnimation(float fromX, float toX, float fromY, float toY,
            int pivotXType, float pivotXValue, int pivotYType, float pivotYValue) {
      // 传入不同的pivotType值则对应不同的规则
        省略 .....
    }

使用:

        //pviontX,pivotY都为0
       ScaleAnimation scaleAnimation = new ScaleAnimation(1.0f, 2.0f, 1.0f, 2.0f);//pviontX,pivotY为绝对

         //等同于xml定义中第一种方式 pivotX和pivotY都为100
       ScaleAnimation scaleAnimation1 = new ScaleAnimation(1.0f, 2.0f, 1.0f, 2.0f,
              Animation.ABSOLUTE, 100, Animation.ABSOLUTE, 100);

        // 等同于xml定义中的第二种方式,相对控件本身的坐标
       ScaleAnimation scaleAnimation2 = new ScaleAnimation(1.0f, 2.0f, 1.0f, 2.0f,
              Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);

        //等同于xml定义中的第三种方式,相对父布局的坐标
       ScaleAnimation scaleAnimation3 = new ScaleAnimation(1.0f, 2.0f, 1.0f, 2.0f,
              Animation.RELATIVE_TO_PARENT, 0.5f, Animation.RELATIVE_TO_PARENT, 0.5f);


       Button button =(Button) findViewById(R.id.button);
       scaleAnimation1.setDuration(2000);// 动画持续时间为2000ms
       scaleAnimation1.setFillAfter(true);// 保持动画最后的展示效果
       BounceInterpolator bounceInterpolator = new BounceInterpolator();  // 在动画结束时有回弹的插值器
       mAnimation.setInterpolator(bounceInterpolator);// 设置插值器 也可在xml文件中定义
       mScaleAnimation.setStartOffset(1000); // 动画延时一秒后执行


       button.startAnimation(scaleAnimation1);//开始动画 
2.平移动画

xml文件中使用<translate></>标签定义

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <!--fromXDelta 起始点x的坐标  和scale中一样,有三种表示形式(数值,%,%p)-->
    <!--toXDelta   结束点X的坐标  同上也有三种表示形式-->
    <!--fromYDelta 起始点Y的坐标  同上规律-->
    <!--toYDelta   结束点Y的坐标  同上规律-->
    <translate
        android:duration="2000"
        android:fromXDelta="0.0"
        android:fromYDelta="-100%p"
        android:toXDelta="0.0"
        android:toYDelta="0.0"/>
</set>

使用代码定义:

//        ======平移动画=====
       mTranslateAnimation = AnimationUtils.loadAnimation(this, R.anim.translate_animate);
       mTranslateAnimation.setDuration(2000);
       mTranslateAnimation.setFillAfter(true);

//动态代码创建
       mTranslateNewAnimation = new TranslateAnimation(Animation.ABSOLUTE, 0.0f, Animation.ABSOLUTE, 0.0f,
                Animation.RELATIVE_TO_SELF, -2.0f, Animation.ABSOLUTE, 0.0f);
       mTranslateNewAnimation.setDuration(4000);
透明度动画

xml文件中使用<alpha></>标签定义

<?xml version="1.0" encoding="utf-8"?>
<!--fromAlpha 最开始的透明度  1表示不透明 0表示全透明,值只能在0.0到1.0之间变化-->
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
       android:duration="2000"
       android:fillAfter="true"
       android:fromAlpha="1.0"
       android:toAlpha="0.0"/>
//        =======渐变动画=====
       mAlphaAnimation = AnimationUtils.loadAnimation(this, R.anim.alpha_animation);//加载动画
       mAlphaAnimation.setDuration(1000);
       mAlphaAnimation.setFillAfter(true);
  
        //动态代码创建
       mAlphaNewAnimation1 = new AlphaAnimation(1.0f, 0.0f);
       mAlphaNewAnimation1.setDuration(2000);
       mAlphaNewAnimation1.setFillAfter(false);

       button.startAnimaiton(mAlphaAnimation );
旋转动画

xml文件中使用<ratate></>标签定义

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <!--fromDegrees 旋转的开始角度,正数代表顺时针度数,负数代表逆时针度数-->
    <!--toDegrees   旋转结束角度 -->
    <!--pivotX,pivotY的规律同其他动画规律一致-->
    <rotate
        android:fromDegrees="0"
        android:pivotX="50%p"
        android:pivotY="50%p"
        android:toDegrees="180"/>
</set>
// ===============  旋转动画 ===============
       //加载xml动画
       mRotateAnimation = AnimationUtils.loadAnimation(this, R.anim.rotate);
       mRotateAnimation.setDuration(2000);
       mRotateAnimation.setFillAfter(true);
       mRotateAnimation.setStartOffset(1000);//执行前的等待时间
       button.startAnimation(mRotateAnimation );// 开始动画,对button进行旋转


      //动态创建
       mRotateNewAnimation = new RotateAnimation(0.0f, 180f, Animation.RELATIVE_TO_PARENT, 0.5f, Animation.RELATIVE_TO_PARENT, 0.5f);
       mRotateNewAnimation.setDuration(2000);
       button.startAnimation(mRotateNewAnimation );// 开始动画,对button进行旋转

Frame帧动画

Frame帧动画就是播放一组图片来达到动画的效果。在res/drawable目录下创建drawable resource xml资源文件,使用 <animation-list></>标签。

<?xml version="1.0" encoding="utf-8"?>
<animation-list
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:oneshot="false">
    <!--oneshot 是否只播放一次-->
    <!--duration 单张图片持续时间-->

    <item android:drawable="@mipmap/image1" android:duration="200"/>
    <item android:drawable="@mipmap/image2" android:duration="200"/>
    <item android:drawable="@mipmap/image3" android:duration="200"/>
    <item android:drawable="@mipmap/image4" android:duration="200"/>
    <item android:drawable="@mipmap/image5" android:duration="200"/>
</animation-list>

因为帧动画是播放一张一张的图片,所以需要ImageView作为载体,在布局文件中引用。

     <ImageView
         android:layout_marginTop="30dp"
         android:id="@+id/image"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:src="@drawable/frame_animation"/>

代码中通过ImageView的getDrawable方法得到AniAnimationDrawable。

       mImageView.setOnClickListener(new View.OnClickListener() {
           @Override
           public void onClick(View v) {
              // 得到 AnimationDrawable 
               AnimationDrawable animationDrawable = (AnimationDrawable) mImageView.getDrawable();
               animationDrawable.setOneShot(false); // 循环播放  为true则只播放一次

               if (animationDrawable.isRunning()){
                   animationDrawable.stop(); // 停止动画 
               }else {
                   animationDrawable.start(); // 开始动画
               }
           }
       });

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,240评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,328评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,182评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,121评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,135评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,093评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,013评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,854评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,295评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,513评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,678评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,398评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,989评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,636评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,801评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,657评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,558评论 2 352

推荐阅读更多精彩内容