你了解Android中的动画吗?

Android的动画可以分为三种:View动画帧动画属性动画,其实帧动画也属于View动画的一种,只不过它和平移、旋转等常见的View动画在表现形式上略有不同而已。

一、 View动画

View动画有四种变化效果,Translate、Scale、Rotate和Alpha,这四种动画既可以通过XML来定义,也可以通过代码来动态创建。

名称 标签 子类 效果
平移动画 <translate> TranslateAnimation 移动View
缩放动画 <scale> ScaleAnimation 放大或缩小View
旋转动画 <rotate> RotateAnimation 旋转View
透明度动画 <alpha> AlphaAnimation 改变View的透明度
<?xml version="1.0" encoding="utf-8"?>
<!-- res/anim -->
<set xmlns:android="http://schemas.android.com/apk/res/android">   
 
    <alpha        
        android:fromAlpha="float"        
        android:toAlpha="float"/>    

    <scale        
        android:fromXScale="float"        
        android:toXScale="float"        
        android:fromYScale="float"        
        android:toYScale="float"        
        android:pivotX="float"        
        android:pivotY="float"/>    

     <translate        
        android:fromXDelta="float"        
        android:toXDelta="float"        
        android:fromYDelta="float"        
        android:toYDelta="float"/>    

     <rotate        
        android:fromDegrees="float"        
        android:toDegrees="float"        
        android:pivotX="float"        
        android:pivotY="float" />
</set>

接下来具体讲下一下各类型用法:

1. Translate
<translate>标签表示平移动画,对应TranslateAnimation类,它可以使一个View在水平和竖直方向完成平移的动画效果:

  • android:fromXDelta —— 表示x的起始值
  • android:toXDelta —— 表示x的结束值
  • android:fromYDelta —— 表示y的起始值
  • android:toYDelta —— 表示y的结束值

接下来使用translate使一个View在2秒内在水平方向平移400长度,垂直方向平移100长度,并使其停留在移动后的位置(fillAfter)

  • 用法一:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
     android:fillAfter="true">   

     <translate        
        android:fromXDelta="0"        
        android:toXDelta="400"        
        android:fromYDelta="0"        
        android:toYDelta="100"
        android:duration="2000"/>    

</set>
private void translate(){    
   Animation animation = AnimationUtils.loadAnimation(this, R.anim.translate);    
   block.startAnimation(animation);
}
  • 用法二:
private void translate(){    
   TranslateAnimation animation = new TranslateAnimation(Animation.ABSOLUTE, 0,            
           Animation.ABSOLUTE, 400, Animation.ABSOLUTE, 0, Animation.ABSOLUTE, 100);    
   animation.setDuration(2000);    
   animation.setFillAfter(true);    
   block.startAnimation(animation);
}
效果图

TranslateAnimation共有三个构造函数,分别是:



主要看一下第三个构造函数:

TranslateAnimation(int fromXType, float fromXDelta, int toXType, float toXDelta, 
        int fromYType, float fromYDelta, int toYType, float toYDelta) 

我们会发现每个value前都有一个type

  • Animation.ABSOLUTE,表示为绝对像素,此时XValue和YValue参数的含义和第二个构造函数相同。
  • Animation.RELATIVE_TO_SELF,表示相对位移量了,举个例子来说,如果在X方向上选择Animation.RELATIVE_TO_SELF,那么当XValue=1.0f时,则偏移量为一个自身宽度。
  • Animation.RELATIVE_TO_PARENT,则表示相对位移量了,如果在X方向上选择Animation.RELATIVE_TO_PARENT时,则偏移量为一个父控件宽度。

2. Scale
<scale>标签表示缩放动画,对应ScaleAnimation类,它可以使一个View具有放大或者缩小的动画效果:

  • android:fromXScale —— 水平方向缩放的起始值(是原始值的倍数)
  • android:toXScale —— 水平方向缩放的结束值(是原始值的倍数)
  • android:fromYScale —— 垂直方向缩放的起始值(是原始值的倍数)
  • android:toYScale —— 垂直方向缩放的结束值(是原始值的倍数)
  • android:pivotX —— 缩放的轴点的x坐标,会影响缩放效果
  • android:pivotY —— 缩放的轴点的y坐标,会影响缩放效果

接下来使用scale使一个View在2秒内以其原点为轴点在水平方向和垂直方向都放大为原来的2倍,并保留变化后的状态

  • 用法一:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
     android:fillAfter="true">   

     <scale    
         android:fromXScale="1"    
         android:toXScale="2"    
         android:fromYScale="1"    
         android:toYScale="2"    
         android:pivotX="0"    
         android:pivotY="0"    
         android:duration="2000"/>   

</set>
private void scale(){    
   Animation animation = AnimationUtils.loadAnimation(this, R.anim.scale);    
   block.startAnimation(animation);
}
  • 用法二:
private void scale(){    
   ScaleAnimation animation = new ScaleAnimation(1, 2, 1, 2, Animation.RELATIVE_TO_SELF, 0,        
              Animation.RELATIVE_TO_SELF, 0); 
   animation.setDuration(2000);    
   animation.setFillAfter(true);    
   block.startAnimation(animation);
}
效果图

ScaleAnimation共有四个构造函数,分别是:


主要看一下第四个构造函数:

ScaleAnimation(float fromX, float toX, float fromY, float toY, int pivotXType, float pivotXValue,
               int pivotYType, float pivotYValue) 

pivotXValue和pivotYValue前的Type与之前提到的一样,表示坐标的一个相对位移

3. Rotate
<rotate>标签表示旋转动画,对应RotateAnimation类,它可以使一个View具有旋转的动画效果:

  • android:fromDegrees —— 旋转开始的角度
  • android:toDegrees —— 旋转结束的角度
  • android:pivotX —— 旋转的轴点的x坐标
  • android:pivotY —— 旋转的轴点的y坐标

接下来使用rotate使一个View在2秒内以其右下角为轴点旋转90度,并保留变化后的状态

  • 用法一:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
     android:fillAfter="true">   

     <rotate    
         android:fromDegrees="0"    
         android:toDegrees="90"    
         android:pivotX="80"    
         android:pivotY="80"    
         android:duration="2000"/>

</set>
private void rotate(){    
   Animation animation = AnimationUtils.loadAnimation(this, R.anim.rotate);    
   block.startAnimation(animation);
}
  • 用法二:
private void rotate(){    
   RotateAnimation animation = new RotateAnimation(0, 90, Animation.RELATIVE_TO_SELF, 1,        
               Animation.RELATIVE_TO_SELF, 1);
   animation.setDuration(2000);    
   animation.setFillAfter(true);    
   block.startAnimation(animation);
}
效果图

RotateAnimation共有四个构造函数,分别是:


4. Alpha
<alpha>标签表示透明度动画,对应AlphaAnimation类,它可以改变View的透明度:

  • android:fromAlpha —— 表示透明度的起始值
  • android:toAlpha —— 表示透明度的结束值

接下来使用alpha使一个View在2秒内变成完全透明度为0.2,并保留变化后的状态

  • 用法一:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
     android:fillAfter="true">   

     <alpha    
         android:fromAlpha="1"    
         android:toAlpha="0.2"    
         android:duration="2000"/>

</set>
private void alpha(){    
   Animation animation = AnimationUtils.loadAnimation(this, R.anim.alpha);    
   block.startAnimation(animation);
}
  • 用法二:
private void alpha(){    
   AlphaAnimation animation = new AlphaAnimation(0, 0.2f);
   animation.setDuration(2000);    
   animation.setFillAfter(true);    
   block.startAnimation(animation);
}
效果图

AlphaAnimation共有两个构造函数,分别是:


二、 帧动画

帧动画是顺序播放一组预先定义好的图片,类似于电影播放。不同于View动画,系统提供了另外一个类AnimationDrawable来使用帧动画

<?xml version="1.0" encoding="utf-8"?>
<!-- res/drawable -->
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"    
    android:oneshot="true">    
   
    <item android:drawable="@drawable/pic1" android:duration="500"/>    
    <item android:drawable="@drawable/pic2" android:duration="500"/>    
    <item android:drawable="@drawable/pic3" android:duration="500"/>

</animation-list>
private void frame(){    
    block.setBackgroundResource(R.drawable.frame);    
    AnimationDrawable drawable = (AnimationDrawable) block.getBackground();    
    drawable.start();
}
效果图.gif

onshot为false表示循环播放,不过必须在animation-list的最后多加一帧第一帧动画,如下:

<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"    
    android:oneshot="true">    
   
    <item android:drawable="@drawable/pic1" android:duration="500"/>    
    <item android:drawable="@drawable/pic2" android:duration="500"/>    
    <item android:drawable="@drawable/pic3" android:duration="500"/>
    <item android:drawable="@drawable/pic1" android:duration="500"/>    

</animation-list>

三、 属性动画

属性动画,可以在一个时间间隔内完成对象从一个属性值到另一个属性值得改变。但是属性动画从API11才有,一定程度上制约了属性动画的使用。

<?xml version="1.0" encoding="utf-8"?>
<!-- res/animator -->
<set xmlns:android="http://schemas.android.com/apk/res/android"    
    android:ordering=["together"|"sequentially"]>    

    <objectAnimator        
        android:propertyName="string"        
        android:duration="int"        
        android:valueFrom="float | int | color"        
        android:valueTo="float | int | color"        
        android:startOffset="int"        
        android:repeatCount="int"        
        android:repeatMode=["restart"|"reverse"]        
        android:valueType=["intType"|"floatType"]/>    

    <animator           
        android:duration="int"        
        android:valueFrom="float | int | color"        
        android:valueTo="float | int | color"        
        android:startOffset="int"        
        android:repeatCount="int"        
        android:repeatMode=["restart"|"reverse"]        
        android:valueType=["intType"|"floatType"]/>    
</set>

属性动画的各种参数都比较好理解,在XML中可以定义ValueAnimator、ObjectAnimator以及AnimatorSet,其中<set>标签对应AnimatorSet,<animator>标签对应ValueAnimator,而<objectAnimator>标签对应ObjectAnimator。

set标签里有两个可选值:"together"和"sequentially",其中"together"表示动画集合中的子动画同时播放,"sequentially"则表示动画集合中的子动画按照前后顺序依次播放,默认为"together"。

其他属性:

  • android:propertyName —— 表示属性动画的作用对象的属性的名称
  • android:duration —— 表示动画的时长
  • android:valueFrom —— 表示属性的起始值
  • android:valueTo —— 表示属性的结束值
  • android:startOffset —— 表示动画的延迟时间,当动画开始后,需要延迟多少毫秒才会真正执行动画
  • android:repeatCount —— 表示动画的重复次数
  • android:repeatMode —— 表示动画的重复模式
  • android:valueType —— 表示android:propertyName所指定的属性的类型,intType为整型,floatType为浮点型,如果属性表示的是颜色,则不需要指定valueType

试下来使用属性动画实现一个View的背景颜色在3秒内从#0xFFFF8080到#0xFF8080FF的渐变,动画会无限循环且有反转的效果

用法一:

<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"    
    android:propertyName="backgroundColor"    
    android:duration="3000"    
    android:valueFrom="#FF8080"    
    android:valueTo="#8080FF"    
    android:startOffset="0"    
    android:repeatCount="infinite"    
    android:repeatMode="reverse">
</objectAnimator>
private void objectAnimator(){    
     ObjectAnimator animator = (ObjectAnimator) AnimatorInflater.loadAnimator(this, R.animator.object);
     animator.setEvaluator(new ArgbEvaluator());
     animator.setTarget(block);
     animator.start();
}

用法二:

private void objectAnimator(){
   ValueAnimator colorAnim = ObjectAnimator.ofInt(this, "backgroundColor", Color.parseColor("#FF8080"),  
      Color.parseColor("#8080FF"));    
   colorAnim.setDuration(3000);    
   colorAnim.setEvaluator(new ArgbEvaluator());    
   colorAnim.setRepeatCount(ValueAnimator.INFINITE);    
   colorAnim.setRepeatMode(ValueAnimator.REVERSE);    
   colorAnim.setTarget(block);    
   colorAnim.start();
}
效果图

试下来使用属性动画在3秒内同时实现一个View的背景颜色和透明度的渐变

用法一:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"    
    android:ordering="together">    

    <objectAnimator        
        android:propertyName="alpha"        
        android:duration="3000"        
        android:valueTo="0.2"        
        android:valueType="floatType"/>    

    <objectAnimator        
        android:propertyName="backgroundColor"        
        android:duration="3000"        
        android:valueFrom="#FF8080"        
        android:valueTo="#8080FF"        
        android:valueType="colorType"/>    
</set>
private void animatorSet(){    
   AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(this, R.animator.set);    
   set.setTarget(block);    
   set.start();    
}

用法二:

private void animatorSet(){    
   AnimatorSet set = new AnimatorSet();
   set.playTogether(        
       ObjectAnimator.ofInt(this, "backgroundColor", Color.parseColor("#FF8080"),
          Color.parseColor("#8080FF")),        
       ObjectAnimator.ofFloat(this, "alpha", 1, 0.2f)
   );
   set.setTarget(block);
   set.start(); 
}

如果在构建ObjectAnimator随便传一个属性过去,轻则没动画效果,重则程序直接Crash。

这种情况下可以采用ValueAnimator,监听动画过程,自己实现属性的改变:

ValueAnimator valueAnimator = ValueAnimator.ofInt(0, 100);
valueAnimator.addUpdateListener(new AnimatorUpdateListener(){

      @Override
      public void onAnimationUpdate(ValueAnimator animator){
            // 获得当前动画的进度值,1~100之间
            int currentValue = (Integer) animator.getAnimatedValue();

            requestLayout();    // 根据进度值改变布局
      }
});
valueAnimator.setDuration(5000).start();

哈哈,安卓的动画基础大概就这些,如果想要熟练掌握还需勤加练习~~

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

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 170,569评论 25 707
  • 1 背景 不能只分析源码呀,分析的同时也要整理归纳基础知识,刚好有人微博私信让全面说说Android的动画,所以今...
    未聞椛洺阅读 2,580评论 0 9
  • 1 朋友问我,如何能忘记一个人。 我想都没想,告诉她除非你失忆。 其实感情里最重要的不是你如何忘记,而是你放下就行...
    有一句我替你说_阅读 960评论 2 4
  • 上周时间没安排过来,周末有点松懈自己出去玩,所以导致昨天才看完本书,今天才开始写读书笔记。这个习惯要检讨,看了小强...
    Berrywang阅读 220评论 0 0
  • 跃迁 读书笔记 1014/7 395--467 我的话: 1.知识量和知识点之间的架构非常重要。如果知识点之间能够...
    宁静致远的猫阅读 409评论 0 0