简介
补间动画根据动画效果可以分为四种:平移translate,旋转rotate,缩放scale,透明度alpha。我们可以在xml文件配置(存放路径在res/anim下)或者直接在代码动态配置使用,动画作用于派生自View的控件,不可作用于控件的属性。除了单一的动画效果,我们也可以选择其中几种动画效果组合形成动画集合,接下来让我们具体看下相关使用方法。
因为这几种动画都是继承自Animation,所以在具体使用之前,我们先来了解下Animation的一些属性及其含义:
- interpolator 设置插值器
- fillEnabled 设置是否应用fillBefore的值,默认为true
- fillBefore 设置动画结束时,控件是否恢复开始时状态,默认为true
- fillAfter 设置动画结束时,控件是否保持结束时状态,默认为false,不受fillEnabled影响,优先级比fillBefore高
- duration 设置一次动画的持续时间,单位是毫秒,必须设置
- startOffset 设置动画延时启动时间,单位是毫秒
- repeatCount 设置动画重复次数,设置infinite时为无限循环,默认为0
- repeatMode 设置动画重复模式,搭配repeatCount使用,restart(正序)/reverse(倒序回放) ,默认为restart
- zAdjustment 设置动画的内容运行时在Z轴上的位置,normal(保持当前Z轴的位置)/top(置于其他之上)/bottom(置于其他之下),默认为normal
平移动画 TranslateAnimation
TranslateAnimation独有的属性:
- fromXDelta 起始点X轴坐标,有三种取值方式:具体数值、x%、x%p。设置为具体数值时表示起始点在X轴移动多少数值;设置为x%时表示起始点在X轴移动自己宽度的x%;设置为x%p时,这个p表示取值的基于父控件,即表示起始点在X轴移动父控件宽度的x%。
- toXDelta 终点X轴坐标 取值方式参考fromXDelta
- fromYDelta 起始点Y轴坐标 取值方式参考fromXDelta
- toYDelta 终点Y轴坐标 取值方式参考fromXDelta
XML代码实现,利用translate标签:
//见效果图1中 restart 无限重复 相对于自身宽度
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="2000"
android:fillAfter="true"
android:fillBefore="true"
android:fromXDelta="0"
android:fromYDelta="0"
android:toXDelta="20%"
android:repeatCount="infinite"
android:toYDelta="300">
</translate>
//见效果图1中 reverse 无限重复 相对于父控件宽度
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="2000"
android:fillAfter="true"
android:fillBefore="true"
android:fillEnabled="true"
android:fromXDelta="0"
android:fromYDelta="0"
android:repeatCount="infinite"
android:repeatMode="reverse"
android:toXDelta="20%p"
android:toYDelta="300"
android:zAdjustment="normal">
</translate>
使用
final Animation translateAnimation = AnimationUtils.loadAnimation(MainActivity.this, R.anim.translate_anim);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
tv.startAnimation(translateAnimation);
}
});
java代码动态设置:
三种取值方式在代码中动态创建对应的就是Animation中的Animation.ABSOLUTE(具体数值),Animation.RELATIVE_TO_SELF(相对于自身),Animation.RELATIVE_TO_PARENT(相对于父控件),看名字定义的就很好理解之前xml所说的了。TranslateAnimation 的构造函数有3个,通常使用后面2个,其中4个参数的取值方式默认为Animation.ABSOLUTE,8个参数的就可以灵活指定取值方式。附上相关源码:
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;
}
public TranslateAnimation(int fromXType, float fromXValue, int toXType, float toXValue,
int fromYType, float fromYValue, int toYType, float toYValue) {
mFromXValue = fromXValue;
mToXValue = toXValue;
mFromYValue = fromYValue;
mToYValue = toYValue;
mFromXType = fromXType;
mToXType = toXType;
mFromYType = fromYType;
mToYType = toYType;
}
具体使用
//对应xml效果1
TranslateAnimation translateAnim = new TranslateAnimation(Animation.ABSOLUTE, 0, Animation.RELATIVE_TO_SELF, 0.2f,
Animation.ABSOLUTE, 0, Animation.ABSOLUTE, 300);
translateAnim.setRepeatCount(Animation.INFINITE);
translateAnim.setDuration(2000);
tv.startAnimation(translateAnim);
//对应xml效果2
TranslateAnimation translateAnim2 = new TranslateAnimation(Animation.ABSOLUTE, 0, Animation.RELATIVE_TO_PARENT, 0.2f,
Animation.ABSOLUTE, 0, Animation.ABSOLUTE, 300);
translateAnim2.setRepeatCount(Animation.INFINITE);
translateAnim2.setRepeatMode(Animation.REVERSE);
translateAnim2.setDuration(2000);
tv2.startAnimation(translateAnim2);
效果图1–TranslateAnimation
旋转动画 RotateAnimation
RotateAnimation独有的属性:
- fromDegrees 设置动画开始时旋转的角度 顺时针正值 逆时针为负值
- toDegrees 设置动画结束时旋转的角度 顺时针正值 逆时针为负值
- pivotX 旋转轴点X轴坐标点 取值方式参考上面TranslateAnimation 中 fromXDelta属性介绍 默认为0
- pivotY 旋转轴点Y轴坐标点 同上 默认为0 即旋转轴点默认为控件左上角
XML代码实现,利用rotate标签:
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="2000"
android:fillAfter="true"
android:fillBefore="true"
android:fromDegrees="90"
android:pivotX="50%p"
android:pivotY="100"
android:repeatCount="infinite"
android:repeatMode="reverse"
android:toDegrees="-180">
</rotate>
Animation rotateAnim = AnimationUtils.loadAnimation(MainActivity.this, R.anim.rotate_anim);
tv3.startAnimation(rotateAnim);
java代码实现:
RotateAnimation rotateAnimation = new RotateAnimation(90, -180, Animation.RELATIVE_TO_PARENT, 0.5f
, Animation.ABSOLUTE, 100);
rotateAnimation.setRepeatCount(Animation.INFINITE);
rotateAnimation.setRepeatMode(Animation.REVERSE);
rotateAnimation.setDuration(2000);
tv3.startAnimation(rotateAnimation);
效果图2–RotateAnimation
RotateAnimation 的构造函数就不介绍了,参考TranslateAnimation 使用。现在我们就这个效果来做个分析:
首先轴点的确定:我们设置的属性是X 50%p,Y 100,就是从控件的左上角这个点开始,X轴移动父控件宽度的50%,Y轴移动100;动画的起始旋转角度是90,所以我们顺时针旋转90就是我们的动画起始点,同理动画结束点,是旋转-180,我们逆时针旋转180就确定结束点,我们确定起始结束点都是基于控件的原始位置的。
缩放动画 ScaleAnimation
ScaleAnimation独有的属性:
- fromXScale 设置动画开始时控件在X轴方向相对于自身的缩放倍数。0就是缩小到没有,1.0无变化,0-1缩小,大于1放大
- toXScale 设置动画结束控件在X轴方向相对于自身的缩放倍数。具体缩放可参考fromXScale介绍
- fromYScale 设置动画开始时控件在Y轴方向相对于自身的缩放倍数。参考fromXScale介绍
- toYScale 设置动画结束控件在Y轴方向相对于自身的缩放倍数。参考fromXScale介绍
- pivotX 缩放起点X轴坐标。取值方式参考上面TranslateAnimation 中 fromXDelta属性介绍 默认为0
- pivotY 缩放起点Y轴坐标。取值方式参考上面TranslateAnimation 中 fromXDelta属性介绍 默认为0, 即控件左上角,这与RotateAnimation 的pivotX、pivotY属性含义有所不同,缩放动画的这个点是动画缩放的轴点,RotateAnimation 的是旋转的轴点。
XML代码实现,利用scale标签:
<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="2000"
android:fromXScale="1"
android:fromYScale="0.4"
android:pivotX="50"
android:pivotY="30"
android:repeatCount="infinite"
android:repeatMode="reverse"
android:toXScale="1.5"
android:toYScale="2">
</scale>
Animation scaleAnim = AnimationUtils.loadAnimation(MainActivity.this, R.anim.scale_anim);
tv4.startAnimation(scaleAnim);
java代码实现:
//具体使用参考TranslateAnimation
ScaleAnimation scaleAnimation = new ScaleAnimation(1.0f, 1.5f, 0.4f, 2.0f, Animation.ABSOLUTE, 50, Animation.ABSOLUTE, 30);
scaleAnimation.setRepeatCount(Animation.INFINITE);
scaleAnimation.setRepeatMode(Animation.REVERSE);
scaleAnimation.setDuration(2000);
tv4.startAnimation(scaleAnimation);
效果图3–ScaleAnimation
当我们把缩小倍数设为负数时,效果会是怎样的呢,我们来实际操作下,我们把X轴方向初始缩放倍数设为-1,Y轴方向初始缩放倍数设为-2:
ScaleAnimation scaleAnimation = new ScaleAnimation(-1.0f, 1f, -2f, 1f, Animation.ABSOLUTE, 0, Animation.ABSOLUTE, 0);
scaleAnimation.setRepeatCount(Animation.INFINITE);
scaleAnimation.setRepeatMode(Animation.REVERSE);
scaleAnimation.setDuration(5000);
tv4.startAnimation(scaleAnimation);
更多好玩的效果可以自己动手试一试。
透明度动画 AlphaAnimation
AlphaAnimation独有的属性:
- fromAlpha 设置动画开始时透明度,默认1。 0为全透明 1为不透明
- toAlpha 设置动画结束时透明度,默认1。 0为全透明 1为不透明
XML代码实现,利用alpha标签:
<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="5000"
android:fromAlpha="1"
android:repeatCount="infinite"
android:repeatMode="reverse"
android:toAlpha="0">
</alpha>
Animation alphaAnim = AnimationUtils.loadAnimation(MainActivity.this, R.anim.alpha_anim);
tv5.startAnimation(alphaAnim);
java代码实现:
AlphaAnimation alphaAnimation = new AlphaAnimation(1.0f, 0.2f);
alphaAnimation.setRepeatCount(Animation.INFINITE);
alphaAnimation.setRepeatMode(Animation.REVERSE);
alphaAnimation.setDuration(5000);
tv5.startAnimation(alphaAnimation);
效果图4–AlphaAnimation
动画集合 AnimationSet
相对于前面四个动画而言,它们只能完成特定单一的功能,而AnimationSet可以把它们组合起来,完成一个动画。AnimationSet继承自Animation,所以也具有公共属性。
- shareInterpolator 设置子动画是否和组合共享同一个插值器 AnimationSet的独有属性
XML代码实现,利用set标签:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="2000"
android:fromXDelta="0"
android:fromYDelta="0"
android:repeatCount="infinite"
android:repeatMode="reverse"
android:toXDelta="50%"
android:toYDelta="0"/>
<rotate
android:duration="1000"
android:fromDegrees="0"
android:pivotX="50%"
android:pivotY="50%"
android:repeatCount="infinite"
android:repeatMode="reverse"
android:startOffset="2000"
android:toDegrees="360"/>
<alpha
android:duration="3000"
android:fromAlpha="1.0"
android:repeatCount="infinite"
android:repeatMode="reverse"
android:startOffset="1000"
android:toAlpha="0.2"/>
<scale
android:duration="2000"
android:fromXScale="1.5"
android:fromYScale="1.5"
android:repeatCount="infinite"
android:repeatMode="reverse"
android:pivotX="50%"
android:pivotY="50%"
android:toXScale="1.0"
android:toYScale="1.0"
/>
</set>
Animation setAnim = AnimationUtils.loadAnimation(MainActivity.this, R.anim.set_anim);
tv6.startAnimation(setAnim);
java代码实现:
AnimationSet animationSet = new AnimationSet(true);
TranslateAnimation translateAnimation = new TranslateAnimation(Animation.ABSOLUTE, 0, Animation.RELATIVE_TO_SELF, 0.5f,
Animation.ABSOLUTE, 0, Animation.ABSOLUTE, 0);
translateAnimation.setRepeatCount(Animation.INFINITE);
translateAnimation.setRepeatMode(Animation.REVERSE);
translateAnimation.setDuration(2000);
RotateAnimation rotateAnimation = new RotateAnimation(0, 360, Animation.RELATIVE_TO_SELF, 0.5f
, Animation.RELATIVE_TO_SELF, 0.5f);
rotateAnimation.setRepeatCount(Animation.INFINITE);
rotateAnimation.setRepeatMode(Animation.REVERSE);
rotateAnimation.setDuration(1000);
rotateAnimation.setStartOffset(2000);
AlphaAnimation alphaAnimation = new AlphaAnimation(1.0f, 0.2f);
alphaAnimation.setRepeatCount(Animation.INFINITE);
alphaAnimation.setRepeatMode(Animation.REVERSE);
alphaAnimation.setDuration(3000);
ScaleAnimation scaleAnimation = new ScaleAnimation(1.5f, 1.0f, 1.5f, 1.0f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
scaleAnimation.setRepeatCount(Animation.INFINITE);
scaleAnimation.setRepeatMode(Animation.REVERSE);
scaleAnimation.setDuration(2000);
animationSet.addAnimation(translateAnimation);
animationSet.addAnimation(rotateAnimation);
animationSet.addAnimation(alphaAnimation);
animationSet.addAnimation(scaleAnimation);
tv6.startAnimation(animationSet);
效果图5–AnimationSet
注意:
- 动画集合中的动画默认是同时开始的,要想实现不同动画不同时间开始,需要给子动画设置延迟开始时间android:startOffset
- 当AnimationSet设置公共属性(继承自Animation的属性)会覆盖单个动画设置的属性,但是repeatCount属性除外,这个必须对单个动画设置才有效。
动画监听
最后就是动画执行的状态,我们可以利用Animation的AnimationListener 来监听动画执行的状态
translateAnimation.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
//动画开始触发
}
@Override
public void onAnimationEnd(Animation animation) {
//动画结束触发
}
@Override
public void onAnimationRepeat(Animation animation) {
//动画重复执行触发
}
});
关于补间动画的使用我们暂时就了解到这了,感兴趣的可以自行再去深入了解,当然最重要的还是自己动手操作一番,这样也有助于加深印象,谢谢观看。