Android-动画分析

Android的动画就可以分为3种:

  • View动画 View Animation
  • 帧动画 Drawable Animation
  • 属性动画 Property Animation

1.View动画

View动画的作用对象是View。View动画的View移动只是视觉效果,并不能真正的改变位置。

View动画的种类

种类 标签 子类 效果
平移动画 <translate> TranslateAnimation 平移View
缩放动画 <scale> ScaleAnimation 放大或者缩小View
旋转动画 <rotate> RotateAnimation 旋转View
透明度动画 <alpha> AlphaAnimation View的透明度变化

使用View动画

要使用View动画,需要先创建动画的XML文件,这个文件的路径为res/anim/animateFile.xml

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
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator=""
android:shareInterpolator="[true | false]"
android:fillAfter="true"
android:duration='integar'>


<translate
android:fromXDelta="float"
android:toXDelta="float"
android:fromYDelta="float"
android:toYDelta="float"/>

<scale
android:fromXScale="float"
android:toXScale="float"
android:fromYScale="float"
android:toYScale="float"
android:pivotX="float"
android:pivotY="float"/>

<rotate
android:fromDegrees="float"
android:toDegrees="float"
android:pivotY="float"
android:pivotX="float"/>

<alpha
android:fromAlpha="float"
android:toAlpha="float"/>


</set>

View动画既可以是单个动画,也可以由一系列动画组成。

<set>:表示动画集合,对应AnimationSet,可以包含若干个动画,并且内部也可以嵌套其他动画集合。

  • android:interpolator:表示动画集合所采用的插值器,插值器会影响到动画的速度。
  • android:shareInterpolator:是否共享插值器。如果不指定,子动画就需要单独指定插值器或者使用默认值。
  • android:fillAfter:表示动画结束时是否保持动画结束的状态。false回到动画初始样式
  • android:integar:表示动画持续时长

<translate>:表示平移动画,对应TranslateAnimation

  • android:fromXDelta:动画起始时X坐标上的位置。
  • android:toXDelta:动画结束时X坐标上的位置。
  • android:fromYDelta:动画起始时Y坐标上的位置。
  • android:toYDelta:动画结束时Y坐标上的位置。

以上4个属性的取值可能为数值,百分数,百分数P,他们的含义有所区别:

数值: 50 –> 以View左上角为原点,向正方向偏移50px

百分数 50% –> 以View左上角为原点,向正方向偏移View宽/高的50%

百分数P 50%P -> 以View左上角为原点,向正方向偏移父布局(parent)宽/高的50%;

<scale>:表示缩放动画,对应ScaleAnimation

  • android:fromXScale动画起始时水平方向伸缩值。
  • android:toXScale:动画结束时水平方向伸缩值。
  • android:fromYScale:动画起始时竖直方向伸缩值。
  • android:toYScale:动画结束时水平方向伸缩值。

以上4个属性的取值有不同的含义

值为0.0 缩放比为0 代表缩放到原来的0 即消失

值<1.0 缩放比小于1 代表缩小

值为1.0 缩放比等于1 代表与原来相同

值>1.0 缩放比大于1 代表放大

  • android:pivotX:缩放轴点的X坐标。
  • android:pivotY:缩放轴点的Y坐标。

以上两个属性表示 ,缩放的起始坐标,取值为%默认View的中心点,即50%,50%。举个例子:如果pivotX和pivotY设置为0,即为左上角坐标,缩放时就是以左上角为原点向外向内。

<rotate>:表示旋转动画,对应RotateAnimation

  • android:fromDegrees:动画起始时旋转的角度 。
  • android:toDegrees:动画结束时旋转的角度。

以上两个属性共同确定旋转方向,原则是:当角度为数时表示逆时针旋转,反之。

故共存在以下四种情况:

  • from=负数 -> to=正数:表示顺时针旋转
  • from=负数 ->to =负数:表示逆时针旋转
  • from=正数 ->to =正数:表示顺时针旋转
  • from=正数 ->to=负数:表示逆时针旋转
  • android:pivotX:旋转轴点的X坐标。
  • android:pivotY:旋转轴点的Y坐标。

<alpha>:表示透明度动画,对应AlphaAnimation

  • android:fromAlpha:动画起始时透明度。
  • android:toAlpha动画结束时透明度。

以上两个属性取值范围为 0~1

值<=0 代表完全透明

值>=1 代表完全不透明

应用代码

通过XML文件构建

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
<!-- animationset.xml -->
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:shareInterpolator="true" >


<translate
android:duration="2000"
android:fromXDelta="0"
android:fromYDelta="0"
android:toXDelta="100%"
android:toYDelta="100%">
/>
<scale
android:duration="2000"
android:fromXScale="1.0"
android:fromYScale="1.0"
android:pivotX="50%"
android:pivotY="50%"
android:toXScale="0.5"
android:toYScale="0.5" />

<rotate
android:duration="2000"
android:fromDegrees="0"
android:toDegrees="360"
android:pivotX="50%"
android:pivotY="50%"/>

<alpha
android:duration="2000"
android:fromAlpha="1.0"
android:toAlpha="0"/>

</set>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Animation animation = AnimationUtils.loadAnimation(this,R.anim.animationet);
view.startAnimation(animation);
animation.setAnimationListener(new AnimationListener(){
void onAnimationStart(Animation animation){
//动画开始
}

void onAnimationEnd(Animation animation){
//动画结束
}

void onAnimationRepeat(Animation animation){
//动画重复 设置 android:repeatMode="[restart | reverse]" 时触发
}
})

通过Java构建

1
2
3
4
5
6
7
AlphaAnimation alphaAnimation = new AlphaAnimation(1, 0);
alphaAnimation.setDuration(2000);

AnimationSet animationSet = new AnimationSet(true);
animationSet.addAnimation(alphaAnimation);

view.startAnimation(animationSet);

自定义View动画

自定义View动画是为了 实现系统提供的无法满足的动画情况,例如3D翻转效果,无法简单组合就能实现,就需要用到自定义View动画。

实现步骤:继承Animation -> 重写initialize()以及applyTransformation()方法

  • inltialize():初始化工作
  • allpyTransformation():进行相应的矩阵变换

自定义View动画实例

TODO

View动画特殊使用场景

1. LayoutAnimation

作用于ViewGroup,为ViewGroup指定一个动画,当它的子元素出场时都会具有这样的效果。

1
2
3
4
<layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"
android:delay=""
android:animationOrder=""
android:animation="" />

android:delay:表示子元素开始动画的延迟时间。

比如,设置子元素入场动画的周期为 300ms,delay设置为0.5意味着,每个子元素都需要延迟150ms播放动画

android:animationOrder :表示子元素动画的顺序

  • normal 正序显示,按照排列顺序播放
  • random 随机显示
  • reverse 逆序显示

android:animation:表示设置的子元素动画

应用代码

XML定义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// anim_layout.xml
<layoutAnimation
xmlns:android="http://schemas.android.com/apk/res/android"
android:animation="@anim/anim_layout_item"
android:delay="0.5"
android:animationOrder="normal">

</layoutAnimation>

//anim_layout_item.xml
<set
xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="500"
android:shareInterpolator="true"
android:interpolator="@android:anim/accelerate_interpolator">

<alpha
android:fromAlpha="0"
android:toAlpha="1" />

<scale
android:fromXScale="1"
android:toXScale="0" />

</set>

<ListView
android:layoutAnimation ="@anim/anim_layout" />

Java代码生成

1
2
3
4
5
Animation animation = AnimationUtils.loadLayoutAnimation(this, R.anim.anim_item);
LayoutAnimationController controller = new LayoutAnimationController(animation);//对应android:animation属性
controller.setDelay(0.5);//对应android:delay属性
controller.setOrder(LayoutAnimationController.ORDER_NORMAL);//对应android:animationOrder属性
listView.setLayoutAnimation(controller);//对应android:layoutAnimation属性

2.Activity切换效果

Activity有默认的切换效果,是由系统自己定义的。需要自定义切换效果就需要用到oberridePendingTransition(int inAnim,int outAnim)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// enter_anim.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/decelerate_interpolator">

<scale android:fromXScale="2.0" android:toXScale="1.0"
android:fromYScale="2.0" android:toYScale="1.0"
android:pivotX="50%p" android:pivotY="50%p"
android:duration="@android:integer/config_mediumAnimTime" />

</set>

//exit_anim.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/decelerate_interpolator"
android:zAdjustment="top">

<scale android:fromXScale="1.0" android:toXScale=".5"
android:fromYScale="1.0" android:toYScale=".5"
android:pivotX="50%p" android:pivotY="50%p"
android:duration="@android:integer/config_mediumAnimTime" />

<alpha android:fromAlpha="1.0" android:toAlpha="0"
android:duration="@android:integer/config_mediumAnimTime"/>

</set>
1
2
3
4
5
6
Intent intent =new Intent(this,AnimActivity.class);
startActivityIntent(intent);
overridePendingTransition(R.anim.enter_anim,R.anim.exit_anim);
//退出时设置
finish();
overridePendingTransition(R.anim.enter_anim,R.anim.exit_anim);

该方法必须在startActivity()或者finish()之后调用才生效。

2.帧动画

帧动画是顺序播放一组预先定义好的图片,对应AnimationDrawable

1
2
3
4
<animation-list  xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="[true | false]">

<item android:drawable="" android:duration="intreger"/>
</animation-list>

android:oneshot:表示是否播放一次

应用代码

XML方式

1
2
3
4
5
6
7
8
// animationlist.xml
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="false">

<item android:drawable="@drawable/bg1" android:duration="500"/>
<item android:drawable="@drawable/bg2" android:duration="500"/>
<item android:drawable="@drawable/bg3" android:duration="500"/>
<item android:drawable="@drawable/bg4" android:duration="500"/>
</animation-list>
1
2
3
view.setBackgroundResource(R.drawable.animationlist);
AnimationDrawable animationDrawable = (AnimationDrawable)mView.getBackground();
animationDrawable.start();

Java生成

1
2
3
4
5
6
7
8
AnimationDrawable ad = new AnimationDrawable();//1.创建AnimationDrawable对象
for (int i = 0; i < 4; i++) {//2.添加Drawable对象及其持续时间
Drawable drawable = getResources().getDrawable(getResources().getIdentifier("bg" + i, "drawable", getPackageName()));
ad.addFrame(drawable, 500);
}
ad.setOneShot(false);//3.设置是否执行一次
mView.setBackgroundResource(ad);//4.将帧动画作为view背景
ad.start();//5.播放动画

使用帧动画时要注意不能使用尺寸过大的图片。否则容易造成OOM错误

优化内存占用

由于图片全部是从xml中读取的,一定要全部读取下来动画才可以开始,因为要不断地替换图片去实现动画效果。一次性取出所有图片,就容易导致OOM

优化思路:一次只取一个图片,开启一个线程去取下一张,达到一致的效果。

3.属性动画


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!