梦回嫦娥仙子 🧚‍♀️ 带你一览 Android 动画~ *ଘ(੭*ˊᵕˋ)੭* ੈ♡‧₊˚

1,244

我正在参加中秋创意投稿大赛,详情请看:中秋创意投稿大赛

缘起缘灭,似乎兜兜转转,却又回到原点。

惘然相望,又是一年中秋。

月饼的味道似乎传遍了大街小巷,浓浓的相思,儿时的记忆,不断涌现,一切似乎昨天。。。

仿若间,儿时那朗朗背诵诗词声音渐渐传来...

白兔捣药秋复春,嫦娥孤栖与谁邻?

今人不见古时月,今月曾经照古人。

古人今人若流水,共看明月皆如此。

唯愿当歌对酒时,月光长照金樽里。

也不知,在那广寒宫之中的嫦娥仙子🧚‍♀️,又在思念着谁...

浓浓的睡意席卷而来,眼睛闭上的霎那间,一扇带有古老尘封气息的大门悄然开启...

寒宫之旅,悄然开启~

image.png

此 Demo GitHub 地址

仙子,听我和你说动画

动画的出现,让普通的 View 有了更多可能,同样给予了用户更佳的舒适体验度。

一起看下 Android 中的那些动画(非完整版、后续补充,希望可以兑现):

image.png

视图动画

关于视图动画,可以参照属性动画去理解:

  • 视图动画仅仅是在视觉上产生了动画行为,而 View 本身属性并没有发生改变。

帧动画

官方说法:

通过使用 AnimationDrawable 按顺序显示一系列图片来创建动画。

顾名思义,按顺序展示一系列图片已达到动画效果。

比如说,陪着仙子一起看下小玉兔在干嘛?

Kapture 2021-09-14 at 00.12.15.gif

看一波关键属性?

  • 根元素 animation-list,包含一个或者多个 item 元素。
  • 属性 android:oneshot,如果执行一次,则为 true。如果循环播放则为 false。默认为 false,循环播放。
    • 单帧动画 item,包含在 animation-list 中。
      • 属性 android:drawable,单帧图片。
      • 属性 android:duration,当前帧持续的时间。

一起实现一波?

一、定义 Drawable

<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
    android:oneshot="false">
    <item
        android:drawable="@drawable/img_rabbit_000"
        android:duration="150" />
    <item
        android:drawable="@drawable/img_rabbit_001"
        android:duration="150" />
    <item
        android:drawable="@drawable/img_rabbit_002"
        android:duration="150" />
    ...
</animation-list>

二、定义 ImageView

<ImageView
    android:id="@+id/ivFrameAnim"
    android:layout_width="120dp"
    android:layout_height="120dp" 
    android:scaleType="fitXY"  />

三、播放动画

还有一种方案是通过循环去不断的为 drawable addFrame,个人更倾向于下面这种方式:

private fun startFrameAnim() {
    binding.ivFrameAnim.apply {
        setBackgroundResource(R.drawable.animation_rabbit)
        val animationDrawable = background as AnimationDrawable
        animationDrawable.start()
    }
}

一定注意,帧动画中的单帧图片记得压缩,切勿太大,否则会造成 OOM。

这里发现了一个问题,在启动帧动画的时候,内存会出现爆增,开始想着处理回收 bitmap,折腾半天无果,后续再说哇。

补间动画

引入官老爷说法:

通过使用 Animation 对单张图片执行一系列转换来创建动画

其实这里也不仅仅是单张图片,相关的 View 均可以。

后期个人更为习惯的方式是封装为工具类,方便一次书写,多地方调用。

rotate 爱的魔力转圈圈

一起来看仙子转圈圈~

Kapture 2021-09-16 at 23.12.55.gif

然后我们再来跟着仙子学习~ 🧚‍♀️🧚‍♀️🧚‍♀️

首先来看属性列表:

  • rotate 旋转动画。代表 RotateAnimation。
    • android:duration 动画执行速度
    • android:fromDegrees 起始角度
    • android:toDegrees 结束角度
    • android:pivotX 旋转的 X 轴坐标
    • android:pivotY 旋转的 Y 轴坐标

先来份代码版本的尝尝鲜?

val rotateAnimation = RotateAnimation(0f, 360f).apply {
    duration = 1800
}
binding.ivTweenRotate0.startAnimation(rotateAnimation)

没错,就是这么简单,当然也包含其他构造:

image.png

再来个 xml 版?

首先创建 anim 目录,并创建对应 rotate 文件:

<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1800"
    android:fromDegrees="0"
    android:pivotX="50%"
    android:pivotY="50%"
    android:toDegrees="360" />

如何使用呢?

binding.ivTweenRotate1.apply {
    val rotateAnim =
        AnimationUtils.loadAnimation(this@AnimationListActivity, R.anim.anim_rotate)
    startAnimation(rotateAnim)
}

alpha 喜欢仙子若隐若现

Kapture 2021-09-17 at 00.20.16.gif

淡入淡出动画属性相对较为简单:

  • alpha 淡入或淡出动画。代表 AlphaAnimation。
    • android:duration 动画执行速度
    • android:fromAlpha 起始不透明度偏移,0.0 表示透明,1.0 表示不透明。
    • android:toAlpha 结束不透明度

同样献上一份代码版本:

val alphaAnimation = AlphaAnimation(0f, 1f).apply {
    duration = 1800
}
binding.ivTweenAlpha0.startAnimation(alphaAnimation)

再来一份 xml 版本:

<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1800"
    android:fromAlpha="1"
    android:toAlpha="0" />

最后的使用:

binding.ivTweenAlpha1.apply {
    val alphaAnim =
        AnimationUtils.loadAnimation(this@AnimationListActivity, R.anim.anim_alpha)
    startAnimation(alphaAnim)
}

这里有的小伙伴就说了,我不想让仙子消失这么快,我要知道仙子消失开始以及结束,怎么办呢?

这里同样为我们提供了监听方式,如下:

binding.ivTweenAlpha1.apply {
    AnimationUtils.loadAnimation(this@AnimationListActivity, R.anim.anim_alpha).apply {
        startAnimation(this)
        setAnimationListener(object : Animation.AnimationListener {

            /**
             * 动画开始
             */
            override fun onAnimationStart(animation: Animation?) {

            }

            /**
             * 动画结束
             */
            override fun onAnimationEnd(animation: Animation?) {

            }

            /**
             * 动画重复播放
             */
            override fun onAnimationRepeat(animation: Animation?) {

            }

        })
    }
}

scale 爱你的心 永恒不变

Kapture 2021-09-17 at 00.52.40.gif

属性一览:

  • scale 缩放动画:
    • android:duration 动画执行速度
    • android:fromXScale 起始 X 尺寸偏移,其中 1.0 表示不变
    • android:toXScale 结束 X 尺寸偏移
    • android:fromYScale 起始 Y 尺寸偏移
    • android:toYScale 结束 Y 尺寸偏移
    • android:pivotX 在对象缩放时要保持不变的 X 坐标
    • android:pivotY 在对象缩放时要保持不变的 Y 坐标

搞一份代码版本试试?

val scaleAnimation = ScaleAnimation(1f, 1.2f, 1f, 1.2f).apply {
    duration = 1800
}
binding.ivTweenScale0.startAnimation(scaleAnimation)

再来一份 xml 版本:

<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1800"
    android:fromXScale="1"
    android:fromYScale="1"
    android:pivotX="50%"
    android:pivotY="50%"
    android:toXScale="1.2"
    android:toYScale="1.2" />

同样的 load 方式:

binding.ivTweenScale1.apply {
    AnimationUtils.loadAnimation(this@AnimationListActivity, R.anim.anim_scale).apply {
        startAnimation(this)
    }
}

translate 能否平移到你心房

Kapture 2021-09-17 at 01.26.34.gif

属性一览:

  • translate 平移动画:
    • android:duration 动画执行速度
    • android:fromXDelta 起始 X 偏移
    • android:toXDelta 结束 X 偏移
    • android:fromYDelta 起始 Y 偏移
    • android:toYDelta 结束 Y 偏移

来份代码版本:

val translateAnimation = TranslateAnimation(0f,100f,0f,100f).apply {
    duration = 3600
    fillAfter = true // 动画结束后不回到原地
}
binding.ivTweenTranslate0.startAnimation(translateAnimation)

再来份 xml 版本:

<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1800"
    android:fromXDelta="0"
    android:fromYDelta="0"
    android:toXDelta="100"
    android:toYDelta="100" />

以及对应使用:

binding.ivTweenTranslate1.apply {
    AnimationUtils.loadAnimation(this@AnimationListActivity, R.anim.anim_translate).apply {
        startAnimation(this)
    }
}

set 仙子 让我为你舞起来

太晚了,明日更新。。。

属性动画

未完待续,稍等片刻。。。

叨逼叨

害,意料之中,意料之外,又要忙于找工作啦,暂时搁置,后续继续维护~

理解万岁~

THK

前人栽树,后人乘凉,感谢前辈大佬~

附上对应参考地址链接~

参考资料

引用资源

使用工具

在此仅列举之前未使用的工具,有更好的工具欢迎推荐~