序言
- 动画是Android开发中经常使用的知识,好的动画会使你的APP看起来非常吸引人
- 本文将详细向大家解释补间动画的原理和使用方法
1.作用对象
- 可以作用于各种View组件如TextView,Button,ImageView等
- 但是不可作用于View组件的属性,如:颜色、背景、长度等等
2.原理
- 通过确定开始的视图样式 & 结束的视图样式、中间动画变化过程由系统补全来确定一个动画
- 即补间动画的动画效果就是:平移、缩放、旋转、透明度动画
3.分类
根据不同的动画效果,补间动画分为4种动画:
- 平移动画(Translate)
- 缩放动画(scale)
- 旋转动画(rotate)
- 透明度动画(alpha)
同时,不同类型的动画对应于不同的子类,具体如下图:
各子类源码如下:
- 平移动画
gezilei
/**
* Constructor to use when building a TranslateAnimation from code
*
* @param fromXDelta Change in X coordinate to apply at the start of the
* animation
* @param toXDelta Change in X coordinate to apply at the end of the
* animation
* @param fromYDelta Change in Y coordinate to apply at the start of the
* animation
* @param toYDelta Change in Y coordinate to apply at the end of the
* animation
*/
public TranslateAnimation(float fromXDelta, float toXDelta, float fromYDelta, float toYDelta) {
mFromXValue = fromXDelta;
mToXValue = toXDelta;
mFromYValue = fromYDelta;
mToYValue = toYDelta;
mFromXType = ABSOLUTE;
mToXType = ABSOLUTE;
mFromYType = ABSOLUTE;
mToYType = ABSOLUTE;
}
- 缩放动画
/**
* Constructor to use when building a ScaleAnimation from code
*
* @param fromX Horizontal scaling factor to apply at the start of the
* animation
* @param toX Horizontal scaling factor to apply at the end of the animation
* @param fromY Vertical scaling factor to apply at the start of the
* animation
* @param toY Vertical scaling factor to apply at the end of the animation
* @param pivotXType Specifies how pivotXValue should be interpreted. One of
* Animation.ABSOLUTE, Animation.RELATIVE_TO_SELF, or
* Animation.RELATIVE_TO_PARENT.
* @param pivotXValue The X coordinate of the point about which the object
* is being scaled, specified as an absolute number where 0 is the
* left edge. (This point remains fixed while the object changes
* size.) This value can either be an absolute number if pivotXType
* is ABSOLUTE, or a percentage (where 1.0 is 100%) otherwise.
* @param pivotYType Specifies how pivotYValue should be interpreted. One of
* Animation.ABSOLUTE, Animation.RELATIVE_TO_SELF, or
* Animation.RELATIVE_TO_PARENT.
* @param pivotYValue The Y coordinate of the point about which the object
* is being scaled, specified as an absolute number where 0 is the
* top edge. (This point remains fixed while the object changes
* size.) This value can either be an absolute number if pivotYType
* is ABSOLUTE, or a percentage (where 1.0 is 100%) otherwise.
*/
public ScaleAnimation(float fromX, float toX, float fromY, float toY,
int pivotXType, float pivotXValue, int pivotYType, float pivotYValue) {
mResources = null;
mFromX = fromX;
mToX = toX;
mFromY = fromY;
mToY = toY;
mPivotXValue = pivotXValue;
mPivotXType = pivotXType;
mPivotYValue = pivotYValue;
mPivotYType = pivotYType;
initializePivotPoint();
}
- 旋转动画
/**
* Constructor to use when building a RotateAnimation from code
*
* @param fromDegrees Rotation offset to apply at the start of the
* animation.
*
* @param toDegrees Rotation offset to apply at the end of the animation.
*
* @param pivotXType Specifies how pivotXValue should be interpreted. One of
* Animation.ABSOLUTE, Animation.RELATIVE_TO_SELF, or
* Animation.RELATIVE_TO_PARENT.
* @param pivotXValue The X coordinate of the point about which the object
* is being rotated, specified as an absolute number where 0 is the
* left edge. This value can either be an absolute number if
* pivotXType is ABSOLUTE, or a percentage (where 1.0 is 100%)
* otherwise.
* @param pivotYType Specifies how pivotYValue should be interpreted. One of
* Animation.ABSOLUTE, Animation.RELATIVE_TO_SELF, or
* Animation.RELATIVE_TO_PARENT.
* @param pivotYValue The Y coordinate of the point about which the object
* is being rotated, specified as an absolute number where 0 is the
* top edge. This value can either be an absolute number if
* pivotYType is ABSOLUTE, or a percentage (where 1.0 is 100%)
* otherwise.
*/
public RotateAnimation(float fromDegrees, float toDegrees, int pivotXType, float pivotXValue,
int pivotYType, float pivotYValue) {
mFromDegrees = fromDegrees;
mToDegrees = toDegrees;
mPivotXValue = pivotXValue;
mPivotXType = pivotXType;
mPivotYValue = pivotYValue;
mPivotYType = pivotYType;
initializePivotPoint();
}
- 透明度动画
/**
* Constructor to use when building an AlphaAnimation from code
*
* @param fromAlpha Starting alpha value for the animation, where 1.0 means
* fully opaque and 0.0 means fully transparent.
* @param toAlpha Ending alpha value for the animation.
*/
public AlphaAnimation(float fromAlpha, float toAlpha) {
mFromAlpha = fromAlpha;
mToAlpha = toAlpha;
}
4.具体使用
- 首先这里还有一个android坐标位置的概念:
坐标都是左上角为原点,然后进行坐标变化
- 补间动画的使用方式分为两种:在XML 代码 / Java 代码里设置(若使用XML代码:在 res/anim的文件夹里创建动画效果.xml文件)
前者优点:动画描述的可读性更好
后者优点:动画效果可动态创建
- 其次要记住这4种动画的公共属性
// 以下参数是4种动画效果的公共属性,即都有的属性
android:duration="3000" // 动画持续时间(ms),必须设置,动画才有效果
android:startOffset ="1000" // 动画延迟开始时间(ms)
android:fillBefore = “true” // 动画播放完后,视图是否会停留在动画开始的状态,默认为true
android:fillAfter = “false” // 动画播放完后,视图是否会停留在动画结束的状态,优先于fillBefore值,默认为false
android:fillEnabled= “true” // 是否应用fillBefore值,对fillAfter值无影响,默认为true
android:repeatMode= “restart” // 选择重复播放动画模式,restart代表正序重放,reverse代表倒序回放,默认为restart|
android:repeatCount = “0” // 重放次数(所以动画的播放次数=重放次数+1),为infinite时无限重复
android:interpolator = @[package:]anim/interpolator_resource // 插值器,即影响动画的播放速度
4.1 平移动画(Translate)
设置方法1:在XML代码设置
- 创建translate.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<!--平移动画的x,y起始位置-->
<translate
android:fromXDelta="0"
android:toXDelta="500"
android:fromYDelta="0"
android:toYDelta="500"
/>
</set>
以下参数是平移动画特有的属性:
- android:fromXDelta="" // 视图在水平方向x 移动的起始值
- android:toXDelta="" // 视图在水平方向x 移动的结束值
- android:fromYDelta="" // 视图在竖直方向y 移动的起始值
- android:toYDelta="" // 视图在竖直方向y 移动的结束值
- 在Java代码中创建Animation对象并播放动画
Animation animation = AnimationUtils.loadAnimation(this, R.anim.translate);
animation.setDuration(5000);//若xml文件为设置该属性,则不会有动画
button.startAnimation(animation);
设置方法2:在 Java 代码中设置
/**
* 使用JAVA代码控制动画
* **/
Animation animation = new TranslateAnimation(0, screen_x, 0, screen_y);
animation.setDuration(3000);//动画持续时间
animation.setFillEnabled(true);//使其可以填充效果从而不回到原地
animation.setFillAfter(true);//不回到起始位置
//如果不添加setFillEnabled和setFillAfter则动画执行结束后会自动回到远点
button.startAnimation(animation);
获取屏幕宽高,可以更好的控制距离
DisplayMetrics metric = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metric);
int screen_x = metric.widthPixels; // 屏幕宽度(像素)
int screen_y = metric.heightPixels; // 屏幕高度(像素)
4.2 缩放动画(Scale)
设置方法1:在XML代码设置
- 创建scale.xmls
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<scale
android:fromXScale="1"
android:fromYScale="1"
android:pivotX="50%"
android:pivotY="50%"
android:toXScale="2"
android:toYScale="2" />
</set>
以下参数是缩放动画特有的属性:
-
android:fromXScale:动画开始时X轴方向控件大小,取值和android:pivot一样;三种取值类型:数字;百分比;百分比+”p”;
-
android:fromYScale:动画开始时Y轴方向控件大小,取值类型同上
动画在水平方向X的起始缩放倍数
0.0表示起始大小收缩到没有
1.0表示起始大小正常无伸缩
值小于1.0表示起始大小收缩倍数
值大于1.0表示起始大小放大倍数 -
android:toXScale:动画在X轴方向上控件的目标大小,取值类型同上
-
android:toYScale:动画在Y轴方向上控件的目标大小,取值类型同上
-
android:pivotX:缩放中心坐标的X值,取值类型有三种:数字;百分比;百分比+”p”;
数字:例如50.0,这里的单位是px像素**
百分比:例如50%,这里是相对于自己控件宽度的百分比,实际的值是mIvImg.getWidth()50%;
百分比+”p”:例如50%p,这里是表示相对于自己控件的父控件的百分比, -
android:pivotY:同上
下面详细讲解一下各属性的取值问题:
- 缩放的中心点位置(缩放的开始位置也就是轴点):android:pivotX/android:pivotY 取值类型有三种:数字;百分比;百分比+”p”;
- 数字:例如50.0,这里的单位是px像素
- 百分比:例如50%,这里是相对于自己空间宽度的百分比,实际的值是mIvImg.getWidth()*50%或者mIvImg.getHeight()*50%;
- 百分比+”p”:例如50%p,这里是表示相对于自己控件的父控件的百分比,
按比例缩放示意图
设置为数字时(如50),轴点为View的左上角的原点在x方向和y方向加上50px的点。。
设置为百分比时(如50%),轴点为View的左上角的原点在x方向加上自身宽度50%和y方向自身高度50%的点。
设置为百分比p时(如50%p),轴点为View的左上角的原点在x方向加上父控件宽度50%和y方向父控件高度50%的点。这个很重要一个问题:它的父控件是那个,就是包裹这个空间的外一层控件,LinearLayout、RelativeLayout或者FrameLayout……
- 缩放的大小比例:android:fromXScale/android:fromYScale/android:toXScale/android:toYScale 取值类型有三种:数字;百分比;百分比+”p”;也就是放大倍数
- 在Java代码中创建Animation对象并播放动画
Animation animation1 = AnimationUtils.loadAnimation(this, R.anim.scale);
animation1.setDuration(3000);
animation1.setFillAfter(true);
animation1.setFillEnabled(true);
imageView.startAnimation(animation1);
设置方法2:在 Java 代码中设置
/**
* 使用JAVA代码控制动画
* **/
Animation animation1 = new ScaleAnimation(0, 2, 0, 2, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
// 参数说明:
// 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方向同理)
animation1.setDuration(3000);
animation1.setRepeatCount(-1);//播放次数,-1循环播放
imageView.startAnimation(animation1);
4.3 旋转动画(Rotate)
设置方法1:在XML代码设置
- 创建rotate.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<rotate
android:fromDegrees="0"
android:toDegrees="270"
android:pivotX="50%"
android:pivotY="50%"
/>
</set>
以下参数是平移动画特有的属性:
- android:pivotX:缩放中心坐标的X值
- android:pivotY:同上
- android:fromDegrees :// 动画开始时 视图的旋转角度(正数 = 顺时针,负数 = 逆时针)
- android:toDegrees:// 动画结束时 视图的旋转角度(正数 = 顺时针,负数 = 逆时针)
- 在Java代码中创建Animation对象并播放动画
Animation animation2=AnimationUtils.loadAnimation(this,R.anim.rotate);
animation2.setDuration(3000);
button1.startAnimation(animation2);
设置方法2:在 Java 代码中设置
Animation animation2 = new RotateAnimation(0, 270, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
// 参数说明:
// 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方向同理)
animation2.setDuration(3000);
button1.startAnimation(animation2);
4.4 透明度动画(Alpha)
设置方法1:在XML代码设置
- 创建alpha.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<alpha
android:fromAlpha="1.0"
android:toAlpha="0.0"
/>
</set>
以下参数是平移动画特有的属性:
- android:fromAlpha: // 动画开始时视图的透明度(取值范围: -1 ~ 1)
- android:toAlpha:// 动画结束时视图的透明度(取值范围: -1 ~ 1)
- 在Java代码中创建Animation对象并播放动画
Animation animation3=AnimationUtils.loadAnimation(this,R.anim.alpha);
animation3.setDuration(3000);
button2.startAnimation(animation3);
设置方法2:在 Java 代码中设置
/**
* 使用JAVA代码控制动画
* **/
Animation animation3 = new AlphaAnimation(1, 0);
// 参数说明:
// 1. fromAlpha:动画开始时视图的透明度(取值范围: -1 ~ 1)
// 2. toAlpha:动画结束时视图的透明度(取值范围: -1 ~ 1)
animation3.setDuration(3000);
button2.startAnimation(animation3);
4.5 组合动画
- 上面讲的都是单个动画效果;而实际中很多需求都需要同时使用平移、缩放、旋转 & 透明度4种动画,即组合动画
- 使用组合动画需要用到标签 < Set/>
Set 对于 Animation,就类似 View 对于 ViewGroup
设置方法1:在XML代码设置
- 创建combination.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<rotate
android:duration="2000"
android:fromDegrees="0"
android:pivotX="50%"
android:pivotY="50%"
android:repeatCount="infinite"
android:toDegrees="360" />
<translate
android:duration="7000"
android:fromXDelta="0"
android:repeatCount="infinite"
android:toXDelta="100%p" />
<alpha
android:duration="7000"
android:fromAlpha="1"
android:repeatCount="infinite"
android:toAlpha="0" />
<scale
android:duration="1000"
android:fromXScale="1"
android:fromYScale="1"
android:pivotX="50%"
android:pivotY="50%"
android:repeatCount="infinite"
android:startOffset="3500"
android:toXScale="2"
android:toYScale="2" />
</set>
- 在Java代码中创建Animation对象并播放动画
Animation animation3=AnimationUtils.loadAnimation(this,R.anim.alpha);
animation3.setDuration(3000);
button2.startAnimation(animation3);
设置方法2:在 Java 代码中设置
与以上的方法类似
5.监听动画
- Animation类通过监听动画开始 / 结束 / 重复时刻来进行一系列操作,如跳转页面等等 通过在 Java
- 代码里setAnimationListener()方法设置
Animation.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
// 动画开始时回调
}
@Override
public void onAnimationEnd(Animation animation) {
// 动画结束时回调
}
@Override
public void onAnimationRepeat(Animation animation) {
//动画重复执行的时候回调
}
});
特别注意
若采取上述方法监听动画,每次监听都必须重写4个方法。
背景:有些时候我们并不需要监听动画的所有时刻
问题:但上述方式是必须需要重写4个时刻的方法,这显示太累赘
解决方案:采用动画适配器AnimatorListenerAdapter,解决
实现接口繁琐 的问题
具体如下:
anim.addListener(new AnimatorListenerAdapter() {
// 向addListener()方法中传入适配器对象AnimatorListenerAdapter()
// 由于AnimatorListenerAdapter中已经实现好每个接口
// 所以这里不实现全部方法也不会报错
@Override
public void onAnimationStart(Animator animation) {
// 如想只想监听动画开始时刻,就只需要单独重写该方法就可以
}
});