RecyclerView自定义动画:元素移动与添加的问题求助
RecyclerView自定义动画问题求助
问题详情
- 严重问题:某RecyclerView使用两种不同ViewHolder布局,执行
animateMove动画时,较矮元素无论上下移动都会出现定位错误,推测是measuredHeight取值异常,但无法确定具体原因。 - 次要问题:为实现元素渐现效果设置了基于位置的启动延迟,但重新添加元素时,列表上方元素无延迟直接显示,下方元素才按位置延迟启动动画。
自定义动画代码
import android.animation.Animator import android.animation.AnimatorListenerAdapter import android.util.Log import androidx.interpolator.view.animation.FastOutSlowInInterpolator import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.SimpleItemAnimator // A custom animator to animate the items in recycler view class RecyclerAnimator : SimpleItemAnimator() { // Never called override fun animateRemove(viewHolder: RecyclerView.ViewHolder): Boolean { viewHolder.itemView.animate() .alpha(0F) .setInterpolator(FastOutSlowInInterpolator()) .setStartDelay(200) .setDuration(300) .scaleY(0F) .setListener(object : AnimatorListenerAdapter() { override fun onAnimationEnd(animation: Animator) { super.onAnimationEnd(animation) dispatchRemoveFinished(viewHolder) } }) .start() Log.d("recycler_animation", "animate remove") return false } // Called when the items appear in the list (launch, fragment change, it was created) override fun animateAdd(viewHolder: RecyclerView.ViewHolder): Boolean { val height: Int = viewHolder.itemView.measuredHeight / 3 val view = viewHolder.itemView view.translationY = height.toFloat() view.alpha = 0F view.scaleY = 1F view.animate() .translationY(0F) .alpha(1F) .setInterpolator(FastOutSlowInInterpolator()) .setDuration(400) .setStartDelay(viewHolder.bindingAdapterPosition * 50L) .setListener(object : AnimatorListenerAdapter() { override fun onAnimationEnd(animation: Animator) { super.onAnimationEnd(animation) dispatchAddFinished(viewHolder) } }) .start() Log.d("recycler_animation", "animate add") return false } // Called when an item is being moved to another position in the adapter override fun animateMove( viewHolder: RecyclerView.ViewHolder, fromX: Int, fromY: Int, toX: Int, toY: Int ): Boolean { val item = viewHolder.itemView item.y = fromY.toFloat() val verticalMovement = if (toY > fromY) (toY - fromY).toFloat() - (item.measuredHeight) else (fromY - toY).toFloat() - (item.measuredHeight) item.animate() .translationY(verticalMovement) .setDuration(300) .setInterpolator(FastOutSlowInInterpolator()) .setStartDelay(200) .setListener(object : AnimatorListenerAdapter() { override fun onAnimationEnd(animation: Animator) { super.onAnimationEnd(animation) dispatchMoveFinished(viewHolder) } }) .start() Log.d("recycler_animation", "animate move") return false } // Called when an item changes its data override fun animateChange( oldHolder: RecyclerView.ViewHolder, newHolder: RecyclerView.ViewHolder, fromLeft: Int, fromTop: Int, toLeft: Int, toTop: Int ): Boolean { newHolder.itemView.alpha = 0F val oldAnimation = oldHolder.itemView.animate() .alpha(0F) .setInterpolator(FastOutSlowInInterpolator()) .setDuration(300) .setListener(object : AnimatorListenerAdapter() { override fun onAnimationEnd(animation: Animator) { super.onAnimationEnd(animation) dispatchChangeFinished(oldHolder, true) } }) val newAnimation = newHolder.itemView.animate() .alpha(1F) .setInterpolator(FastOutSlowInInterpolator()) .setDuration(300) .setListener(object : AnimatorListenerAdapter() { override fun onAnimationEnd(animation: Animator) { super.onAnimationEnd(animation) dispatchChangeFinished(newHolder, false) } }) oldAnimation.start() newAnimation.start() Log.d("recycler_animation", "animate change") return false } // Called when an item is deleted from the adapter override fun animateDisappearance( viewHolder: RecyclerView.ViewHolder, preLayoutInfo: ItemHolderInfo, postLayoutInfo: ItemHolderInfo? ): Boolean { viewHolder.itemView.animate() .alpha(0F) .setInterpolator(FastOutSlowInInterpolator()) .setDuration(400) .setStartDelay(100) .scaleY(0F) .setListener(object : AnimatorListenerAdapter() { override fun onAnimationEnd(animation: Animator) { super.onAnimationEnd(animation) dispatchRemoveFinished(viewHolder) viewHolder.itemView.alpha = 1F viewHolder.itemView.scaleY = 1F } }) .start() Log.d("recycler_animation", "animate disappearance") return false } override fun runPendingAnimations() { Log.d("recycler_animation", "pending animations") } override fun endAnimation(viewHolder: RecyclerView.ViewHolder) { Log.d("recycler_animation", "end animation") val item = viewHolder.itemView item.alpha = 1F item.translationY = 0F item.scaleY = 1F } override fun endAnimations() { Log.d("recycler_animation", "end animation no arg") } override fun isRunning(): Boolean { return false } }
问题演示

内容的提问来源于stack exchange,提问作者m.i.n.a.r.
相关产品推荐
相关产品推荐

