传统 View 动画(Tween/Frame)
1.1 Tween 补间动画
主要有 4 中:缩放、平移、渐变、旋转
文件位置: res/anim/filename.xml
编译资源的数据类型:an Animation
资源引用:
Java: R.anim.filename
编译资源的数据类型:an Animation
资源引用:
Java: R.anim.filename
XML: @[package:]anim/filename
布局文件必须有一个独立的根元素,可以是
<alpha>
,
<scale>
,
<translate>
,
<rotate>
,
<set>
(持有一组其它的动画元素,甚至可以是内嵌的 set 元素) 中的一个.
1.1.1 <set>
一个持有其它动画元素的容器
<alpha>
,
<scale>
,
<translate>
,
<rotate>
或者其它
<set>
元素
属性
android:interpolator
应用于动画的插值器。
1.1.2 <alpha>
一个渐入渐出的动画,对应的 java 类为 AlphaAnimation
属性
android:fromAlpha,
android:toAlpha
代表动画开始和结束时透明度,0.0 表示完全透明,1.0 表示完全不透明,Float 值
1.1.3 <scale>
可以实现动态调控件尺寸的效果,通过设置 pivotX 和 pivotY 你可以指定 image 缩放的中心点,比如:如果这些值是 0,则表示左上角,所有的缩放变化将沿着右下角的轨迹运动。对应的类为:ScaleAnimation
属性,android:fromXScale,android:toXScale,android:fromYScale,android:toYScale
Float 值,为动画起始到结束时,X、Y 坐标上的伸缩尺寸,0.0 表示收缩到没有,1.0 表示正常无伸缩
比如fromXScale=1.0,toXScale=0.5,表示X轴,开始到结束从比例1.0到0.5的缩放
android:pivotX,android:pivotY
代表缩放的中轴点 X/Y 坐标,浮点值
如果我们想表示中轴点为图像的中心,我们可以把两个属性值定义成 0.5 或者 50%。
1.1.4 <translate>
代表一个水平、垂直的位移。对应的类为 TranslateAnimation. 属性
android:fromXDelta 属性代表起始 X 方向的位置
android:toXDelta
android:fromYDelta
android:toYDelta
代表动画起始或者结束 X / Y 方向上的位置,Float 或者百分比值
浮点数 num%、num%p 分别相对于自身或者父控件
如果以浮点数字表示,是一个绝对值,代表相对自身原始位置的像素值;
如果以 num%表示,代表相对于自己的百分比,比如 toXDelta 定义为 100%就表示在 X 方向上移动自己的 1 倍距离
1.1.5
浮点数 num%、num%p 分别相对于自身或者父控件
如果以浮点数字表示,是一个绝对值,代表相对自身原始位置的像素值;
如果以 num%表示,代表相对于自己的百分比,比如 toXDelta 定义为 100%就表示在 X 方向上移动自己的 1 倍距离
如果以 num%p 表示,代表相对于父类组件的百分比。
1.1.5 <rotate>
是旋转动画,与之对应的 Java 类是 RotateAnimation
属性
android:fromDegrees
android:toDegrees
android:fromDegrees
android:toDegrees
代表起始和结束的
弧度位置即
角度,浮点值,单位:度
android:pivotX 属性代表旋转中心的 X 坐标值
android:pivotY 属性代表旋转中心的 Y 坐标值
Float 值或者百分比
这两个属性也有三种表示方式,但是 X 轴都是相对方向都是 Left,Y 轴都是相对于 Top
浮点数、num%、num%p;
数字方式代表相对于自身左边缘的像素值,
num%方式代表相对于自身左边缘或顶边缘的百分比,
自定义插值器 如果你对系统提供的插值器不满意,我们可以创建一个插值器资源修改插值器的属性,比如修改 AnticipateInterpolator 的加速速率,调整 CycleInterpolator 的循环次数等。为了完成这种需求,我们需要创建 XML 资源文件,然后将其放于/res/anim 下,然后再动画元素中引用即可。我们先来看一下几种常见的插值器可调整的属性:都是基础了
1.2.1
1.2.2
android:pivotY 属性代表旋转中心的 Y 坐标值
Float 值或者百分比
这两个属性也有三种表示方式,但是 X 轴都是相对方向都是 Left,Y 轴都是相对于 Top
浮点数、num%、num%p;
数字方式代表相对于自身左边缘的像素值,
num%方式代表相对于自身左边缘或顶边缘的百分比,
num%p 方式代表相对于父容器的左边缘或顶边缘的百分比
调用代码
ImageView image = (ImageView) findViewById(R.id.image);
Animation hyperspaceJump = AnimationUtils.loadAnimation(this, R.anim.hyperspace_jump);
image.startAnimation(hyperspaceJump);
另外,在动画中,如果我们添加了 android:fillAfter="true"后,这个动画执行完之后保持最后的状态;android:duration="integer"代表动画持续的时间,单位为毫秒。
1.1.6 插值器
用于修改一个动画过程中的速率,可以定义各种各样的非线性变化函数,比如加速、减速等
在 Android 中所有的插值器都是 Interpolator 的子类,通过 android:interpolator 属性你可以引用不同的插值器。下面是几种插值器:
你可以通过下面的方式使用它们
<set android:interpolator="@android:anim/accelerate_interpolator">
...
</set>
自定义插值器 如果你对系统提供的插值器不满意,我们可以创建一个插值器资源修改插值器的属性,比如修改 AnticipateInterpolator 的加速速率,调整 CycleInterpolator 的循环次数等。为了完成这种需求,我们需要创建 XML 资源文件,然后将其放于/res/anim 下,然后再动画元素中引用即可。我们先来看一下几种常见的插值器可调整的属性:都是基础了Interpolator接口,重写
getInterpolation()函数, 将动画已经消耗的时间的分数映射到一个表示插值的分数。 * 然后将插值与动画的变化值相乘来推导出当前已经过去的动画时间的动画变化量。
我们先来看一下几种常见的插值器可调整的属性:
<accelerateDecelerateInterpolator>
,加速减速插值器,
public float getInterpolation(float input) {
return (float)(Math
.cos
((input +
1
) * Math.PI) /
2
.0f
) +
0
.5f
;
}
<accelerateInterpolator> 加速插值器
android:factor 浮点值,加速速率,默认为 1
public AccelerateInterpolator(float factor)
{
mFactor = factor;
mDoubleFactor =
2
* mFactor; }
@Override
public float getInterpolation(float input)
{
if
(mFactor ==
1.0f
) {
return
input * input;
}
else
{
return
(
float
)Math.pow(input, mDoubleFactor);
}
}
<decelerateInterpolator>
android:factor 浮点值,减速的速率,默认为 1
public float getInterpolation(float input)
{
float
result;
if
(mFactor ==
1.0f
) {
result = (
1.0f
- ((
1.0f
- input) * (
1.0f
- input)));
}
else
{
result = (
float
)(
1.0f
- Math.pow((
1.0f
- input),
2
* mFactor));
}
return
result;
}
<cycleInterplolator>
正弦周期插值器 android:cycles int,循环的个数,默认为 1
public float getInterpolation(float input)
{
return
(
float
)(Math.sin(
2
* mCycles * Math.PI * input));
}
<anticipateInterploator>
回荡秋千插值器,android:tension 浮点值,起始点后退的张力、拉力数,默认为 2
public float getInterpolation(float t)
{
// a(t) = t * t * ((tension + 1) * t - tension)
return
t * t * (((mTension +
1
) * t) - mTension);
}
<anticipateOvershootInterpolator>
回荡秋千插值器 变种 ,
android:tension 同上 android:extraTension 浮点值,拉力的倍数,默认为 1.5(2 * 1.5)
<bounceInterpolator> 弹跳插值器
无
<linearInterpolator>
线性插值器,无
<overshootInterpolator>
浮点值,超出终点后的张力、拉力,默认为 2
比如:res/anim/my_overshoot_interpolator.xml:
<?xml version="1.0" encoding="utf-8"?>
<overshootInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
android:tension="7.0"/>
This animation XML will apply the interpolator:
<scale xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@anim/my_overshoot_interpolator"
android:fromXScale="1.0"
android:toXScale="3.0"
android:fromYScale="1.0"
android:toYScale="3.0"
android:pivotX="50%"
android:pivotY="50%"
android:duration="700" />
如果简单的修改插值器的属性值还不能够满足我们的需求,那么就自己来通过实现 Interpolator 接口来定义自己的插值器了 因为上面所有的 Interpolator 都实现了 Interpolator 接口,这个接口定义了一个方法:float getInterpolation(float input); 此方法由系统调用,input 代表动画的时间,在 0 和 1 之间,也就是开始和结束之间。
1.2 FrameAnimation (逐帧动画)
先来说说什么是逐帧动画,逐帧动画是一种常见的动画形式(Frame By Frame),其原理是在“连续的关键帧”中分解动画动作,也就是在时间轴的每帧上逐帧绘制不同的内容,使其连续播放而成动画。 因为逐帧动画的帧序列内容不一样,不但给制作增加了负担而且最终输出的文件量也很大,但它的优势也很明显:逐帧动画具有非常大的灵活性,几乎可以表现任何想表现的内容,而它类似与电影的播放模式,很适合于表演细腻的动画
文件目录:res/drawable/filename.xml
编译资源数据类型 AnimationDrawable
资源引用:
Java: R.drawable.filename
XML: @[package:]drawable.filename
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot=["true" | "false"] >
<item
android:drawable="@[package:]drawable/drawable_resource_name"
android:duration="integer" />
</animation-list>
1.2.1 <animation-list>
必须作为根元素,包含一个或者多个根元素
属性:android:oneshot :true:只执行一次动画,false:循环执行
1.2.2 <item>
<animation-list>
element. 一帧独立动画,必须是
<animation-list>
的子元素
属性
android:drawable
Drawable 资源,用于这一帧的图片
android:drawable
Drawable 资源,用于这一帧的图片
android:duration,Integer 类型.该帧的时长,单位为毫秒 milliseconds.
res/anim/rocket.xml:
<?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/rocket_thrust1" android:duration="200" />
<item android:drawable="@drawable/rocket_thrust2" android:duration="200" />
<item android:drawable="@drawable/rocket_thrust3" android:duration="200" />
</animation-list>
调用代码
ImageView rocketImage = (ImageView) findViewById(R.id.rocket_image);
rocketImage.setBackgroundResource(R.drawable.rocket_thrust);
rocketAnimation = (AnimationDrawable) rocketImage.getBackground();
rocketAnimation.start();
在Android中逐帧动画需要得到AnimationDrawable类的支持,它位于"android.graphics.drawable.AnimationDrawable"包下,是Drawable的间接子类。它主要用来创建一个逐帧动画,并且可以对帧进行拉伸,把它设置为View的背景即可使用AnimationDrawable.start()方法播放。既然逐帧动画是需要播放一帧一帧的图像,所以需要为其添加帧。在Android中提供了两种方式为AnimationDrawable添加帧:XML定义的资源文件和Java代码创建,后面再详细讲讲这两种添加帧的方式。
光为AnimationDrawable设置帧还不能完成播放动画的功能,还需要AnimationDrawable定义好的其他的一些方法来操作逐帧动画,下面简单介绍一下AnimationDrawable的常用方法:
• void start():开始播放逐帧动画。
• void stop():停止播放逐帧动画。
• void addFrame(Drawable frame,int duration):为AnimationDrawable添加一帧,并设置持续时间。
• int getDuration(int i):得到指定index的帧的持续时间。
• Drawable getFrame(int index):得到指定index的帧Drawable。
• int getNumberOfFrames():得到当前AnimationDrawable的所有帧数量。
• boolean isOneShot():当前AnimationDrawable是否执行一次,返回true执行一次,false循环播放。
• boolean isRunning():当前AnimationDrawable是否正在播放。
光为AnimationDrawable设置帧还不能完成播放动画的功能,还需要AnimationDrawable定义好的其他的一些方法来操作逐帧动画,下面简单介绍一下AnimationDrawable的常用方法:
• void start():开始播放逐帧动画。
• void stop():停止播放逐帧动画。
• void addFrame(Drawable frame,int duration):为AnimationDrawable添加一帧,并设置持续时间。
• int getDuration(int i):得到指定index的帧的持续时间。
• Drawable getFrame(int index):得到指定index的帧Drawable。
• int getNumberOfFrames():得到当前AnimationDrawable的所有帧数量。
• boolean isOneShot():当前AnimationDrawable是否执行一次,返回true执行一次,false循环播放。
• boolean isRunning():当前AnimationDrawable是否正在播放。
• void setOneShot(boolean oneShot):设置AnimationDrawable是否执行一次,true执行一次,false循环播放