动画分类:
逐帧动画
一、逐帧动画 和 AnimationDrawable
1、xml方式定义逐帧动画
逐帧动画通常采用xml资源文件进行定义。
<animation-list android:oneshot=["true"|"false"]>
<item android:drawable="@drawable/xxx1" android:duration="integer">
<item android:drawable="@drawable/xxx2" android:duration="integer">
...
</animation-list>
oneshot属性控制动画是否只播放一次,true表示,false表示循环播放。每个item子元素即为一帧。假设逐帧动画资源文件为xxx.xml,则可以通过R.drawable.xxx来引用逐帧动画资源。
2、java代码方式创建逐帧动画AnimationDrawable
1、创建AnimationDrawable对象;
2、调用addFrame(Drawable frame, int duration)添加帧;
3、使用逐帧动画AnimationDrawable
习惯把AnimationDrawable设成ImageView的背景
a、在xml中通过background属性指定:
<ImageView
android:id="@+id/image"
android:layout_width="300dp"
android:layout_height="300dp"
android:background="@drawable/framelist"
/>
b、代码中setBackgroundResource()指定
//指定image的background资源
image.setBackgroundResource(R.drawable.framelist)
val background = image.background
play.setOnClickListener {
//开始播放帧动画前,先暂停。否则只有第一次点击生效
(background as AnimationDrawable).stop()
(background as AnimationDrawable).start()
}
stop.setOnClickListener {
(background as AnimationDrawable).stop()
}
注意:
1、AnimationDrawable代表的动画默认是不播放的,必须在程序中启动动画播放才可以。AnimationDrawable提供了start()和stop()方法来开始和停止播放动画。
2、启动Frame动画的代码animationDrawable.start();不能应用在OnCreate()方法中,因为在OnCreate()中AnimationDrawable还没有完全的与ImageView绑定。在OnCreate()中启动动画,只能看到第一张图片。这里在触摸事件中实现的。
3、调用start前,最好先执行一下stop。
简单介绍下AnimationDrawabe类
AnimationDrawabe类的继承关系如下所示,可以看出AnimationDrawabe本质上是一个Drawable,由于其实现了Animatable,所以它具有播放、暂停和获取播放状态的功能。
二、补间动画 Tween
补间动画就是指开发者只需要指定动画开始、动画结束“关键帧”,而动画变化的“中间帧”由系统计算并补齐。是逐帧动画的演化形式。
Animation
Android使用Animation代表抽象的动画类,包括的子类有
AlphaAnimation: 透明度改动的动画。创建该动画时要指定动画开始时的透明度、结束时的透明度和动画持续时间。其中透明度可从0变化到1;
ScaleAnimation: 大小缩放的动画。创建该动画时要指定动画开始时的缩放比(以x、y轴的缩放参数来表示)、结束时动画的缩放比,并指定动画持续时间。由于缩放时以不同点为中心缩放效果并不相同,因此指定缩放动画时还需要通过pivotX,pivotY来指定缩放中心的坐标;
TranslateAnimation: 位移变化的动画,创建动画时只要指定动画开始时的位置(以X,Y坐标来表示)、结束时的位置,并指定动画持续时间即可;
RotateAnimation: 旋转动画。创建该动画时需要指定动画开始时的旋转角度、结束时的旋转角度,并指定动画持续时间。由于旋转时以不同点为中心旋转效果不一样,因此指定旋转动画还要通过pivotX,pivotY来指定旋转轴心的坐标。
补充:
pivotX和pivotY
关于动画属性pivotX和pivotY的值可以设置成三种形式:整数值、百分数(或小数)和百分数p 三种形式,比如50、50%(或0.5)和50%。需要明确的是,这里以进行动画控件左上角为原点坐标。当属性值为数值,如 50 时,表示原点坐标加上 50px,作为起始点;如果是百分数,比如 50%,表示原点坐标加上自己宽度的 50%(即控件水平中心)作为起始点 ;如果是 50%p(字母 p 是 parent 的意思),取值的基数是父控件,因此 50%p 就是表示在原点坐标加上父控件宽度的 50% 作为起始点 x 轴坐标。总之就是:三者都是在原点坐标的基础上变化。具体可以参考文章”图解 Android View动画中 android:pivotX 和 android:pivotY 属性的含义_hust_twj的博客-CSDN博客_android:pivotx“
fromXDelta和toXDelta
TranslateAnimation动画的fromXDelta和toXDelta取值也是以动画控件左上角为原点坐标。
Interpolator
为了控制在动画期间需要动态补入多少帧,具体在动画运行运行的哪些时刻补入帧,需要借助于InterPolator。
Interpolator根据特定算法计算出整个动画所需动态插入帧的密度和位置,简单来说,InterPolator负责控制动画的变化速度,这就使得基本的动画效果能以匀速变化、加速、减速、抛物线速度等各种速度变化。
LinearInterpolator:动画以匀速的变化速度;
AccelerateInterpolator:匀加速变化;
AccelerateDecelerateInterpolator:先匀加速,后匀减速变化;
CycleInterpolator:动画循环播放特定的次数,变化速度按正弦曲线改变;
DecelerateInterpolator:匀减速变化;
xml定义补间动画资源
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/linear_interpolator"
android:fillAfter="true">
<scale android:fromXScale="1.0"
android:toXScale="0.01"
android:fromYScale="1.0"
android:toYScale="0.01"
android:pivotX="10%"
android:pivotY="10%"
android:duration="13000"/>
<alpha android:fromAlpha="1"
android:toAlpha="0.05"
android:duration="3000"
android:fillAfter="true"/>
<rotate android:fromDegrees="0"
android:toDegrees="1800"
android:pivotY="50%"
android:pivotX="50%"
android:duration="13000"
android:fillAfter="true"/>
<translate android:fromXDelta="0"
android:toXDelta="100"
android:fromYDelta="0"
android:toYDelta="100"/>
</set>
fillBefore和fillAfter属性
fillBefore是指动画结束时画面停留在第一帧,fillAfter是指动画结束是画面停留在最后一帧。
1、在代码中设置
animation.setFillAfter(true);
2、在animation的xml文件中设置,但是必须设置成set标签的属性才会生效!!!
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/linear_interpolator"
android:fillAfter="true">
<scale android:fromXScale="1.0"
android:toXScale="0.01"
android:fromYScale="1.0"
android:toYScale="0.01"
android:pivotX="50%"
android:pivotY="50%"
android:duration="3000"/>
...
/>
优先级:当xml文件和java代码中都对fillAfter属性进行了设置,则java代码中的优先级更高。
使用补间动画
1、加载/创建补间动画资源:
//加载补间动画
val tweenAnimation = AnimationUtils.loadAnimation(this, R.anim.tweenanim)
tweenAnimation.fillAfter = false
//代码中创建补间动画对象
var translate = TranslateAnimation(0F, transX,0F, transY)
translate.duration = 1000
translate.fillAfter = true
2、利用imageview启动补间动画
image.startAnimation(translate)