RecyclerView GridLayoutManager Dynami c spancount во время выполнения, изменение размера анимации - PullRequest
0 голосов
/ 07 мая 2020

Итак, моему клиенту нужен список из 3 столбцов, в каждом из которых может быть 1, 2 или 3 столбца. Итак, у меня есть GridLayoutManager.SpanSizeLookup.

object : GridLayoutManager.SpanSizeLookup() {
                override fun getSpanSize(position: Int): Int {
                    return when (viewModel.adapter.list[position]) {
                        is Type.One -> 1
                        is Type.Two -> 2
                        is Type.Three -> 3
                    }
                }
            }

Это хорошо работает. Но с моим аниматором предметов у меня есть сбой, который я не могу показать из-за конфиденциальности клиента.

class ItemAnimator(
    private val cellSize: Float
) : DefaultItemAnimator() {
    private var isRunningTmp: Boolean = false

    override fun animateChange(
        oldHolder: RecyclerView.ViewHolder?,
        newHolder: RecyclerView.ViewHolder?,
        fromLeft: Int,
        fromTop: Int,
        toLeft: Int,
        toTop: Int
    ): Boolean {
        if (oldHolder != null && newHolder != null) {
            val context: Context = newHolder.itemView.context
            val startWidth: Float =
                getSpanCount(oldHolder).times(cellSize).minus(context.dp2px(16f))
            val startHeight: Float = context.dp2px(if (oldHolder is ThreeViewHolder) 208f else 168f)
            val endWidth: Float = getSpanCount(newHolder).times(cellSize).minus(context.dp2px(16f))
            val endHeight: Float = context.dp2px(if (newHolder is ThreeViewHolder) 208f else 168f)
            val diffHeight: Float = endHeight.minus(startHeight)
            val diffWidth: Float = endWidth.minus(startWidth)

            val animator: ValueAnimator = ValueAnimator.ofFloat(0f, 100f)

            val paramsOld: GridLayoutManager.LayoutParams =
                oldHolder.itemView.layoutParams as GridLayoutManager.LayoutParams
            paramsOld.width = endWidth.roundToInt()
            paramsOld.height = endHeight.roundToInt()
            oldHolder.itemView.layoutParams = paramsOld

            when (newHolder) {
                is OneViewHolder -> newHolder.binding.viewModel?.isSelected?.set(true)
                is TwoViewHolder -> newHolder.binding.viewModel?.isSelected?.set(true)
                is ThreeViewHolder -> newHolder.binding.viewModel?.isSelected?.set(true)
            }

            oldHolder.itemView.visibility = View.GONE

            animator.addUpdateListener {
                val percent: Float = (it.animatedValue as Float).div(100)
                val tmpNew = newHolder.itemView.layoutParams

                tmpNew.height = startHeight.plus(percent.times(diffHeight)).roundToInt()
                tmpNew.width = startWidth.plus(percent.times(diffWidth)).roundToInt()

                newHolder.itemView.layoutParams = tmpNew
            }

            animator.duration = 300
            animator.addOnStartAnimation {
                isRunningTmp = true
                dispatchChangeStarting(oldHolder, true)
                dispatchChangeStarting(newHolder, false)
            }.addOnEndAnimation {
                isRunningTmp = false
                oldHolder.itemView.layoutParams = paramsOld
                oldHolder.itemView.visibility = View.VISIBLE
                newHolder.itemView.visibility = View.VISIBLE
                dispatchChangeFinished(oldHolder, true)
                dispatchChangeFinished(newHolder, false)
                dispatchAnimationsFinished()
            }

            animator.start()
            return true
        }

        return super.animateChange(oldHolder, newHolder, fromLeft, fromTop, toLeft, toTop)
    }

    override fun isRunning(): Boolean {
        return super.isRunning() && isRunningTmp
    }

    private fun getSpanCount(viewHolder: RecyclerView.ViewHolder): Int {
        return when (viewHolder) {
            is TwoViewHolder -> 2
            is ThreeViewHolder -> 3
            else -> 1
        }
    }
}

Есть некоторые скачки, особенно когда я изменяю высоту. Не знаю, правильно ли я использую ItemAnimator.

...