补间动画:Tween Animation
帧动画:Frame Animation
属性动画:Property Animation
1.补间动画和帧动画都是作用于View,所以两者又被称为View Animation,可以在View对象上执行一系列的简单变换,比如位置、尺寸、旋转、透明度等。注意:执行这两种动画时View的焦点是没有变的,如果你的View涉及到点击事件等等用该类动画就不合适。
2.属性动画功功能就比较强大了,而且执行动画时View的焦点也是实时变化的。比如监听手机的方向传感器来执行设置界面的旋转,这时候使用属性动画比较合适。还可以通过ValueAnimator控制执行的开始点和结束点,比如一个View关闭的效果。
public static ObjectAnimator ofFloat(Object target, String propertyName, float… values) {}
一般是调用静态函数ofFloat初始化一个ObjectAnimator,几个参数的含义
target:要执行动画的View
propertyName:要执行View的属性,该View必须有set和get方法才可设置
values:这是一个可变参数,可以传入几个值,开始值,中间值,结束值,注意:传入0表示View在初始位置
实例1:多个View同时执行一个旋转动画
//多个View同时执行一个旋转动画
private fun startRotationAnim(degree: Float) {
val animatorSet = AnimatorSet()
val animatorShotAbumImg = ObjectAnimator.ofFloat(shotAlbumImg, "rotation", degree)
val animatorShotAlbumCardView = ObjectAnimator.ofFloat(cardView, "rotation", degree)
val animatorShotMoreImg = ObjectAnimator.ofFloat(shotMoreImg, "rotation", degree)
val animatorShotSwitchCamera = ObjectAnimator.ofFloat(shotSwitchCamera, "rotation", degree)
val animatorCountDownTv = ObjectAnimator.ofFloat(countDownTv, "rotation", degree)
val animatorShotBeautyImg = ObjectAnimator.ofFloat(shotBeautyImg, "rotation", degree)
animatorSet.play(animatorShotAbumImg)
.with(animatorShotMoreImg)
.with(animatorShotSwitchCamera)
.with(animatorCountDownTv)
.with(animatorShotAlbumCardView)
.with(animatorShotBeautyImg)
animatorSet.duration = 300
animatorSet.start()
}
实例2:一个View如何同时执行旋转+平移动画
使用PropertyValuesHolder类
private fun startAnim(degree: Float) {
var videoScaleX: PropertyValuesHolder ?= null
var videoScaleY: PropertyValuesHolder ?=null
var videoRotation: PropertyValuesHolder ?= null
var scale :Float = 0f
val layoutParams = mRootView!!.surfaceView.layoutParams as FrameLayout.LayoutParams
scale = layoutParams.width / layoutParams.height.toFloat()
videoScaleX = PropertyValuesHolder.ofFloat("scaleX", scale)
videoScaleY = PropertyValuesHolder.ofFloat("scaleY", scale)
videoRotation = PropertyValuesHolder.ofFloat("rotation", degree)
val videoAnimation = ObjectAnimator.ofPropertyValuesHolder(mRootView!!.surfaceView, videoScaleX, videoScaleY, videoRotation)
val animatorSet = AnimatorSet()
animatorSet.play(videoAnimation)
animatorSet.duration = 300
animatorSet.start()
}
ObjectAnimator实现自定义动画只需要把propertyName定义成该View没有的属性,然后在onAnimationUpdate回调函数中处理相关的逻辑即可,动画可以是一个3秒或5秒的动画,也可以是一个常驻动画。
实例1:3秒自定义动画
mAnimator = ObjectAnimator
.ofFloat(fl_container, "liuxu", 1.0f, 0.0f)
mAnimator!!.duration = 3000
mAnimator!!.start()
CommonPreference.putBoolean(CommonPreference.IS_FIRST_FRAME, true)
mIsFirstFrame = true
mAnimator?.addUpdateListener(object : ValueAnimator.AnimatorUpdateListener {
override fun onAnimationUpdate(p0: ValueAnimator?) {
//do something what you want
//处理自己的动画逻辑
}
实例2:常驻动画
在1的基础上设置动画为无限循环动画
mCurrentSelectAnimator!!.repeatCount = ValueAnimator.INFINITE
注意:动画的停止方式
//停止无限循环动画的逻辑
if (mCurrentSelectAnimator != null) {
mCurrentSelectAnimator!!.repeatMode = ValueAnimator.RESTART
mCurrentSelectAnimator!!.end()
//这句是关键点,只将动画结束动画是不会停止的
fl_guild_current_select.clearAnimation()
mCurrentSelectAnimator = null
}
ValueAnimator本身并不能执行动画,他只是一个控制器,可以控制你设置的开始点到结束点按照时间一步一步过度执行.
//关闭动画
fun startCloseAnim() {
//设置动画的初始值和结束值
val va = ValueAnimator.ofInt(0, MoliveKit.getPixels(295 / 2f))
val layoutParams = login_collect.fl_login_top.layoutParams
val layoutParams1 = login_collect.fl_login_bottom.layoutParams
va.addUpdateListener { animation ->
//获取中间值
val h = animation?.animatedValue as Int
//给View重新设置高度达到动画的效果
layoutParams.height = h + login_collect.fl_login_top.height
login_collect.fl_login_top.layoutParams = layoutParams
login_collect.fl_login_top.requestLayout()
layoutParams1.height = h + login_collect.fl_login_bottom.height
login_collect.fl_login_bottom.layoutParams = layoutParams1
login_collect.fl_login_bottom.requestLayout()
}
va.addListener(object : AnimatorListenerAdapter() {
override fun onAnimationEnd(animation: Animator?) {
super.onAnimationEnd(animation)
mLogInListener?.onCollectEnd()
}
override fun onAnimationStart(animation: Animator?) {
super.onAnimationStart(animation)
}
})
va.duration = 1000
va.start()
}
调用代码
//这里是通过xml文件实现的,代码的话一样的道理
detailRecyclerView.layoutAnimation = AnimationUtils.loadLayoutAnimation(context, R.anim.anim_recyclerview_left)
detailRecyclerView.adapter.notifyDataSetChanged()
detailRecyclerView.scheduleLayoutAnimation()
anim_recyclerview_left文件
<layoutAnimation
xmlns:android="http://schemas.android.com/apk/res/android"
android:animation="@anim/item_beauty_detail_left"
android:animationOrder="normal"
android:interpolator="@android:anim/overshoot_interpolator"/>
item_beauty_detail_left文件
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="300">
<translate
android:interpolator="@android:anim/decelerate_interpolator"
android:fromXDelta="-100%p"
android:toXDelta="0" />
<alpha
android:fromAlpha="0"
android:toAlpha="1"
android:interpolator="@android:anim/accelerate_decelerate_interpolator" />
set>
不足之处请指正,希望大家共同学习,谢谢!
有什么更炫酷的动画,好的开源库大家都可以分享出来共同研究!