Android动画系列——View动画和帧动画

Android开发中,常用的动画有三种,View动画,帧动画和属性动画。

View动画

View动画也被称为TweenAnimation,是在视图上执行补间动画,它作用于视图整体。补间动画指的是只要指定动画开始和结束时刻的“关键帧”,而动画变化过程的“中间帧”由系统计算并补齐。无论动画如何改变视图的显示区域,视图原来的边界也不会自动调整(缩放)来适应视图动画的显示区域。那么就可以这样理解:视图通过ScaleAnimation或者TranslateAnimation动画,使显示区域超过了视图原有的边界,视图不会被剪裁。与之相反的是,当视图的动画超过父容器的边界时,显示区域将被剪裁。
系统提供的View动画有且只有4种:TranslateAnimation(平移动画)、AlphaAnimation(透明度动画)、ScaleAnimation(缩放动画)、Rotation(旋转动画)。他们都是以Animation类的派生类。具体的相关类的继承图如下:


Animation的派生类

AnimationSet是动画集合类,可以将多个不同的XxxAnimation组合,形成一组复杂效果的View动画。
使用View动画主要有两种方式,xml定义和代码定义:
先看看xml定义,首先在res/anim目录下定义一个xml文件

<set xmlns:android="http://schemas.android.com/apk/res/android" >
    <translate
        android:duration="2000"
        android:fromXDelta="0"
        android:fromYDelta="0"
        android:toXDelta="0"
        android:toYDelta="200" />
</set>

然后通过AnimationUtils加载xml中的动画,生成Animation对象

TranslateAnimation translateAnimation = AnimationUtils.loadAnimation(context,R.anim.anim_translate);
intentBtn.startAnimation(translateAnimation);

最后调用视图的startAnimation方法给视图设置动画并开始。
再来看看在代码中定义:

TranslateAnimation translateAnimation = new TranslateAnimation(0f, 0f, 0f, 200f);
translateAnimation.setDuration(1000);//动画的持续时间,单位毫秒
translateAnimation.setFillAfter(true);//参数为true表示动画结束后View停留在结束位置
intentBtn.startAnimation(translateAnimation);

上面的代码是简单的Animation动画的使用方式,其中值得一提的是,setFillAfter(true)方法,参数为true,表示动画结束后,视图停留在完成时的位置;参数为false(默认),表示动画结束后,视图还原到起始位置。
我们还可以给Animation设置监听事件,监听动画的开始和结束

translateAnimation.setAnimationListener(new Animation.AnimationListener() {
                    @Override
                    public void onAnimationStart(Animation animation) {
                        //动画开始时调用
                    }

                    @Override
                    public void onAnimationEnd(Animation animation) {
                      //动画结束时调用
                    }

                    @Override
                    public void onAnimationRepeat(Animation animation) {
                      //动画重复播放时调用
                    }
                });
View动画的两个常用的特殊场景
  • ViewGroup子视图的布局动画(LayoutAnimation)。以ListView为例:
//然后在代码中,给ListView设置动画(LayoutAnimation)
LayoutAnimationController lac=new LayoutAnimationController(AnimationUtils.loadAnimation(this, R.anim.zoom_in));
lac.setDelay(0.5f);
lac.setOrder(LayoutAnimationController.ORDER_RANDOM);
mListView.setLayoutAnimation(lac);

//也可以layout文件中给ListView设置layoutAnimation属性
<ListView
    android:id="@+id/listView"
    android:layoutAnimation="@anim/anim_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
</ListView>

layoutAnimation虽然是API 1中就已经引入,但只能在ViewGroup初次创建时才能使用指定动画。容器创建以后,再往ViewGroup里加Item就不会再有动画。在API 11之后,Android为了支持ViewGroup类控件,在添加和移除其中控件时自动添加动画,为我们提供了一个非常简单的属性:android:animateLayoutChanges=“true”,所有派生自ViewGroup的控件都具有此属性,只要在XML中添加上这个属性,就能实现添加/删除其中控件时,带有默认动画了。但是这个属性设置后,只能使用默认的动画,不支持自定义动画。同时在API 11时引入的LayoutTransaction也能起到LayoutAnimation+animateLayoutChanges效果,并且能够设置自定义动画。它的使用涉及到属性动画,相对LayoutAnimation的使用更复杂,以后再提。

  • 通过补间动画(Tween animation)为Activity自定义切换动画
    Android系统为Activity设置了默认的切换动画,这个动画我们是可以进行自定义的。通过调用Activity类的overridePendingTransition(int enterAnim, int exitAnim)方法可以实现自定义Activity的切换动画,注意这个方法必须在startActivity和finish调用之后被调用,否者没有效果。
View动画的缺点

它只是改变了视图的显示,但没有改变视图的响应区域。也就是说,比如你用ScaleAnimation将视图放大或缩小,其实视图的点击响应区域还是动画开始前的位置;或者用TranslateAnimation将视图平移到另一个位置,点击响应区域还是在动画开始前的位置,而动画结束时视图所在的区域没有点击响应。

帧动画

帧动画也就是Drawable动画,是用来逐帧显示定义好的一组图片或者Drawable资源。效果类似于范灯片,一张张地切换图片。对应于AnimationDrawable类。实际的开发中,帧动画使用的场景相对较少。
典型的用法如下:
首先在res/drawable目录下通过xml定义一个帧动画(AnimationDrawable)

<?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/first_pic"
        android:duration="1000"/>
    <item
        android:drawable="@drawable/second_pic"
        android:duration="1000"/>
    <item
        android:drawable="@drawable/third_pic"
        android:duration="1000"/>
    <item
        android:drawable="@drawable/fourth_pic"
        android:duration="1000"/>
    <item
        android:drawable="@drawable/fifth_pic"
        android:duration="1000"/>
    <item
        android:drawable="@drawable/sixth_pic"
        android:duration="1000"/>
</animation-list>

<animation-list>标签表示一组帧动画,oneshot属性为true,表示动画只播放一次,否则就会重复播放。每一个item对应每一帧的图片。duration属性表示每一帧显示的时间。
接下来将定义好的AnimationDrawable设置为View的背景或者ImageView的图像

AnimationDrawable animationDrawable = (AnimationDrawable) getResources().getDrawable(R.drawable.anim_list);
image.setImageDrawable(animationDrawable);
animationDrawable.start();

以上是通过xml的方式定义帧动画(AnimationDrawable),当然也可以通过代码来定义

AnimationDrawable animationDrawable = new AnimationDrawable();
animationDrawable.addFrame(getResources().getDrawable(R.drawable.first_pic), 1000);
animationDrawable.addFrame(getResources().getDrawable(R.drawable.second_pic), 1000);
animationDrawable.addFrame(getResources().getDrawable(R.drawable.third_pic), 1000);
animationDrawable.addFrame(getResources().getDrawable(R.drawable.fourth_pic), 1000);
animationDrawable.addFrame(getResources().getDrawable(R.drawable.fifth_pic), 1000);
animationDrawable.addFrame(getResources().getDrawable(R.drawable.sixth_pic), 1000);
animationDrawable.setOneShot(true);
image.setImageDrawable(animationDrawable);
animationDrawable.start();

有一点需要强调的是:启动animationDrawable.start()不能在Activity的onCreate和onStart中调用,因为在onCreate和onStart中AnimationDrawable还没有完全的与ImageView绑定,在onCreate和onStart中启动动画,就只能看到第一张图片。解决的办法是确保Activity在Resume状态下调用animationDrawable.start()。
帧动画的缺陷是不能添加监听事件。

本文参考:
https://www.jianshu.com/p/b117c974deaf
https://www.jianshu.com/p/5d811aaf4541
http://wiki.jikexueyuan.com/project/android-animation/12.html

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

推荐阅读更多精彩内容