Android四大动画

前言

动画是生活中必不可少的东西,只要在向用户传递信息或展示内容都会用到动画,接下来我们讲讲在 Android 中的一些动画,这些动画主要分为 4 种,分别是 帧动画, 矢量动画, 补间动画, 属性动画

一.帧动画

帧动画,顾名思义就是通过一张张图片通过快速切换而到达的一种视觉效果,看起来像图片中的物体动起来一般,我们平常说的 60帧,120帧,指的就是一秒钟播放 60张图片或 120 张图片。

1.在xml文件中添加图片

res -> drawable 下面将这一系列连续的图片加入进去。然后新建一个名为 fire_animationxml 文件,在文件中给每个 item 添加图片资源和显示时长,如下:

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

    <item android:drawable="@drawable/campfire01" android:duration="80"/>
    <item android:drawable="@drawable/campfire02" android:duration="80"/>
    <item android:drawable="@drawable/campfire03" android:duration="80"/>
    <item android:drawable="@drawable/campfire04" android:duration="80"/>
    <item android:drawable="@drawable/campfire05" android:duration="80"/>
    <item android:drawable="@drawable/campfire06" android:duration="80"/>
    <item android:drawable="@drawable/campfire07" android:duration="80"/>
    <item android:drawable="@drawable/campfire08" android:duration="80"/>
    <item android:drawable="@drawable/campfire09" android:duration="80"/>
    <item android:drawable="@drawable/campfire10" android:duration="80"/>
    <item android:drawable="@drawable/campfire11" android:duration="80"/>
    <item android:drawable="@drawable/campfire12" android:duration="80"/>
    <item android:drawable="@drawable/campfire13" android:duration="80"/>
    <item android:drawable="@drawable/campfire14" android:duration="80"/>
    <item android:drawable="@drawable/campfire15" android:duration="80"/>
    <item android:drawable="@drawable/campfire16" android:duration="80"/>
    <item android:drawable="@drawable/campfire17" android:duration="80"/>
</animation-list>

注意: 根节点如果是 set 的话,是不能循环动画的,只能播放一次就结束

2.activity中使用

接下来在 acctivity_main 中使用这个资源文件 fire_animation.xml。最后在代码中解析成 AnimationDrawable,使用就可以了。

v = findViewById(R.id.imageView)
animation = v.drawable as AnimationDrawable
animation.start()

效果如下:


当然,这也可以完全通过代码创建,

v = findViewById(R.id.imageView)

fun fireAnimation() {
       val firesArray = arrayOf(
            R.drawable.campfire01,
            R.drawable.campfire02,
            R.drawable.campfire03,
            R.drawable.campfire04,
            R.drawable.campfire05,
            R.drawable.campfire06,
            R.drawable.campfire07,
            R.drawable.campfire08,
            R.drawable.campfire09,
            R.drawable.campfire10,
            R.drawable.campfire11,
            R.drawable.campfire12,
            R.drawable.campfire13,
            R.drawable.campfire14,
            R.drawable.campfire15,
            R.drawable.campfire16,
            R.drawable.campfire17
        )
        AnimationDrawable().apply {
            //添加图片资源
            for (item in firesArray) {
                addFrame(getDrawable(item)!!,80)
            }
            //关联图片和帧动画
            v.setImageDrawable(this)
            //启动
            start()
        }
    }

二.矢量动画

矢量动画相较帧动画就稍显复杂,我们来讲讲使用矢量动画最简单的步骤吧。我们通过相关网站,进行动画设计,它会为我们快速生成 xml 文件,你可以选择导入图片的格式: SVGAndroid Drawable

屏幕右边的方框中,很多值都对应着代码中的值,上手相对容易,具体使用请自行百度.

设计完矢量动画之后,我们点击 Export 选择 Animated Vector Drawable,它会自动为我们生成 xml 文件,之后我们将其添加至 drawable 文件夹中。

<animated-vector
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:aapt="http://schemas.android.com/aapt">
    <aapt:attr name="android:drawable">
        <vector
            android:name="vector"
            android:width="447dp"
            android:height="285dp"
            android:viewportWidth="447"
            android:viewportHeight="285">
            <path
                android:name="path"
                android:pathData="M 0.307 165.05 L 154.691 285.204 L 446.691 0.358"
                android:strokeColor="#00aa00"
                android:strokeWidth="20"
                android:strokeLineCap="round"
                android:strokeLineJoin="round"/>
        </vector>
    </aapt:attr>
    <target android:name="path">
        <aapt:attr name="android:animation">
            <objectAnimator
                android:propertyName="trimPathEnd"
                android:duration="500"
                android:valueFrom="0"
                android:valueTo="1"
                android:valueType="floatType"
                android:interpolator="@android:interpolator/fast_out_slow_in"/>
        </aapt:attr>
    </target>
</animated-vector>

我们可以看到这个矢量动画的 xml 是这样的。那么接下来就是在代码中将其转化为 AnimatedVectorDrawable 类型(注意在布局中要将srcCompat换成当前的资源),这个和帧动画的使用非常相似。

v = findViewById(R.id.imageView)
val anim = v.drawable as AnimatedVectorDrawable
anim.start()

矢量动画主要麻烦在动画资源文件的书写,但是我们可以通过这个网站来快速获得你预想动画的代码,这个使用起来也是蛮简单的。

三.补间动画

补间动画也是蛮特殊的,控件在做动画时,它的位置其实还是停留在原处,因此如果想在动画结束后给控件加点击事件,这样做是无效的,你需要通过我们待会要讲的属性动画来完成,但补间动画也有优点,就是制作简便,占用内存小等。

属性 解释
duration 动画时长,单位是毫秒
interpolator 动画的播放模式,如匀速
repeatCount 动画播放次数
repeatMode 设置动画结束重新播放动画还是倒放动画
start() 启动动画
cancel() 取消动画
fillBefore 动画播放结束是否保持动画开始状态
fillAfter 动画播放结束是否保持动画结束状态

补间动画有4种,分别是:RotateAnimation-旋转动画TranslateAnimation-位移动画AlphaAnimation-透明度动画ScaleAnimation-缩放动画

由于这几种动画创建的方式都一样,唯独就是部分属性值不一样,因此在这里就以 ScaleAnimation 为例,下面演示一下如何完成动画操作。

一共有两种完成动画的方式,xml创建纯代码创建

1.在xml中创建完成动画

找到 res 文件夹,在下面新建一个 Android Resource DirectoryResource type 选择 anim。然后我们在里面写入以下代码,根节点是什么,就是什么动画,当然你也可以选择 set 一次定义多个动画。

<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromXScale="1"  设置缩放起始时的x轴的倍数
    android:fromYScale="1"  设置缩放起始时的y轴的倍数
    android:toXScale="50"   设置缩放结束时的x轴的倍数
    android:toYScale="50"   设置缩放起始时的y轴的倍数
    android:pivotX="50%"    设置缩放时以x轴的某点为中心进行缩放
    android:pivotY="50%"    设置缩放时以y轴的某点为中心进行缩放
                            这两个属性加起来就是以物体中心点向四周缩放
    android:duration="700"  动画完成时间
    android:fillAfter="false"/>  动画是否保持结束时最后一刻的状态

然后就是在代码中使用这段动画了,

//获取控件
private val bgView = findViewById<View>(R.id.view)
//加载动画资源
scaleAnimation = AnimationUtils.loadAnimation(this,R.anim.btn_scale_anim)
//启动动画,和其他动画不同,补间动画启动是通过 view.startAnimation
bgView.startAnimation(scaleAnimation)

效果如下:

2.完全通过代码创建实现动画
val imageView = findvViewById<ImageView>(R.id.iamgeView)

animation = ScaleAnimation(
            0f,//起始缩放倍数x轴
            1f,//结束缩放倍数x轴
            0f,//起始缩放倍数y轴
            1f,//结束缩放倍数x轴
            Animation.RELATIVE_TO_SELF,
            0.5f,//相对自身x轴0.5倍距离
            Animation.RELATIVE_TO_SELF,
            0.5f//相对自身y轴0.5倍距离
        ).apply {
            interpolator = LinearInterpolator()
            repeatMode = Animation.REVERSE
            duration = 5000
            repeatCount = Animation.INFINITE
        }
imageView.startAnimation(animation)

当我开始执行动画时就是以下效果:

四.属性动画

属性动画前面也提到了,通常是要在动画结束后有点击事件时运用。它使用起来很方便。属性动画的一些属性名称以及对应的值和渐变动画很多都一样,只是属性动画的暂停是 animator.pause()

属性动画常用的有两种 ObjectAnimatorValueAnimatorObjectAnimator 是直观的给 Object 加上动画效果,能直观地为我们展示动画,如 translationX 就是在x轴上移动,而 ValueAnimator 是能产生很多关于动画的值,我们将这些值赋给每个动画因子,就可以完成很多花里胡哨的动画,如,我手动绘制一个这样的加载动画(屏幕上方那一个),它的一个动画因子就是 startAngle(画圆弧的起始角度)

下面就举例讲一个属性动画 translationX。顾名思义,是在物体 x轴 方向上移动,向右移动是正,向左移动是负。

val v = findViewById<View>(R.id.view)
ObjectAnimator.ofFloat(v,"translationX",0f, height - 50f.apply {
    duration = 350
    interpolator = BounceInterpolator()
}.start()

由于是 ofFloat 所以参数都必须是 Float 类型!

  • 当有多个动画时可以使用 AnimatorSet 设置同时播放或顺序播放。
//同时播放
AnimatorSet().playTogether(动画一,动画二)
//顺序播放,写在前面的先播放
AnimatorSet().playSequentially(动画一,动画二)
  • 属性动画允许添加事件监听
val v = findViewById<View>(R.id.view)
ObjectAnimator.ofFloat(v, "translationX", - 2f, 0f).apply {
            duration = 500
            interpolator = LinearInterpolator()
            addListener(
                onStart = {
                    //动画开始时 TODO
                },
                onCancel = {
                    //动画取消时 TODO
                },
                onEnd = {
                    //动画结束时 TODO
                },
                onRepeat = {
                    //动画重复时 TODO
                })
        }.start()
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,482评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,377评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,762评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,273评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,289评论 5 373
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,046评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,351评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,988评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,476评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,948评论 2 324
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,064评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,712评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,261评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,264评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,486评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,511评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,802评论 2 345

推荐阅读更多精彩内容