Animation

动画

  • 帧动画

  • 补间动画

  • 属性动画

  • Interpolator

帧动画 FrameAnimation

其实就是一个Drawable ,将一系列的图片联合起来顺序的播放。形成动画效果。

帧动画本质就是一些图片的集合,要播放这个动画就必须将一系列的图片全部加载进内存中,所以帧动画的图片不易过大。

创建drawable文件

  • oneshot :是否只播放一次,

  • drawable :一帧的图片

  • duration :一帧播放的时间 毫秒单位

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android" android:oneshot="true">
<item android:drawable="@mipmap/a_01" android:duration="200"/>
<item android:drawable="@mipmap/a_02" android:duration="200"/>
<item android:drawable="@mipmap/a_03" android:duration="200"/>
<item android:drawable="@mipmap/a_04" android:duration="200"/>
<item android:drawable="@mipmap/a_5" android:duration="200"/>
<item android:drawable="@mipmap/a_6" android:duration="200"/>
</animation-list>

使用刚才的drawable文件做背景

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<ImageView
android:id="@+id/image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:background="@drawable/drawable_frame"
android:clickable="true"
android:onClick="onClick"/>

播放动画

1
2
3
4
//FrameAnimation 帧动画
((AnimationDrawable)image.getBackground()).start();

image


补间动画 tweenAnimation

主要是对view的内容完成一系列的图形变换(缩放,透明,旋转,平移)来实现动画效果。
具体来说就是 预先定义一些指令 ,这些指令指定了图形变换的类型,触发时间,持续时间。指令可以预先定义在xml文件中也可以源代码的方式定义。程序沿着时间线执行这些指令就可以实现动画效果。

Android中提供了 Animation,Interpolator,Transformation 等类具体实现Tween动画,

Animation类及其子类是动画的核心模块,它实现了 各种动画效果如 平移 旋转 缩放 改变透明度等等。

Tween动画的每一帧都根据Interpolator对view的内容做一次图像变换,因此Animation的核心工作是做变换(transformation);

Animation是基类 ,它记录了动画的通用属性和方法。主要的属性包括动画持续时间、重复次数、Interpolator等。

常用属性

  • duration :动画时间 毫秒

  • infinite :无限次

  • fillAfter 是否停顿在最后一针

  • repeatMode 重复模式 值:restart 重新开始 reserve 反复

  • repeatCount :重复次数

  • startOffset :开始延迟时间

常用Animation子类:

  • AlphaAnimation 改变Alpha值

  • TranslationAnimation 平移动画

  • RotateAnimation 旋转动画

  • ScaleAnimation 缩放动画

  • AnimationSet 动画集合

实例

补间动画 既可以使用 xml文件预先定义 也可以使用代码动态创建;

使用xml文件定义必须在 res/anim/目录下创建 文件;

可以使用 AnimationUtils的静态方法 loadAnimation()将动画文件加载

AlphaAnimation 透明度改变动画

定义 AlphaAnimation 文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
android:fromAlpha="1"
android:toAlpha="0.1"
android:duration="2000"
android:repeatCount="5"
android:repeatMode="reverse">
</alpha>
加载 动画文件并播放
1
2
3
4
5
6
//AlphaAnimation xml定义
AlphaAnimation alphaAnimation = (AlphaAnimation) AnimationUtils.loadAnimation(this,R.anim.anim_alpha);
view.startAnimation(alphaAnimation);
代码创建
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//AlphaAnimation 代码创建
AlphaAnimation alphaAnimation1 = new AlphaAnimation(0.1f,0.8f);
alphaAnimation1.setDuration(2000);
alphaAnimation1.setStartOffset(100);
alphaAnimation1.setFillAfter(true);
alphaAnimation1.setRepeatCount(2);
alphaAnimation1.setRepeatMode(Animation.REVERSE);
view.startAnimation(alphaAnimation1);

TranslationAnimation 平移动画

  • fromXDelta X轴开始坐标

  • toXDelta X轴结束坐标

  • fromYDelta Y 轴开始坐标

  • toYDelta Y轴结束坐标

>

定义动画文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="2000"
android:fromXDelta="0"
android:toXDelta="300"
android:repeatMode="reverse"
android:repeatCount="3"
android:fillBefore="true"
android:fromYDelta="200"
android:toYDelta="100">
</translate>
加载动画并播放
1
2
3
4
TranslateAnimation translateAnimation = (TranslateAnimation) AnimationUtils.loadAnimation(this,R.anim.anim_translation);
view.startAnimation(translateAnimation);
代码创建动画
1
2
3
4
5
6
7
8
TranslateAnimation translateAnimation1 = new TranslateAnimation(-10,100,0,0);
translateAnimation1.setInterpolator(new BounceInterpolator());
translateAnimation1.setDuration(2000);
view.startAnimation(translateAnimation1);

RotateAnimation 旋转动画

  • fromDegrees:起始角度

  • toDegrees:到达角度

  • pivotX:X轴中心点

  • pivotY:Y轴中心点

中心点取值模式:

  • 固定像素 50

  • 相对于自身 50%

  • 相对于父容器 50%p

定义动画文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:pivotX="50%"
android:pivotY="50%"
android:toDegrees="90"
android:fromDegrees="0"
android:duration="2000"
android:fillAfter="true">
</rotate>
加载动画并播放
1
2
3
4
RotateAnimation rotate = (RotateAnimation) AnimationUtils.loadAnimation(this,R.anim.anim_rotate);
view.startAnimation(rotate);
代码创建动画
1
2
3
4
5
6
7
8
9
10
11
12
//在右上角中心,0-180度
RotateAnimation rotate = new RotateAnimation(0, 180);
//(100,100)像素位中心
RotateAnimation rotate = new RotateAnimation(0, 180, 100, 100);
//相对于自身一半为中心
RotateAnimation rotate = new RotateAnimation(0, 180,Animation.RELATIVE_TO_SELF, 0.5f,Animation.RELATIVE_TO_SELF, 0.5f);

沿中心旋转 45°

1
2
3
4
5
6
7
8
9
10
RotateAnimation rotateAnimation = new RotateAnimation(0,45,Animation.RELATIVE_TO_SELF, 0.5f,Animation.RELATIVE_TO_SELF, 0.5f);
rotateAnimation.setInterpolator(new DecelerateInterpolator());
rotateAnimation.setDuration(2000);
rotateAnimation.setFillAfter(true);
view.startAnimation(rotateAnimation);

ScaleAnimation 缩放动画

  • fromXScale:X轴起始缩放值

  • fromYScale:Y轴起始缩放值

  • toXScale:X轴到达缩放值

  • toYScale:Y轴到达缩放值

  • 缩放值可以是缩放倍数,也可以是缩放到具体尺寸

定义动画文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
android:fromXScale="0"
android:toXScale="2"
android:fromYScale="0"
android:toYScale="3"
android:duration="2000"
android:pivotY="50%"
android:pivotX="50%">
</scale>
加载动画并播放
1
2
3
4
ScaleAnimation scale = (ScaleAnimation) AnimationUtils.loadAnimation(this,R.anim.anim_scale);
view.startAnimation(scale);
代码创建动画
1
2
3
4
5
6
ScaleAnimation scale = new ScaleAnimation(0, 2, 0, 2);
ScaleAnimation scale = new ScaleAnimation(0, 2, 0, 2, 100, 100);
ScaleAnimation scale = new ScaleAnimation(0, 2, 0, 2,Animation.RELATIVE_TO_PARENT, 0.5f,Animation.RELATIVE_TO_PARENT, 0.5f);

AnimationSet 动画集合

定义动画文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="2000">
<rotate android:pivotX="0"
android:pivotY="0"
android:fromDegrees="-180"
android:toDegrees="0"/>
<scale android:pivotX="50%"
android:pivotY="50%"
android:fromXScale="0"
android:toXScale="1"
android:fromYScale="0"
android:toYScale="1"/>
</set>
加载动画并播放
1
2
3
4
Animation animation = AnimationUtils.loadAnimation(this,R.anim.anim_set);
view.startAnimation(animation);
代码创建动画
1
2
3
4
5
6
7
8
9
10
11
12
13
14
//子动画是否共用差值器
AnimationSet set = new AnimationSet(true);
set.addAnimation(new RotateAnimation(-180,0));
set.addAnimation(new ScaleAnimation(0,1,0,1,Animation.RELATIVE_TO_SELF, 0.5f,Animation.RELATIVE_TO_SELF,0.5f));
set.setDuration(2000);
set.setFillAfter(true);
view.startAnimation(set);

Interpolator

Interpolator 被用来修饰动画效果,定义动画的变化率,可以使存在的动画效果accelerated(加速),decelerated(减速),repeated(重复),bounced(弹跳)等。

常用的差值器

  • LinearIntepolator 匀速效果

  • DecelerateInterpolator 减速效果

  • Accelerateinterpolator 加速效果

  • CycleInterpolator 循环效果

  • BouncedInterpolator 弹跳效果


Property Animation 属性动画

属性动画的用处有很多很多,我就列几个常用的方式把;具体参考官网文档:https://developer.android.com/guide/topics/graphics/prop-animation.html

补间动画并不能改变view真实的位置,只是形式上的位置改变。而属性动画会将view的真实位置改变。

属性动画定义必须在 res/animator目录下

ValueAnimation

valueType 常用三种取值:

  • intType整数值、

  • floatType浮点值、

  • colorType颜色值、

定义动画文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?xml version="1.0" encoding="utf-8"?>
<animator xmlns:android="http://schemas.android.com/apk/res/android"
android:valueFrom="2"
android:valueTo="200"
android:duration="2000"
android:valueType="intType"
android:interpolator="@android:interpolator/linear">
</animator>

加载动画 并添加 动画监听

属性动画 就是在 监听中去改变控件的属性的值 ,让控件 位置和形态的属性都发生真正的变化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
ValueAnimator animator = (ValueAnimator) AnimatorInflater.loadAnimator(this,R.animator.animator_value);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
//intType
int value= (int) animation.getAnimatedValue();
image.setTranslationY(value);
// image.setTranslationX(value);
//floatType
// float alpha = (float) animation.getAnimatedValue();
// image.setAlpha(alpha);
}
});

代码创建

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
// ValueAnimator valueAnimator = ValueAnimator.ofFloat(1f,0.5f,0f);
PropertyValuesHolder alphaHolder = PropertyValuesHolder.ofFloat("alpha",1f,0.5f);
PropertyValuesHolder widthHolder = PropertyValuesHolder.ofInt("width",1,200);
PropertyValuesHolder rotateHolder = PropertyValuesHolder.ofFloat("rotate",0,180);
ValueAnimator valueAnimator = ValueAnimator.ofPropertyValuesHolder(alphaHolder,widthHolder,rotateHolder);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
// float value= (float) animation.getAnimatedValue();
// image.setAlpha(value);
float alpha= (float) animation.getAnimatedValue("alpha");
int width = (int) animation.getAnimatedValue("width");
float rotate = (float) animation.getAnimatedValue("rotate");
Log.e("MainActivity","alpha:"+alpha);
Log.e("MainActivity","width:"+width);
image.setAlpha(alpha);
image.setMaxWidth(width);
image.setMinimumWidth(width);
image.setRotation(rotate);
}
});
valueAnimator.setDuration(2000);
valueAnimator.start();

ObjectAnimator

大部分属性都和ValueAnimator相同,只多了对要控制改变的控件的属性的声明

propertyName:要控制的控件的属性名;

动画会直接修改制定属性名的属性

需要注意:设置了getter/setter方法的属性才能生效

定义动画文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:propertyName="rotation"
android:valueFrom="0"
android:valueTo="45"
android:duration="2000"
android:valueType="floatType">
<!--
rotation
rotationY
rotationX
-->
</objectAnimator>

加载动画并设置播放动画的对象

1
2
3
4
5
6
ObjectAnimator object = (ObjectAnimator) AnimatorInflater.loadAnimator(this,R.animator.animator_object);
object.setTarget(image);
object.start();

代码创建动画

凡是 有get/set方法的属性都可以设置值

1
2
3
4
5
6
7
8
9
10
// ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(image,"alpha",1f,0.2f);
ObjectAnimator objectAnimator = ObjectAnimator.ofInt(view,"backgroundColor", Color.RED,Color.YELLOW,Color.BLUE,Color.GREEN);
objectAnimator.setDuration(2000);
objectAnimator.setInterpolator(new BounceInterpolator());
objectAnimator.start();

完整代码github地址:https://github.com/sky-mxc/AndroidDemo/tree/master/animation

坚持原创技术分享,您的支持将鼓励我继续创作!