Использование ItemTouchHelper.Callback для создания левого меню в RecyclerView. - PullRequest
0 голосов
/ 20 сентября 2018

Я пытался реализовать «меню смахивания» для своих элементов в RecyclerView, используя «ItemTouchHelper.Callback».Сначала я пытаюсь остановить элемент в определенной позиции, а не сдвинуть его обратно в положение (X) 0.

Для этого решения я просто следовал руководству поСредний и он должен делать, как описано выше: https://codeburst.io/android-swipe-menu-with-recyclerview-8f28a235ff28

Код ниже не на 100% такой же, как в учебнике, так как я также хотел реализовать функцию перетаскивания элементов (которая работает).

Тем не менее, я пытался следовать учебному пособию шаг за шагом, но безуспешно.Я не могу найти других полезных руководств и т. Д. Для этой конкретной функции

Вот мой код для реализации ItemTouchHelper.Callback:

enum class ButtonsState {
    GONE,
    VISIBLE
}

class SwipeItemHelper : ItemTouchHelper.Callback  {

    private var mAdapter:           ItemTouchHelperAdapter

    private var swipeBack:          Boolean         = true
    private var buttonShowedState:  ButtonsState    = ButtonsState.GONE
    private val buttonsWidth:       Float           = 300f

    constructor(adapter: ItemTouchHelperAdapter) {
        mAdapter = adapter
    }

    override fun onChildDraw(c: Canvas, recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder, dX: Float, dY: Float, actionState: Int, isCurrentlyActive: Boolean) {
        if (actionState == ACTION_STATE_SWIPE) {
            setTouchListener(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive)
        }
        super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive)
    }

    private fun setTouchListener(c: Canvas, recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder, dX: Float, dY: Float, actionState: Int, isCurrentlyActive: Boolean) {
        recyclerView.setOnTouchListener { v, event ->
            swipeBack = event.action == MotionEvent.ACTION_CANCEL || event.action == MotionEvent.ACTION_UP
            if (swipeBack) {
                if (dX < -buttonsWidth)
                    buttonShowedState = ButtonsState.VISIBLE

                if (buttonShowedState !== ButtonsState.GONE) {
                    setTouchDownListener(c, recyclerView, viewHolder, -buttonsWidth, dY, actionState, isCurrentlyActive)
                    setItemsClickable(recyclerView, false)
                }
            }
            false
        }
    }

    // SwipeController.java
    private fun setTouchDownListener(c: Canvas,
                                     recyclerView: RecyclerView,
                                     viewHolder: RecyclerView.ViewHolder,
                                     dX: Float, dY: Float,
                                     actionState: Int, isCurrentlyActive: Boolean) {
        recyclerView.setOnTouchListener { v, event ->
            if (event.action == MotionEvent.ACTION_DOWN) {
                setTouchUpListener(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive)
            }
            false
        }
    }

    private fun setTouchUpListener(c: Canvas,
                                   recyclerView: RecyclerView,
                                   viewHolder: RecyclerView.ViewHolder,
                                   dX: Float, dY: Float,
                                   actionState: Int, isCurrentlyActive: Boolean) {
        recyclerView.setOnTouchListener { v, event ->
            if (event.action == MotionEvent.ACTION_UP) {
                SwipItemHelper@super.onChildDraw(c, recyclerView, viewHolder, 0f, dY, actionState, isCurrentlyActive)
                recyclerView.setOnTouchListener { v, event -> false }
                setItemsClickable(recyclerView, true)
                swipeBack = false
                buttonShowedState = ButtonsState.GONE
            }
            false
        }
    }

    private fun setItemsClickable(recyclerView: RecyclerView,
                                  isClickable: Boolean) {
        for (i in 0 until recyclerView.childCount) {
            recyclerView.getChildAt(i).isClickable = isClickable
        }
    }

    override fun convertToAbsoluteDirection(flags: Int, layoutDirection: Int): Int {
        if (swipeBack) {
            swipeBack = false
            return 0
        }
        return super.convertToAbsoluteDirection(flags, layoutDirection)
    }

    override fun getMovementFlags(recyclerView: RecyclerView?, viewHolder: RecyclerView.ViewHolder?): Int {
        val dragFlags   = ItemTouchHelper.UP or ItemTouchHelper.DOWN
        val swipeFlags  = ItemTouchHelper.START
        return makeMovementFlags(dragFlags, swipeFlags)
    }

    override fun onMove(recyclerView: RecyclerView?, viewHolder: RecyclerView.ViewHolder?, target: RecyclerView.ViewHolder?): Boolean {
        if (viewHolder == null || target == null)
            return false

        mAdapter.onItemMove(viewHolder.getAdapterPosition(), target.getAdapterPosition())
        return true
    }

    override fun isLongPressDragEnabled(): Boolean {
        return true
    }

    override fun onSwiped(viewHolder: RecyclerView.ViewHolder?, direction: Int) {

    }

}

1 Ответ

0 голосов
/ 27 июня 2019

Я также борюсь с той же проблемой, следуя тому же учебнику.

Вы можете ограничить свое движение таким образом в onChildDraw :

val newDX:Float = max(dX, -buttonWidth)
super.onChildDraw(c, recyclerView, viewHolder, newDX, dY, actionState, isCurrentlyActive)

Это установит newDX до значения buttonWidth , если вы переместились за пределы ширины кнопки, поэтому ваш элемент списка будет нарисован правильно.

...