概述
一般而言,我们在页面跳转或者加载数据时都是瞬间完成的,这样子会导致用户体验非常的不好;有神马方法能够解决这个问题呢?当然就是这篇文章所记录的动画啦。
1.分类
android中的动画分为三类,分别如下:
- 补间动画(Tween Animation)也常称为View动画
对视图进行一系列的图像变换(平移、旋转、缩放、透明度)产生的动画效果。它只改变View的显示,而对View的响应区域没有影响。 - 逐帧动画(Frame Animation)
顺序播放事先准备好的一系列图像。 - 属性动画(Property Animation)
通过反射技术动态的改变对象的属性从而产生动画效果,它不仅会改变View的显示,而且会改变View的响应区域。
本节主要介绍第一、二类动画。
提到动画,我们就不得不提到
Interpolator(插值器)
了,下面对插值器进行简单的介绍,详细下面的文章会进行介绍。
2.Interpolator-插值器
什么是插值器?-本质是一个数学函数,参数为[0.0,1.0]之间的浮点数,输出值也是[0.0,1.0]之间的浮点数,所代表曲线的斜率即为动画的速度。
Android常见的插值器有:(y值0-1)
Interpolator class | Resource ID | Description |
AccelerateDecelerateInterpolator | @android:anim/accelerate_decelerate_interpolator | 先加速后减速 |
AccelerateInterpolator | @android:anim/accelerate_interpolator | 加速 |
AnticipateInterpolator | @android:anim/anticipate_interpolator | 先反向运动(先加速后减速到0)(y值为负),正向加速运动到1 |
AnticipateOvershootInterpolator | @android:anim/anticipate_overshoot_interpolator | 先反向运动(先加速后减速到0)(y值为负),正向先加速后减速至0(此时值超出1),后反向到1 |
BounceInterpolator | @android:anim/bounce_interpolator | 仿小球下降后的回弹效果 |
CycleInterpolator | @android:anim/cycle_interpolator | 先加速到1,后反向加速到负数,再次运行到1,后到0 |
DecelerateInterpolator | @android:anim/decelerate_interpolator | 减速 |
LinearInterpolator | @android:anim/linear_interpolator | 匀速线性 |
OvershootInterpolator | @android:anim/overshoot_interpolator | 正向先加速后减速至0(此时值超出1),后反向到1 |
3.补间动画(Tween Animation )
其一般位于res/anim/
目录下。
查看Animation的继承结构,如图:
由上图,可知Animation抽象类的子类主要有以下四类。
ScaleAnimation | 缩放动画 |
TranslateAnimation | 平移动画 |
AlphaAnimation | 透明度动画 |
RotateAnimation | 旋转动画 |
这四种动画都可以通过Animation与AnimationUtils类配合使用。
XML语法为:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@[package:]anim/interpolator_resource"
android:fillAfter=["true" | "false"]
android:shareInterpolator=["true" | "false"] >
<alpha
android:fromAlpha="float"
android:toAlpha="float" />
<scale
android:fromXScale="float"
android:toXScale="float"
android:fromYScale="float"
android:toYScale="float"
android:pivotX="float"
android:pivotY="float" />
<translate
android:fromXDelta="float"
android:toXDelta="float"
android:fromYDelta="float"
android:toYDelta="float" />
<rotate
android:fromDegrees="float"
android:toDegrees="float"
android:pivotX="float"
android:pivotY="float" />
<set>
...
</set>
</set>
android:fillAfter | true代表停留在动画的终点 |
android:duration | 动画持续时间 |
android:interpolator | 插值器 |
android:shareInterpolator | 是否共享插值器 |
以下对各个标签下对应的属性进行简单介绍:
- < alpha/>对应透明度动画
0.0为透明,1.0为不透明
android:fromAlpha | 透明度的起始值 |
android:toAlpha | 透明度的起始值 |
- < scale/>对应缩放动画
1.0没有任何变化
android:fromXScale | x方向缩放比例的初始值 |
android:toXScale | x方向缩放比例的结束值 |
android:fromYScale | y方向缩放比例的初始值 |
android:toYScale | y方向缩放比例的初始值 |
android:pivotX | 缩放中心点x坐标 |
android:pivotY | 缩放中心点y坐标 |
- < rotate/>对应旋转动画
android:fromDegrees | 旋转角度的初始值 |
android:toDegrees | 旋转角度的结束值 |
android:pivotX | 旋转中心点x坐标 |
android:pivotY | 旋转中心点y坐标 |
- < translate/>对应缩放动画
android:fromXDelta | 移动起始点的x坐标 |
android:toXDelta | 移动终点的x坐标 |
android:fromYDelta | 移动起始点的y坐标 |
android:toYDelta | 移动终点的y坐标 |
注意点:
Float or percentage. 移动起始点的x坐标. 表示形式有三种:
1 相对于自己的左边界的距离,单位像素值。(例如 “5”)
2 相对于自己的左边界的距离与自身宽度的百分比。(例如 “5%”)
3 相对于父View的左边界的距离与父View宽度的百分比。(例如 “5%p”)
简单使用:<透明度动画>:
1.res/anim/下新建alpha.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" android:fillAfter="true">
<alpha
android:fromAlpha="1.0"
android:duration="5000"
android:interpolator="@android:anim/accelerate_interpolator"
android:toAlpha="0.0" />
</set>
2.使用
final Animation animation = AnimationUtils.loadAnimation(this,R.anim.alpha);
imageView.startAnimation(animation);
效果如图:
其他3类,请自行定义并使用。
Animation自带监听接口,可给其设置监听事件。
animation.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
Log.e("wdl", "onAnimationStart: ");
}
@Override
public void onAnimationEnd(Animation animation) {
Log.e("wdl", "onAnimationEnd: ");
}
@Override
public void onAnimationRepeat(Animation animation) {
Log.e("wdl", "onAnimationRepeat: ");
}
});
4.逐帧动画(Frame Animation )
其实是Drawable的一种,即AnimationDrawable,在res/drawable下新建animation.xml,其基本xml如下:
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android" android:oneshot="false">
<item android:duration="500" android:drawable="@drawable/a"/>
<item android:duration="500" android:drawable="@drawable/b"/>
<item android:duration="500" android:drawable="@drawable/c"/>
<item android:duration="500" android:drawable="@drawable/d"/>
</animation-list>
其中,duration即持续时长,drawable即显示的资源。android:oneshot=“true”
代表只播放一次。
怎么使用:
imageView.setBackgroundResource(R.drawable.animation_drawable);
AnimationDrawable drawable = (AnimationDrawable) imageView.getBackground();
drawable.start();
效果图:
4.补间动画的两个特殊使用场景
- 通过布局动画LayoutAnimation给ViewGroup的子View指定入场动画。如:ListView的入场动画。
- 为Activity自定义切换动画。
第一种:指定入场动画(方法一
)
- res/anim下新建自定义动画anim_list.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" android:shareInterpolator="true"
android:interpolator="@android:anim/accelerate_interpolator">
<scale
android:duration="500"
android:fromXScale="0.0"
android:fromYScale="0.0"
android:pivotX="50%"
android:pivotY="50%"
android:toXScale="1.0"
android:toYScale="1.0" />
<alpha
android:duration="500"
android:fromAlpha="0.0"
android:toAlpha="1.0"/>
</set>
- res/anim下新建包含layoutAnimation标签的xml文件
<?xml version="1.0" encoding="utf-8"?>
<layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"
android:animation="@anim/list_anim"
android:delay="0.5"
android:animationOrder="random"/>
其三个属性:
android:animation 需要引用的动画文件
android:delay 每个动画的延时时长
android:animationOrder 每个子项动画的出场顺序,normal正常,reserve倒序,random随机
- ViewGroup中引用layoutAnimation
<ListView
android:id="@+id/list"
android:divider="@color/colorAccent"
android:dividerHeight="1.0dp"
android:layoutAnimation="@anim/anim_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
方法二:
前几步与方法一一致,法二是在Java代码中动态设置:
<ListView
android:id="@+id/list"
android:divider="@color/colorAccent"
android:dividerHeight="1.0dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
即不用新建layoutAnimation.xml文件
//通过Java代码设置进场动画
Animation animation = AnimationUtils.loadAnimation(this,R.anim.list_anim);
LayoutAnimationController controller = new LayoutAnimationController(animation);
controller.setDelay(0.5f);
controller.setOrder(LayoutAnimationController.ORDER_RANDOM);
listView.setLayoutAnimation(controller);
第二种:界面切换动画
Android系统提供默认切换动画,通过调用overridePendingTransition(int enterAnim,int exitAnim)可自定义切换动画。注意: 这个方法必须在startActivity(Intent intent)或者finish()之后调用才会生效,否则无效。
结合上例使用:
startActivity(new Intent(ListActivity.this,MainActivity.class));
//设置转Activity动画
overridePendingTransition(R.anim.in_anim,R.anim.out_anim);
效果图:
注意事项:
如果要在Fragment中使用切换动画,需要使用FragmentTransaction.setCustomAnimations()来添加切换动画。不能采用属性动画。