如何解决如何使用 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 举报,一经查实,本站将立刻删除。