Android 中的控件动画可以分为以下3类:逐帧动画、补间动画、属性动画。本篇介绍android中补间动画的使用。
补间动画需要指定动画的开始和结束的"关键帧",而动画变化的"中间帧"由系统计算,并通过插补器interpolator自动补齐。
补间动画有四种:
- 透明度: alpha
- 位移:translate
- 缩放:scale
- 旋转: rotate
系统提供的插补器,常用有以下几种:
- accelerate_decelerate_interpolator 其变化开始和结束速率较慢,中间加速
- accelerate_interpolator 其变化开始速率较慢,后面加速
- decelerate_interpolator 其变化开始速率较快,后面减速
- linear_interpolator 其变化速率恒定
- anticipate_interpolator 其变化开始向后甩,然后向前
四种基本补间动画
动画的实现可以通过xml或java代码两种方式。我们先使用java代码:
透明度
// 1. fromAlpha:动画开始时视图的透明度(取值范围: -1 ~ 1)
// 2. toAlpha:动画结束时视图的透明度(取值范围: -1 ~ 1)
Animation alphaAnimation = new AlphaAnimation(1,0);
alphaAnimation.setDuration(2000);
imgRun.startAnimation(alphaAnimation);
位移
// 创建平移动画的对象:平移动画对应的Animation子类为TranslateAnimation
// 参数分别是:
// 1. fromXDelta :视图在水平方向x 移动的起始值
// 2. toXDelta :视图在水平方向x 移动的结束值
// 3. fromYDelta :视图在竖直方向y 移动的起始值
// 4. toYDelta:视图在竖直方向y 移动的结束值
Animation translateAnimation = new TranslateAnimation(0,500,0,500);
translateAnimation.setDuration(3000);
imgRun.startAnimation(translateAnimation);
缩放
// 1. fromX :动画在水平方向X的结束缩放倍数
// 2. toX :动画在水平方向X的结束缩放倍数
// 3. fromY :动画开始前在竖直方向Y的起始缩放倍数
// 4. toY:动画在竖直方向Y的结束缩放倍数
// 5. pivotXType:缩放轴点的x坐标的模式
// 6. pivotXValue:缩放轴点x坐标的相对值
// 7. pivotYType:缩放轴点的y坐标的模式
// 8. pivotYValue:缩放轴点y坐标的相对值
// pivotXType = Animation.ABSOLUTE:缩放轴点的x坐标 = View左上角的原点 在x方向 加上 pivotXValue数值的点(y方向同理)
// pivotXType = Animation.RELATIVE_TO_SELF:缩放轴点的x坐标 = View左上角的原点 在x方向 加上 自身宽度乘上pivotXValue数值的值(y方向同理)
// pivotXType = Animation.RELATIVE_TO_PARENT:缩放轴点的x坐标 = View左上角的原点 在x方向 加上 父控件宽度乘上pivotXValue数值的值 (y方向同理)
Animation scaleAnimation= new ScaleAnimation(0,2,0,2,Animation.RELATIVE_TO_SELF,0.5f,Animation.RELATIVE_TO_SELF,0.5f);
scaleAnimation.setDuration(2000);
imgRun.startAnimation(scaleAnimation);
旋转
// 1. fromDegrees :动画开始时 视图的旋转角度(正数 = 顺时针,负数 = 逆时针)
// 2. toDegrees :动画结束时 视图的旋转角度(正数 = 顺时针,负数 = 逆时针)
// 3. pivotXType:旋转轴点的x坐标的模式
// 4. pivotXValue:旋转轴点x坐标的相对值
// 5. pivotYType:旋转轴点的y坐标的模式
// 6. pivotYValue:旋转轴点y坐标的相对值
// pivotXType = Animation.ABSOLUTE:旋转轴点的x坐标 = View左上角的原点 在x方向 加上 pivotXValue数值的点(y方向同理)
// pivotXType = Animation.RELATIVE_TO_SELF:旋转轴点的x坐标 = View左上角的原点 在x方向 加上 自身宽度乘上pivotXValue数值的值(y方向同理)
// pivotXType = Animation.RELATIVE_TO_PARENT:旋转轴点的x坐标 = View左上角的原点 在x方向 加上 父控件宽度乘上pivotXValue数值的值 (y方向同理)
Animation rotateAnimation = new RotateAnimation(0,270,Animation.RELATIVE_TO_SELF,0.5f,Animation.RELATIVE_TO_SELF,0.5f);
rotateAnimation.setDuration(2000);
imgRun.startAnimation(rotateAnimation);
组合动画
可以把集中基本动画进行组合,我们使用xml方式。在/res/anim/文件夹下添加一个xml文件set_anim.xml,把四种动画进行组合。
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/accelerate_decelerate_interpolator">
<scale
android:duration="3000"
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="3000"
android:fromAlpha="1.0"
android:toAlpha="0.5" />
<rotate
android:fromDegrees="0"
android:toDegrees="720"
android:pivotX = "50%"
android:pivotY="50%"
android:duration = "3000"/>
<translate
android:fromXDelta="0"
android:toXDelta="200"
android:fromYDelta="0"
android:toYDelta="0"
android:duration = "3000"/>
</set>
代码调用:
Animation anim = AnimationUtils.loadAnimation(getApplicationContext(),R.anim.set_anim);
//设置动画结束后保留结束状态
anim.setFillAfter(true);
imgRun.startAnimation(anim);
监听动画事件
可以监听动画的开始、结束、重复的事件。
anim.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
Toast.makeText(getApplicationContext(),"动画结束",Toast.LENGTH_SHORT).show();
}
@Override
public void onAnimationRepeat(Animation animation) {
}
});
自定义补间动画
Animation 是补间动画抽象基类,我们自定义动画就是要集成这个类,并覆写两个方法initialize和applyTransformation。
initialize:里面可获取控件的宽高和父容器的宽高
applyTransformation:这里面是实现动画的关键。在动画执行过程中,这个方法会被调用很多次,每次传进来的interpolatedTime值是不同的,这个值是根据你采用的插补器类型由系统计算好传过来,范围是0-1。Transformation参数代表了补间动画在不同时刻对图形或组件的变形程度。
public class JumpeggAnimation extends Animation {
@Override
public void initialize(int width, int height, int parentWidth, int parentHeight) {
super.initialize(width, height, parentWidth, parentHeight);
}
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
t.getMatrix().setTranslate((float) Math.sin(interpolatedTime*24)*50,(float) Math.sin(interpolatedTime*24)*25);
super.applyTransformation(interpolatedTime, t);
}
}
现在我们要实现一个JumpEgg的震动效果(上下左右摆动),就是要对控件的X、Y坐标进行周期性的变化,本文使用了数学中的正弦函数作为周期函数,使用interpolatedTime参数作为周期变化因子,实现了X\Y轴的左右变化。使用如下:
Animation jupAnimation= new JumpeggAnimation();
jupAnimation.setDuration(1500);
imgRun.startAnimation(jupAnimation);
布局与视图动画
android 对各种布局Layout也支持动画,用到LayoutAnimationController 类.比如我们对上面的几个按钮添加动画,也就是对他们的父容器LinearLayout设置动画:
Animation alphaAnimation = new AlphaAnimation(1,0);
alphaAnimation.setDuration(2000);
LayoutAnimationController lac =new LayoutAnimationController(alphaAnimation,0.5f);//0.5f表示每个子项的动画在上一个子项动画运行到一半时再开始
lac.setOrder(LayoutAnimationController.ORDER_RANDOM);//子项的展示顺序
LinearLayout linearLayout = findViewById(R.id.linearLayout);
linearLayout.setLayoutAnimation(lac);
LayoutAnimationController 不仅可以对布局设置动画,也可以对各种集合视图的子项展示、增删等添加动画,比如ListView、CardView等。