如何使用 ItemTouchHelper 在回收视图的每一侧显示 2 个单独的按钮

如何解决如何使用 ItemTouchHelper 在回收视图的每一侧显示 2 个单独的按钮

所以我试图在我的回收站视图中制作一个可滑动的列表,如果我向右滑动,左侧会显示一个撤消按钮,如果我向左滑动,则右侧会显示一个删除按钮。我能够为左右滑动显示一个按钮。如果我先向左滑动,即使我向右滑动,删除按钮也会显示。当我向右滑动时也会发生同样的事情。我认为这与 draw 函数的工作方式有关,但我不确定出了什么问题。我想要做的是让左右滑动绘制2个相互独立的不同按钮

这是我在 kotlin 中的 itemtouchhelper

import android.annotation.SuppressLint
import android.content.Context
import android.graphics.*
import android.view.MotionEvent
import android.view.View
import androidx.annotation.ColorRes
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.itemtouchhelper
import androidx.recyclerview.widget.RecyclerView
import java.util.*
import kotlin.math.abs
import kotlin.math.max

abstract class SwipeHelper(
    private val recyclerView: RecyclerView
) : itemtouchhelper.SimpleCallback(
    itemtouchhelper.ACTION_STATE_IDLE,itemtouchhelper.LEFT or itemtouchhelper.RIGHT
) {
    private var swipedPosition = -1
    private val buttonsBuffer: MutableMap<Int,List<UnderlayButton>> = mutableMapOf()
    private val recoverQueue = object : LinkedList<Int>() {
        override fun add(element: Int): Boolean {
            if (contains(element)) return false
            return super.add(element)
        }
    }

    @SuppressLint("ClickableViewAccessibility")
    private val touchListener = View.OnTouchListener { _,event ->
        if (swipedPosition < 0) return@OnTouchListener false
        buttonsBuffer[swipedPosition]?.forEach { it.handle(event) }
        recoverQueue.add(swipedPosition)
        swipedPosition = -1
        recoverSwipedItem()
        true
    }

    init {
        recyclerView.setonTouchListener(touchListener)
    }

    private fun recoverSwipedItem() {
        while (!recoverQueue.isEmpty()) {
            val position = recoverQueue.poll() ?: return
            recyclerView.adapter?.notifyItemChanged(position)
        }
    }

    private fun drawButtons(
        canvas: Canvas,buttons: List<UnderlayButton>,itemView: View,dX: Float
    ) {
        var right = itemView.right
        buttons.forEach { button ->
            val width = button.intrinsicWidth / buttons.intrinsicWidth() * abs(dX)
            val left = right - width
            button.draw(
                canvas,RectF(left,itemView.top.toFloat(),right.toFloat(),itemView.bottom.toFloat())
            )

            right = left.toInt()
        }
    }

    private fun drawButtonsRight(
        canvas: Canvas,dX: Float
    ) {
        var left = itemView.left
        buttons.forEach { button ->
            val width = button.intrinsicWidth / buttons.intrinsicWidthRight() * abs(dX)
            val right = width
            button.draw(
                canvas,RectF(left.toFloat(),right,itemView.bottom.toFloat())
            )

            left = right.toInt()
        }
    }

    override fun onChildDraw(
        c: Canvas,recyclerView: RecyclerView,viewHolder: RecyclerView.ViewHolder,dX: Float,dY: Float,actionState: Int,isCurrentlyActive: Boolean
    ) {
        val position = viewHolder.adapterPosition
        var maxDX = dX
        val itemView = viewHolder.itemView

        if (actionState == itemtouchhelper.ACTION_STATE_SWIPE) {
            if (dX < 0) {
                if (!buttonsBuffer.containsKey(position)) {
                    buttonsBuffer[0] = instantiateUnderlayButton(position)
                }

                val buttons = buttonsBuffer[position] ?: return
                if (buttons.isEmpty()) return
                maxDX = max(-buttons.intrinsicWidth(),dX)
                drawButtons(c,buttons,itemView,maxDX)
            }
            if(dX > 0) {
                if (!buttonsBuffer.containsKey(position)) {
                    buttonsBuffer[1] = instantiateUnderlayButtonRight(position)
                }
                val buttons = buttonsBuffer[position] ?: return
                if (buttons.isEmpty()) return
                maxDX = buttons.intrinsicWidthRight()
                drawButtonsRight(c,maxDX)
            }
        }

        super.onChildDraw(
            c,recyclerView,viewHolder,maxDX,dY,actionState,isCurrentlyActive
        )
    }

    override fun onMove(
        recyclerView: RecyclerView,target: RecyclerView.ViewHolder
    ): Boolean {
        return false
    }

    override fun onSwiped(viewHolder: RecyclerView.ViewHolder,direction: Int) {
        val position = viewHolder.adapterPosition
        if (swipedPosition != position) recoverQueue.add(swipedPosition)
        swipedPosition = position
        recoverSwipedItem()
    }

    abstract fun instantiateUnderlayButton(position: Int): List<UnderlayButton>
    abstract fun instantiateUnderlayButtonRight(position: Int): List<UnderlayButton>

    //region UnderlayButton
    interface UnderlayButtonClickListener {
        fun onClick()
    }

    class UnderlayButton(
        private val context: Context,textSize: Float,private val bitmap: Bitmap,@ColorRes private val colorRes: Int,private val clickListener: UnderlayButtonClickListener
    ) {
        private var clickableRegion: RectF? = null
        private val textSizeInPixel: Float = textSize * context.resources.displayMetrics.density // dp to px
        private val horizontalPadding = 100.0f
        val intrinsicWidth: Float


        init {
            val titleBounds = Rect()
            intrinsicWidth = titleBounds.width() + 2 * horizontalPadding
        }


        fun draw(canvas: Canvas,rect: RectF) {
            val paint = Paint()

            // Draw background
            paint.color = ContextCompat.getColor(context,colorRes)
            canvas.drawRect(rect,paint)

            // Draw title
            paint.color = ContextCompat.getColor(context,android.R.color.white)
            paint.textSize = textSizeInPixel
            paint.typeface = Typeface.DEFAULT_BOLD
            paint.textAlign = Paint.Align.LEFT


            val spaceHeight = 10f // change to whatever you deem looks better

            val bounds = Rect()
            val combinedHeight = bitmap.height + spaceHeight + bounds.height()
            canvas.drawBitmap(
                bitmap,rect.centerX() - bitmap.width / 2,rect.centerY() - combinedHeight / 2,null
            )

            clickableRegion = rect
        }

        fun handle(event: MotionEvent) {
            clickableRegion?.let {
                if (it.contains(event.x,event.y)) {
                    clickListener.onClick()
                }
            }
        }
    }
    //endregion
}

private fun List<SwipeHelper.UnderlayButton>.intrinsicWidth(): Float {
    if (isEmpty()) return 0.0f
    return map { it.intrinsicWidth }.reduce { acc,fl -> acc + fl }
}


private fun List<SwipeHelper.UnderlayButton>.intrinsicWidthRight(): Float {
    if (isEmpty()) return 0.0f
    return map { it.intrinsicWidth }.reduce { acc,fl -> acc + fl }
}

我觉得我很接近但不确定我哪里出错了。任何帮助,将不胜感激 谢谢

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?