0

I am using android recyclerView, now on the swipe of item in recycler view I want to show two views, one for delete and one for mute, Now on click of view, the views(delete/mute) should go back and content should be in previous form, at a time only one row must be swiped

The swipeHelperClass I used is as

abstract class SwipeHelper(
    var context: Context,
    private val recyclerView: RecyclerView
) : ItemTouchHelper.SimpleCallback(
    ItemTouchHelper.ACTION_STATE_IDLE,
    ItemTouchHelper.LEFT
) {

    var ct = context
    private var swipedPosition = -1
    private var previousSwipedPosition = -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)
        }
    }


    override fun getSwipeThreshold(viewHolder: ViewHolder): Float {
        return mSwipeThreshold
    }

    override fun getSwipeEscapeVelocity(defaultValue: Float): Float {
        return 0.1f * defaultValue
    }

    override fun getSwipeVelocityThreshold(defaultValue: Float): Float {
        return 5.0f * defaultValue
    }

    @SuppressLint("ClickableViewAccessibility")
    private val touchListener = View.OnTouchListener { _, event ->
        if (swipedPosition < 0) return@OnTouchListener false

        buttonsBuffer[swipedPosition]?.forEach { it.handle(event) }
        recoverQueue.add(swipedPosition)
        Log.d("swipePos", "$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()
        }
    }

    fun hideViews() {
        if (swipedPosition != -1) {
            val viewHolder = recyclerView.findViewHolderForAdapterPosition(swipedPosition)
            viewHolder?.itemView?.animate()?.translationX(0f)?.start()
            swipedPosition = -1
            clearView(recyclerView, viewHolder!!)
        }
    }


    private lateinit var mCanvas: Canvas
    private lateinit var swipedViewHolder: ViewHolder
    private lateinit var buttons: List<UnderlayButton>

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

        if (actionState == ItemTouchHelper.ACTION_STATE_SWIPE) {
            if (dX < 0) {
                buttons = instantiateUnderlayButton(position)
                buttonsBuffer[position] = buttons
                val buttons = buttonsBuffer[position] ?: return
                if (buttons.isEmpty()) return
                maxDX = max(-buttons.intrinsicWidth(), dX)
                drawButtons(c, buttons, itemView, maxDX)


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


    }


    override fun onSelectedChanged(viewHolder: ViewHolder?, actionState: Int) {
        super.onSelectedChanged(viewHolder, actionState)
        Log.d(TAG, "onSelectedChanged: ")
        if (actionState != ItemTouchHelper.ACTION_STATE_IDLE && viewHolder != null) {
            viewHolder.itemView.setBackgroundColor(
                ContextCompat.getColor(
                    context,
                    R.color.bckgRecyclerViewColor
                )
            )
        }
    }

    override fun clearView(
        @NonNull recyclerView: RecyclerView,
        @NonNull viewHolder: ViewHolder
    ) {    //called when you dropped the item
        Log.d(TAG, "clearView: ")
        super.clearView(recyclerView, viewHolder)
        viewHolder.itemView.setBackgroundColor(ContextCompat.getColor(context, R.color.white))
    }

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


    private val TAG = "SwipeHelper"

    override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
        val position = viewHolder.absoluteAdapterPosition
        Log.d(TAG, "onSwiped => position : $position prevPosition : $previousSwipedPosition")
        previousSwipedPosition = position
        if (swipedPosition != position)
            recoverQueue.add(swipedPosition)
        swipedPosition = position
        recoverSwipedItem()
        swipedViewHolder = viewHolder
        mSwipeThreshold = 0.5F * buttons.size * 60
    }



    private var mSwipeThreshold: Float = 0F

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

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


    class UnderlayButton(
        private val context: Context,
        @ColorRes private val colorRes: Int,
        private val icon: Int,
        private val clickListener: UnderlayButtonClickListener
    ) {
        private var clickableRegion: RectF? = null
   private val horizontalPadding = 84.0f
        val intrinsicWidth: Float

        init {
            val paint = Paint()
            paint.typeface = Typeface.DEFAULT_BOLD
            paint.textAlign = Paint.Align.LEFT
            val titleBounds = Rect()
            intrinsicWidth = titleBounds.width() + 2 * horizontalPadding
        }

        fun draw(canvas: Canvas, rect: RectF) {
            val paint = Paint()
            paint.color = ContextCompat.getColor(context, colorRes)
            canvas.drawRect(rect, paint)
            paint.color = ContextCompat.getColor(context, android.R.color.white)
            paint.typeface = Typeface.DEFAULT_BOLD
            paint.textAlign = Paint.Align.LEFT
            val background_dest =
                RectF(rect.left + 30, rect.top + 30, rect.right - 30, rect.bottom - 30)
            canvas.drawBitmap(getBitmapMarker(context, icon), null, background_dest, paint)
            clickableRegion = background_dest
        }

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

fun getBitmapMarker(ct: Context, icon: Int): Bitmap {
    val customMarkerView: View =
        (ct.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater?)!!.inflate(
            icon,
            null
        )

    customMarkerView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED)
    customMarkerView.layout(
        0,
        0,
        customMarkerView.measuredWidth,
        customMarkerView.measuredHeight
    )
    customMarkerView.buildDrawingCache()
    val returnedBitmap = Bitmap.createBitmap(
        customMarkerView.measuredWidth, customMarkerView.measuredHeight,
        Bitmap.Config.ARGB_8888
    )
    val canvas = Canvas(returnedBitmap)
    canvas.drawColor(Color.WHITE, PorterDuff.Mode.SRC_IN)
    val drawable = customMarkerView.background
    drawable?.draw(canvas)
    customMarkerView.draw(canvas)
    return returnedBitmap
}

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

ItemTouchHelper(object : SwipeHelper(requireContext(), vb.rvPriority) { override fun instantiateUnderlayButton(position: Int): List { val deleteButton = deleteButton(position) val muteUnmuteButton = muteUnmute(position, this) return listOf(deleteButton, muteUnmuteButton) } }).attachToRecyclerView(vb.rvPriority)

**function muteUnmute is as **
  private fun muteUnmute(
        position: Int, swipeHelper: SwipeHelper
    ): SwipeHelper.UnderlayButton {
        val id =
            if (recentUserList[position].chat_muted) R.layout.unmute_button else R.layout.mute_button

        return SwipeHelper.UnderlayButton(
            requireContext(),
            R.color.black,
            id,
            object : SwipeHelper.UnderlayButtonClickListener {
                override fun onClick() {

                    userAdapter.getItemAt(position)?.let { item ->

                        if (item.blue_ring || item.red_ring) {
                            "You can't mute this chat because you have active order present with this user.".showToast(
                                requireContext()
                            )
                        } else {
                            // mute chat
                            if (userAdapter.getItemAt(position)?.chat_muted == false) {
                                userAdapter.getItemAt(position)?.chat_muted = true
                                chatHelper.muteChat(userAdapter.getItemAt(position)?.id ?: "")
                                userAdapter.notifyItemChanged(position)
                            } else { // unmute chat
                                userAdapter.getItemAt(position)?.chat_muted = false
                                chatHelper.unmuteChat(userAdapter.getItemAt(position)?.id ?: "")
                                userAdapter.notifyItemChanged(position)
                            }
                            swipeHelper.hideViews()
                            vb.rvPriority.smoothScrollToPosition(position)
                        }
                    }
                }
            })
    }
**onClick on muteUnmute recyclerView go back to its original view, but I am unable to achieve one item swiped at a time**  [![enter image description here](https://i.stack.imgur.com/b3tVi.png)](https://i.stack.imgur.com/b3tVi.png)

0 Answers0