补间动画又叫View动画。Android中的补间动画分四种,渐变、缩放、平移,旋转。还有个set是他们的组合,
在XML文件中的标签对应是 <alpha>,<scale>,<translate>,<rotate>
对应的四个类是AlphaAnimation,ScaleAnimation,TranslateAnimation,RotateAnimation
四个类。
这四个类都继承Animation类,Animation是个抽象类。
Java类 | XML标签 | 效果 |
AlphaAnimation |
| 让透明度渐变, |
ScaleAnimation |
| 放大或缩小 |
TranslateAnimation |
| 移动位置 |
RotateAnimation |
| 绕某一点旋转 |
使用
View动画是作用在View上的。使用有两种方式,以一个简单的旋转动画为例:
- 在res中新建anim文件夹,在这个文件夹里写上xml动画文件。如res/anim/anim_test.xml.
- 在java文件中用这个xml文件生成Animation类。
- 调用View的startAnimation来启动动画。
xml文件:
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromDegrees="0"
android:toDegrees="180"
android:duration="2000"
android:pivotX="50%"
android:pivotY="50%"
/>
java activity:
btnRun = (Button) findViewById(R.id.btn_run);
ivIc = (ImageView) findViewById(R.id.iv_ic);
final Animation animation = AnimationUtils.loadAnimation(this,R.anim.anim_test);
btnRun.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
ivIc.startAnimation(animation);
}
});
!
- 直接在Java文件中new一个Animation的子类,然后调用View的startAnimation来启动动画。
final RotateAnimation animation = new RotateAnimation(0,180,50,50);
animation.setDuration(2000);
btnRun.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
ivIc.startAnimation(animation);
}
});
应该能发现这两个动画并不一样。因为在xml文件中`pivotX="50% pivotY="50%""
指的是在要动画的view的高宽的50%为动画中心,也就是View的正中心。这里是旋转,就是旋转中心了。 而在Java中设置的两个50,意思是从这个View的左上角向右偏移50像素,向下偏移50像素为动画中心。
一般推荐用XML来写View动画,有以下好处:
- xml文件以配置的形式,让动画看起来更直观,可读性强。
- 一个动画文件可以被多个View使用,重用性强。
- 便于更换动画。更换一个View的动画只要更换load的xml文件就行,不需要修改其他代码。
既然xml以配置的形式来定义动画,那么只要弄明白这些属性的意义就能灵活实现自己需要的动画了。
Animation的属性
这四个子类独有的属性并不多,大部分都是继承自父类Animation的。所以先看看Animation的属性。
Animation的属性 | 含义 |
android:detachWallpaper | 针对Window的动画属性。当一个window在桌面上动画时,是否让桌面壁纸跟着动画。默认是false |
android:duration | 动画执行的时间 |
android:fillAfter | 如果为true,那么动画执行完就会定格在执行完的那个画面,也就是动画的最后一帧,不会恢复到原位。比如上面的旋转转完就回去了。 |
android:fillBefore | 只有当android:fillEnabled设为true时,这个值才有效。否则就假定这个值为true |
android:fillEnabled | 是否考虑android:fillBefore的值。只要为true时,android:fillBefore的值才会被考虑。 不过这个属性跟上个属性我咋设置都没啥用,渣渣呀!谁能给个能出效果的例子。。。 |
android:interpolator | 设置插值器,来控制动画在不同时间段的速度。默认是加速减速插值器。 |
android:repeatCount | 动画重复的次数,所以总共会运行的动画次数是这个重复次数+1; |
android:repeatMode | 动画重复的方式,有两个值,reverse 和 restart。reverse表示动画会正反轮流执行;restart |
android:startOffset | 动画延迟执行的时间,单位是毫秒 |
android:zAdjustment | 可以取三个值,normal:0,top:1,bottom:-1。代表可以在动画过程中调整z轴的顺序,也就是显示层次。0表示维持当前层次,1表示放在其他内容上面,-1表示放在其他内容下面。但是我渣还是没实现过这个属性,怎么搞都没用呀? |
android:repeatMode
- reverse
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="2000"
android:fromDegrees="0"
android:pivotX="50%"
android:pivotY="50%"
android:repeatCount="2"
android:repeatMode="reverse"
android:toDegrees="360" />
- restart
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="2000"
android:fromDegrees="0"
android:pivotX="50%"
android:pivotY="50%"
android:repeatCount="2"
android:repeatMode="restart"
android:toDegrees="360" />
AlphaAnimation的独有属性
AlphaAnimation的独有属性 | 含义 |
android:fromAlpha | 动画开始时的透明度 从0.0-1.0 0.0表示完全透明,1.0表示完全不透明 |
android:toAlpha | 动画结束时的透明度 |
5秒从全透变成完全不透 从0-1;
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="5000">
<alpha
android:fromAlpha="0"
android:toAlpha="1"
/>
</set>
ScaleAnimation独有属性
ScaleAnimation独有属性 | 含义 |
android:pivotX | float,缩放起点,或缩放原点的X轴坐标。缩放围绕这个点运行。 这个坐标默认是View的左上角,(0,0) |
android:pivotY | float,同上 Y轴坐标. 在XML中的值有三种写法:数值:50;百分数:50%;百分数p:50%p。如果是数值,表示以View的左上角为(0,0),然后加上写的数值,以这个点作为缩放中心。如果为百分数,如50%,表示总左上角(0,0)加上自身高度的50%,作为缩放点。如果是百分数p,如50%p,表示总左上角(0,0)加上父控件高度的50%,作为缩放点。 |
android:fromXScale | float 动画开始时,X轴上缩放的比例。1表示本身大小。 |
android:fromYScale | float 动画开始时,Y轴上缩放的比例。1表示本身大小。 |
android:toXScale | float Y动画结束时,X轴上缩放的比例。1表示本身大小。 |
android:toYScale | float Y动画结束时,Y轴上缩放的比例。1表示本身大小。 |
从图片的右下角开始缩放,宽高各从从原来的2倍缩放到原来的十分之一:
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="3000">
<scale
android:pivotX="100%"
android:pivotY="100%"
android:fromXScale="2"
android:fromYScale="2"
android:toXScale="0.1"
android:toYScale="0.1"
/>
</set>
TranslateAnimation独有属性
TranslateAnimation独有属性 | 含义 |
android:fromXDelta | 动画开始时View左上角的X坐标,也有三种写法,同pivotX |
android:fromYDelta | 动画开始时View左上角的Y坐标,也有三种写法,同pivotX |
android:toXDelta | 动画结束时View左上角的X坐标,也有三种写法,同pivotX |
android:toYDelta | 动画结束时View左上角的Y坐标,也有三种写法,同pivotXY |
从自身的左上角移到自身的右下角:
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="3000">
<translate
android:fromXDelta="-100%"
android:fromYDelta="-100%"
android:toXDelta="100%"
android:toYDelta="100%"
/>
</set>
RotateAnimation独有属性
RotateAnimation独有属性 | 含义 |
android:pivotX | 旋转动画的中心的X坐标,旋转围绕这个点进行,也有三种写法,同pivotX |
android:pivotY | 旋转动画的中心的Y坐标,旋转围绕这个点进行,也有三种写法,同pivotX |
android:fromDegrees | 动画开始时的旋转角度。角度顺时针转增加,逆时针转减少。所以根据开始角度和结束角度来判断是顺时针还是逆时针。360度为一圈。 |
android:toDegrees | 动画结束时的旋转角度。 |
从360度转到-90度:
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="3000">
<rotate
android:pivotX="50%"
android:pivotY="50%"
android:fromDegrees="360"
android:toDegrees="-90"
/>
</set>
AnimationSet
AnimationSet代表动画的集合,在XML文件中的标签是<set>
,前面已经出现过了。
影这个标签可以把不同的动画组合起来作用在同一个View上。
使用AndroidStudio时发现只有在<set>
标签里面,才能自动提示出来Animation的属性,在<alpha>
等标签里只提示他自己独有的那几个属性,不知道有没有解决办法。
例如要同时缩放旋转,并改变透明度:
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="3000">
<rotate
android:pivotX="50%"
android:pivotY="50%"
android:fromDegrees="360"
android:toDegrees="-90"
/>
<alpha
android:fromAlpha="1"
android:toAlpha="0.2"/>
</set>
还能用同一种动画拼成一个连续动画,只是这样做好像有点low:
<set xmlns:android="http://schemas.android.com/apk/res/android"
>
<translate
android:fromXDelta="0"
android:fromYDelta="0"
android:toYDelta="-100%"
android:toXDelta="-100%"
android:duration="2000" />
<translate
android:fromXDelta="0"
android:fromYDelta="0"
android:toXDelta="200%"
android:duration="2000"
android:startOffset="2000"/>
<translate
android:fromXDelta="0"
android:fromYDelta="0"
android:toYDelta="200%"
android:duration="2000"
android:startOffset="4000"/>
<translate
android:fromXDelta="0"
android:fromYDelta="0"
android:toXDelta="-200%"
android:duration="2000"
android:startOffset="6000"/>
<translate
android:fromXDelta="0"
android:fromYDelta="0"
android:toXDelta="100%"
android:toYDelta="-100%"
android:duration="2000"
android:startOffset="8000"/>
</set>
android:shareInterpolator
AnimationSet也有个属性android:shareInterpolator
.值为true或flase。表示集合中的动画是佛共享同一个插值器。
插值器Interpolator
Interpolator继承自TimeInterpolator,用来定义动画在不同的时间有不同的速度。也叫插补器。
插值器可以通过在xml文件中用android:interpolator
设置,也可以在java中通过animation.setInterpolator()
来设置.
在java中设置可以传一些参数,对插值器进行更详细的设置,比较灵活。
插值器 | XML中的值 | 作用 |
AccelerateDecelerateInterpolator | @android:anim/accelerate_decelerate_interpolator | 加速减速插值器 动画先加速再减速 |
AccelerateInterpolator | @android:anim/accelerate_interpolator | 加速插值器 动画速度越来越快 |
DecelerateInterpolator | @android:anim/decelerate_interpolator | 减速插值器 动画速度越来越慢 |
BounceInterpolator | @android:anim/bounce_interpolator | 回弹插值器 动画结束会回弹几下 |
CycleInterpolator | @android:anim/cycle_interpolator | 圆插值器,动画会重复几次,动画的速度沿着正弦曲线变化 |
LinearInterpolator | @android:anim/linear_interpolator | 线性插值器 动画速度保持匀速 |
AnticipateOvershootInterpolator | @android:anim/anticipate_overshoot_interpolator | 预期预期超调插值器。先往前甩一定的值,然后开始动画,结束时往后甩一定的值,结束动画。 |
AnticipateInterpolator | @android:anim/anticipate_interpolator | 预期插值器,动画开始时会往前甩一下 |
OvershootInterpolator | @android:anim/overshoot_interpolator | 超调插值器 动画结束时往后甩一下 |
下面以让一个图片顺时针旋转360度为例,其他动画都类似的作用:
AccelerateDecelerateInterpolator
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="3000"
android:interpolator="@android:anim/accelerate_decelerate_interpolator">
<rotate
android:fromDegrees="0"
android:toDegrees="360"
android:pivotX="50%"
android:pivotY="50%"/>
</set>
AccelerateInterpolator
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="3000"
android:interpolator="@android:anim/accelerate_interpolator">
<rotate
android:fromDegrees="0"
android:toDegrees="360"
android:pivotX="50%"
android:pivotY="50%"/>
</set>
DecelerateInterpolator
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="3000"
android:interpolator="@android:anim/decelerate_interpolator">
<rotate
android:fromDegrees="0"
android:toDegrees="360"
android:pivotX="50%"
android:pivotY="50%"/>
</set>
BounceInterpolator
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="3000"
android:interpolator="@android:anim/bounce_interpolator">
<rotate
android:fromDegrees="0"
android:toDegrees="360"
android:pivotX="50%"
android:pivotY="50%"/>
</set>
CycleInterpolator
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="3000"
android:interpolator="@android:anim/cycle_interpolator">
<rotate
android:fromDegrees="0"
android:toDegrees="360"
android:pivotX="50%"
android:pivotY="50%"/>
</set>
LinearInterpolator
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="3000"
android:interpolator="@android:anim/linear_interpolator">
<rotate
android:fromDegrees="0"
android:toDegrees="360"
android:pivotX="50%"
android:pivotY="50%"/>
</set>
AnticipateOvershootInterpolator
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="3000"
android:interpolator="@android:anim/anticipate_overshoot_interpolator">
<rotate
android:fromDegrees="0"
android:toDegrees="360"
android:pivotX="50%"
android:pivotY="50%"/>
</set>
AnticipateInterpolator
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="3000"
android:interpolator="@android:anim/anticipate_interpolator">
<rotate
android:fromDegrees="0"
android:toDegrees="360"
android:pivotX="50%"
android:pivotY="50%"/>
</set>
OvershootInterpolator
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="3000"
android:interpolator="@android:anim/overshoot_interpolator">
<rotate
android:fromDegrees="0"
android:toDegrees="360"
android:pivotX="50%"
android:pivotY="50%"/>
</set>
对View动画的监听
Animation里有一个AnimationListener类提供了对动画开始,重复,和结束的监听。
animation.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
Log.i(TAG, "动画开始时做操作: ");
}
@Override
public void onAnimationEnd(Animation animation) {
Log.i(TAG, "动画重复时做操作: ");
}
@Override
public void onAnimationRepeat(Animation animation) {
Log.i(TAG, "动画结束时做操作: ");
}
});