1.概念
View Animation,国内翻译成补间动画。从英文名称可以看出,这种动画作用在View上,通过对位置、大小、旋转和透明度的改变,让View内容动起来。这种方式比手动重新绘制Canvas来达到相似的效果要节省很多资源。
2.适用范围
- Activity间的转换
- Activity内的布局间的转换
- 相同View中的不同内容间的转换
- 为用户提供反馈,例如提示进度,通过“晃动”输入框来说明错误或者无效的数据输入
3.分类
- AlphaAnimation 可以改变View的透明度(不透明或者alpha混合)
- RotateAnimation 可以在XY二维平面上旋转选中的View Canvas
- ScaleAnimation 允许缩放选中的View
- TranslateAnimation 可以在屏幕上移动选中的View(但是它只能在其原始边界的范围内显示)
同时系统还提供了AnimationSet 类(对应XML文件中的set标签)来对动画进行分组和配置,从而让他们作为一个集合运行。
4.创建动画
创建补间动画可分为XML方式或Java代码方式动态创建。
XML方式
在res/anim目录下创建新的XML文件
例如:
<?xml version="1.0" encoding="utf-8"?>
<rotate
xmlns:android="http://schemas.android.com/apk/res/android"
android:fromDegrees="-180"
android:toDegrees="0"
android:pivotX="50%"
android:pivotY="50%"
android:fillAfter="true"
android:duration="200" />
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate android:fromYDelta="0" android:toYDelta="-100%" android:duration="200"/>
<alpha android:fromAlpha="1.0" android:toAlpha="0.0" android:duration="200" />
</set>
Java代码方式
例如:
TranslateAnimation translateAnimation = new TranslateAnimation(0,200,0,200);
translateAnimation.setDuration(3000);
translateAnimation.setRepeatCount(2);
translateAnimation.setRepeatMode(RESTART);
5.插值器Interpolator
开发者使用补间动画,无须定义动画过程的每一帧,只需要定义动画的开始和结束这两个关键帧,并指定动画变化的时间和方式等等,其余的就可以交由Android 系统计算实现,而系统依靠的就是插值器Interpolator。具体来说,Interpolator 会根据类型的不同,选择不同的算法计算出在补间动画期间所需要动态插入帧的密度和位置,Interpolator 负责控制动画的变化速度,使得前面所说的四种基本动画效果能够以匀速、加速、减速、抛物线等多种速度进行变化。
/**
* An interpolator defines the rate of change of an animation. This allows
* the basic animation effects (alpha, scale, translate, rotate) to be
* accelerated, decelerated, repeated, etc.
*/
public interface Interpolator extends TimeInterpolator {
// A new interface, TimeInterpolator, was introduced for the new android.animation
// package. This older Interpolator interface extends TimeInterpolator so that users of
// the new Animator-based animations can use either the old Interpolator implementations or
// new classes that implement TimeInterpolator directly.
}
/**
* A time interpolator defines the rate of change of an animation. This allows animations
* to have non-linear motion, such as acceleration and deceleration.
*/
public interface TimeInterpolator {
/**
* Maps a value representing the elapsed fraction of an animation to a value that represents
* the interpolated fraction. This interpolated value is then multiplied by the change in
* value of an animation to derive the animated value at the current elapsed animation time.
*
* @param input A value between 0 and 1.0 indicating our current point
* in the animation where 0 represents the start and 1.0 represents
* the end
* @return The interpolation value. This value can be more than 1.0 for
* interpolators which overshoot their targets, or less than 0 for
* interpolators that undershoot their targets.
*/
float getInterpolation(float input);
}
具体到Android 代码中,Interpolator 类实际上是继承自TimeInterpolator的一个空接口,TimeInterpolator时间插值器允许动画进行非线性运动变换,如加速或减速等。而Android SDK 也为我们提供了几个Interpolator的实现类:
- AccelerateDecelerateInterpolator 在动画开始与结束的时候速率改变比较慢,在中间的时候加速
- AccelerateInterpolator 在动画开始的地方速率改变比较慢,然后开始加速
- AnticipateInterpolator 在动画开始的时候先向后,然后向前滑动
- AnticipateOvershootInterpolator 动画开始的时候先向后,然后向前甩一定值后返回最后的值
- BounceInterpolator 动画结束的时候弹起
- CycleInterpolator 动画循环播放特定的次数,速率的改变遵循正弦曲线
- DecelerateInterpolator 在动画开始的地方速率改变比较快,然后开始变慢
- LinearInterpolator 动画以常量速率进行改变
- OvershootInterpolator 动画向前甩一定值后再回到原来位置
- PathInterpolator 新增的,通过定义路径坐标,动画可以按照路径坐标来运行;注意这里的坐标并不是指十字坐标系,而是单方向,也就是可以从0~1,然后弹回0.6后再弹到0.8,直到最后时间结束
6 使用动画监听器
AnimationListener 可以用于创建一个事件处理程序,当动画开始或结束的时候触发它。这样就可以在动画开始之前或者结束之后执行某些操作,例如改变View的内容或者连接多个动画。
animation.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
//在动画开始时执行处理
}
@Override
public void onAnimationEnd(Animation animation) {
//在动画结束时执行处理
}
@Override
public void onAnimationRepeat(Animation animation) {
//在动画重复时执行处理
}
});
7 为布局和 ViewGroup 添加动画
使用LayoutAnimationController为ViewGroup 的每一个子View添加动画,还可以设置动画的执行顺序和起始时间:
LayoutAnimationController 可以选择每一个View的开始偏移时间(以毫秒为单位),以及把动画应用到每一个子View中的顺序和起始时间(正向、反向、随机)。
GridLayoutAnimationController 这是一个派生类,它使用由行和列所映射的网格来向子View分配动画序列。
创建和使用布局动画
XML方式:
1.创建动画:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate android:fromYDelta="0" android:toYDelta="-100%" android:duration="200"/>
</set>
2.创建LayoutAnimation
<?xml version="1.0" encoding="utf-8"?>
<layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"
android:delay="0.5"
android:animationOrder="random"
android:animation="@anim/anim_fill"/>
3.布局引用
android:layoutAnimation="@anim/anim_layout"
Java代码方式:
1.创建动画
2.创建LayoutAnimationController对象,,传入动画并进行一些自定义动画设置
LayoutAnimationController controller = new LayoutAnimationController(animation);
- 调用setLayoutAnimation方法对ViewGroup或布局设置
constraintLayout.setLayoutAnimation();
布局动画使用技巧
布局动画会在ViewGroup第一次进行布局的时候执行一次,可以通过对ViewGroup对象调用scheduleLayoutAnimation 方法来强制它再次执行。当然,不是在调用之后立即执行,而是在它下次被布局的时候。
布局动画也支持动画监听器。
LayoutAnimationController controller = new LayoutAnimationController(scaleAnimation);
constraintLayout.setLayoutAnimation(controller);
constraintLayout.setLayoutAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
}
@Override
public void onAnimationRepeat(Animation animation) {
}
});
constraintLayout.scheduleLayoutAnimation();