效果图:

分析:
gif中可看到存在2个动画,一个箭头的反转,一个二级列表的伸缩。箭头的反转比较好实现。伸缩动画刚开始尝试过平移动画,效果很僵硬不太理想。后面想到用属性动画,动态修改布局高度,达到了想要的效果。
实现步骤:
1.箭头的反转
private fun startRotate() {
animation = if (View.VISIBLE == hideView.visibility) {
RotateAnimation(180f, 0f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f)
} else {
RotateAnimation(0f, 180f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f)
}
animation?.duration = 60
animation?.interpolator = LinearInterpolator()
animation?.repeatMode = Animation.REVERSE
animation?.fillAfter = true//此行重点,动画结束的时候停留在最后一帧
arrow.startAnimation(animation)
}
2、列表的伸缩
private fun expand(v: View) {
v.visibility = View.VISIBLE
val animator = createTelescopicAnim(v, 0, mHeight)
animator.start()
}
private fun shrink(view: View) {
val origHeight = view.height
val animator = createTelescopicAnim(view, origHeight, 0)
animator.addListener(object : AnimatorListenerAdapter() {
override fun onAnimationEnd(animation: Animator) {
view.visibility = View.GONE
}
})
animator.start()
}
private fun createTelescopicAnim(v: View, start: Int, end: Int): ValueAnimator {
val animator = ValueAnimator.ofInt(start, end)
animator.addUpdateListener { arg0 ->
val value = arg0.animatedValue as Int
val layoutParams = v.layoutParams
layoutParams.height = value
v.layoutParams = layoutParams
}
return animator
}
完整代码:
核心类ExpandabelAnimUtil
import android.animation.Animator
import android.animation.AnimatorListenerAdapter
import android.animation.ValueAnimator
import android.content.Context
import android.view.View
import android.view.animation.Animation
import android.view.animation.LinearInterpolator
import android.view.animation.RotateAnimation
class ExpandableAnimUtil private constructor(
context: Context, private val hideView: View, private val arrow: View
, height: Int
) {
private val mHeight: Int
private var animation: RotateAnimation? = null
companion object {
fun newInstance(context: Context, hideView: View, down: View, height: Int): ExpandableAnimUtil {
return ExpandableAnimUtil(context, hideView, down, height)
}
}
init {
val mDensity = context.resources.displayMetrics.density
mHeight = (mDensity * height).toInt()//dp2px
}
fun toggle() {
startRotate()
if (View.VISIBLE == hideView.visibility) {
shrink(hideView)
} else {
expand(hideView)
}
}
private fun startRotate() {
animation = if (View.VISIBLE == hideView.visibility) {
RotateAnimation(180f, 0f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f)
} else {
RotateAnimation(0f, 180f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f)
}
animation?.duration = 30
animation?.interpolator = LinearInterpolator()
animation?.repeatMode = Animation.REVERSE
animation?.fillAfter = true
arrow.startAnimation(animation)
}
private fun expand(v: View) {
v.visibility = View.VISIBLE
val animator = createTelescopicAnim(v, 0, mHeight)
animator.start()
}
private fun shrink(view: View) {
val origHeight = view.height
val animator = createTelescopicAnim(view, origHeight, 0)
animator.addListener(object : AnimatorListenerAdapter() {
override fun onAnimationEnd(animation: Animator) {
view.visibility = View.GONE
}
})
animator.start()
}
private fun createTelescopicAnim(v: View, start: Int, end: Int): ValueAnimator {
val animator = ValueAnimator.ofInt(start, end)
animator.addUpdateListener { arg0 ->
val value = arg0.animatedValue as Int
val layoutParams = v.layoutParams
layoutParams.height = value
v.layoutParams = layoutParams
}
return animator
}
}
Adapter,这里直接使用BRVAH,非常便捷
class ExpandableAdapter(list: ArrayList<String>) :
BaseItemDraggableAdapter<String, BaseViewHolder>(R.layout.item_expandable, list) {
override fun convert(helper: BaseViewHolder?, item: String?) {
helper?.getView<View>(R.id.ctl_outer)?.setOnClickListener {
ARouter.getInstance().build(RouterUri.WALLET_DETAIL_ACTIVITY).navigation()
}
helper?.getView<View>(R.id.ll_inner)?.setOnClickListener {
ARouter.getInstance().build(RouterUri.SEND_RECORD_ACTIVITY).navigation()
}
helper?.getView<View>(R.id.iv_more)?.setOnClickListener {
val animView = helper.getView<View>(R.id.ll_inner)
val ivMore = helper.getView<View>(R.id.iv_more)
ExpandableAnimUtil.newInstance(mContext, animView, ivMore, 200).toggle()
}
}
}
这个在项目中直接使用的,以后抽时间整理个demo再贡献完整源码吧。
网友评论