Android的动画可以分为三种:View动画、帧动画和属性动画。
- View动画包括:平移、旋转、缩放、透明度。不会改变控件坐标参数
- 帧动画:图片切换动画。不会改变控件坐标参数
- 属性动画:通过动态改变控件的属性(改变控件部分坐标参数)达到动画效果。
一 View动画的创建步骤和方式
TranslateAnimation,RotateAnimation,ScaleAnimation,AlphaAnimation。这四种动画既可以通过XML来定义,也可以通过代码来动态创建。他们的集成关系如下:
通过xml去创建动画的步骤:
1.在res文件夹下创建anim文件夹
2.在anim文件夹下去创建动画xml文件
3.通过AnimationUtils类的静态方法loadAnimation获取动画对象
4.通过View.startAnimation()方法开启动画;
通过代码去创建动画的步骤(这里不写具体的步骤):
1.创建TranslateAnimation、RotateAnimation、ScaleAnimation或AlphaAnimation对象;
2.设置创建的动画对象的属性,如动画执行时间、延迟时间、起始位置、结束位置等;
3.通过View.startAnimation()方法开启动画;
二 TranslateAnimation动画
创建一个动画xml文件
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="500"
android:fromXDelta="0"
android:fromYDelta="0"
android:toXDelta="300"
android:toYDelta="300" />复制代码
解释一下属性:
这里的坐标系是以控件自身的左上角为坐标原点,右下为正方向的坐标系
android:fromXDelta:动画开始时候X方向的坐标
android:fromYDelta:动画开始时候Y方向的坐标
android:toXDelta:动画结束时候X方向的坐标
android:toYDelta:动画结束时候Y方向的坐标
它们的值不仅可以指定像素,而且还可以指定百分比,且坐标系的原点不会改变!
相对于自身可以指定像这样:
android:toXDelta="100%"复制代码
相对于父控件可以指定像这样
android:toXDelta="100%p"复制代码
android:duration:一个动画周期持续时间,单位是ms
android:fillAfter :设置为true,动画结束时,将保持动画最后时的状态
android:fillBefore :设置为true,动画结束时,还原到开始动画前的状态,默认值
android:repeatCount :重复次数,想让永远设置成-1
android:repeatMode :重复类型,有reverse和restart两个值,reverse表示倒序回放,restart表示重新放一遍,必须与repeatCount一起使用才能看到效果。因为这里的意义是重复的类型,即回放时的动作。默认不写是restart效果
android:startOffset:动画延迟执行的时间,单位是ms
android:interpolator:动画插值器,改变动画播放速率
插值器的值有:
@android:anim/accelerate_interpolator:加速变化(开始慢,越来越快)
@android:anim/decelerate_interpolator:减速变化(开始快,越来越慢)
@android:anim/accelerate_decelerate_interpolator:先加速后减速(中间速度最快)
@android:anim/linear_interpolator:线性均匀变化
@android:anim/overshoot_interpolator:超出结尾的临界值,然后在缓慢回到结束值
@android:anim/anticipate_interpolator:先向相反的方向改变一点,然后加速变化
@android:anim/anitcipate_overshoot_interpolator:先向相反的方向改变一点,然后在加速播放至超出结束值一点,然后在缓慢回到结束值
@android:anim/bounce_interpolator:动画快结束的时候,模拟球落地的回弹效果
@android:anim/cycle_interpolator:反方向在做一次动画效果
代码加载xml去开启动画代码:
//加载xml动画
val translate1 = AnimationUtils.loadAnimation(this, R.anim.translate1)
//给控件设置动画并开启
btn.startAnimation(translate1)复制代码
三RotateAnimation动画
创建一个动画xml文件
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="500"
android:fromDegrees="0"
android:toDegrees="-300"
android:pivotX="50%"
android:pivotY="50%">
</rotate>复制代码
解释一下属性:
这里的夹角是和Y轴的夹角,顺时针为正,逆时针为负,坐标系还是当前控件的左上角为原点
android:fromDegrees:开始动画的角度
android:toDegrees:结束时候的角度
android:pivotY,android:pivotX:旋转的中心点坐标,不写是控件的左上角原点为中心点
其余的属性和平移动画一样,不再重复
四 ScaleAnimation动画
创建一个动画xml文件
<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="500"
android:fromXScale="0.0"
android:fromYScale="0.0"
android:pivotX="50%"
android:pivotY="50%"
android:toXScale="1.5"
android:toYScale="1.5">
</scale>复制代码
解释一下属性:
坐标系还是当前控件的左上角为原点
android:fromYScale,android:fromXScale:开始缩放比例
android:toXScale, android:toYScale:结束缩放比例
android:toYScale,android:pivotY:缩放中心点
其余的属性和平移动画一样,不再重复
五AlphaAnimation动画
<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="500"
android:fromAlpha="1.0"
android:toAlpha="0.0">
</alpha>复制代码
解释一下属性:
android:fromAlpha:动画开始时候透明度
android:fromAlpha:动画结束时候透明度
其余的属性和平移动画一样,不再重复
六组合到一起
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="10000">
<translate
android:fromXDelta="0"
android:fromYDelta="0"
android:toXDelta="0"
android:toYDelta="300" />
<rotate
android:fromDegrees="0"
android:pivotX="50%"
android:pivotY="50%"
android:toDegrees="300" />
<scale
android:fromXScale="0"
android:fromYScale="0"
android:pivotX="50%"
android:pivotY="50%"
android:toXScale="1"
android:toYScale="1" />
<alpha
android:fromAlpha="0"
android:toAlpha="1" />
</set>复制代码
这里有两个细节需要注意:
- 如果我们给set设置了共有的属性,那么它包裹的动画再次设置这个属性也不会生效,都会以跟属性为准。
- 但是插值器可以单独设置,需要配合android:shareInterpolator一起设置,表示集合中的动画是否和集合共享同一个插值器。
- 如果不想让组合动画同时执行,我们可以通过设置动画的延迟时间去改变不去同时执行,它并没有像属性动画那样给我们提供设置执行先后顺序的方法。
七View动画的监听
val loadAnimation = AnimationUtils.loadAnimation(this, R.anim.enter)
loadAnimation.setAnimationListener(object : Animation.AnimationListener {
//动画完全结束时候调用
override fun onAnimationEnd(animation: Animation?) {
}
//动画开始时候调用
override fun onAnimationStart(animation: Animation?) {
}
//动画重复时候调用
override fun onAnimationRepeat(animation: Animation?) {
}
})复制代码
八帧动画
帧动画是顺序播放一组预先定义好的图片,类似于电影播放。帧动画创建的文件在drawable文件夹下。需要用到的类是AnimationDrawable。它的继承关系如下:
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="false">
<item android:drawable="@drawable/d_beishang" android:duration="500" />
<item android:drawable="@drawable/d_bishi" android:duration="500" />
<item android:drawable="@drawable/d_bizui" android:duration="500" />
<item android:drawable="@drawable/d_chanzui" android:duration="500" />
</animation-list>复制代码
//把定义的帧动画设置给控件
btn.setBackgroundResource(R.drawable.donghua);
//获取控件中的帧动画
var anim = btn.background as AnimationDrawable
//开启帧动画
anim.start()复制代码
解释: android:oneshot属性表示是否重复动画,
注意:帧动画的使用比较简单,但是比较容易引起OOM。
九view动画常见应用场景
8.1 5.0版本之前Activity切换动画
主要用到 overridePendingTransition(int enterAnim,int exitAnim)这个方法,这个方法必须在 startActivity(Intent)或者finish()之后被调用才能生效。这里自定义的view动画设置到里边就能替换原生系统的切换动画。
延伸:5.0版本之后google对于切换界面动画提供了新的方式:
8.2给ViewGroup的子控件加进场动画
这种效果需要用到layoutAnimation类,步骤如下:
1.创建res/anim下view动画
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:fromXDelta="0"
android:toXDelta="0"
android:fromYDelta="100%"
android:toYDelta="0"
android:duration="2000" />
<alpha
android:fromAlpha="0"
android:toAlpha="1"
android:duration="2000" />
</set>复制代码
2.在res/anim下创建layoutAnimation
<?xml version="1.0" encoding="utf-8"?>
<layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"
android:delay="0.5"
android:animationOrder="normal"
android:animation="@anim/anim_layout">
</layoutAnimation>复制代码
解释属性:
android:delay:可以取值为数值,百分数,或百分数p。表示两个子控件执行出场动画的间隔时间,为0时,所有控件的动画没有延迟全部开始执行;为1时表示等上一个控件动画执行完毕才开始执行下一个
android:animationOrder:有三个值::normal表示按正常顺序出现。random表示乱序出现。reverse表示反序出现。
android:animation:指定出现时要执行的view动画
3.给viewGroup设置layoutAnimation的值
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layoutAnimation="@anim/layout_viewgrop"
android:orientation="vertical">
<Button
android:id="@+id/btn"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
...
</LinearLayout>复制代码
同时可以用代码设置子view的动画:
//加载组定义的view动画
val loadAnimation = AnimationUtils.loadAnimation(this, R.anim.anim_layout)
//创建动画控制器
val Controller = LayoutAnimationController(loadAnimation)
//设置每个子view动画间隔
Controller.delay=0.5F
//设置动画播放顺序
Controller.order = LayoutAnimationController.ORDER_NORMAL
//把动画设置给父控件
viewGroup.layoutAnimation = Controller复制代码