Android ScrollView внутри RecyclerView.ViewHolder: не позволяет ItemTouchHelper получить сенсорное событие? - PullRequest
0 голосов
/ 09 января 2020

Настройка: у меня есть RecyclerView с vertical LinearLayoutManager. Каждый ViewHolder имеет 2 TextViews (зеленый и красный на картинке), что может быть очень длинным. RED можно прокручивать горизонтально благодаря HorizontalScrollView. GREEN можно прокручивать вертикально благодаря ScrollView.

Теперь я реализовал ItemTouchHelper, чтобы провести ВЛЕВО, ВВЕРХ или ВНИЗ. Проблема в том, что мой ScrollViews больше не работает. Вместо этого, даже когда я провожу GREEN ВВЕРХ или ВНИЗ, мой ViewHolder движется. Как мне запретить моему ItemTouchHelper получать событие касания?

Я пробовал:

- android:descendantFocusability="blocksDescendants"

- NestedScrollView вместо ScrollView

-исполнение setOnTouchListener внутри моего адаптера для возврата true (слушатель срабатывает, но событие не используется)

- мысль об использовании RecyclerView.findChildViewUnder внутри onChildDraw, чтобы прокрутить вручную и заблокировать метод super, но я не могу найти способ получить координаты

Пока ничего не работает. Как мне это сделать? Вот мой ItemTouchHelper:

private fun enableSwipe() {
        val simpleItemTouchCallback =
            object : ItemTouchHelper.SimpleCallback(ItemTouchHelper.ACTION_STATE_IDLE, ItemTouchHelper.UP or ItemTouchHelper.DOWN or ItemTouchHelper.LEFT) {

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

            override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
                val position = viewHolder.adapterPosition

                if (direction == ItemTouchHelper.LEFT) {
                    val content = mAdapter.getContentForPosition(position)

                    //do stuff...
                }
            }

            override fun onChildDraw(
                c: Canvas,
                recyclerView: RecyclerView,
                viewHolder: RecyclerView.ViewHolder,
                dX: Float,
                dY: Float,
                actionState: Int,
                isCurrentlyActive: Boolean
            ) {

                val mdX = if (abs(dY) > abs(dX)) {
                    0f
                }else{
                    dX
                }
                val mdY = if (abs(dY) > abs(dX)) {
                    when{
                        dY > 0 ->  if (dY > 500f) 500f else dY
                        else -> if (dY < -500f) -500f else dY
                    }

                }else{
                    0f
                }
                //override viewHolder in case we swipe up or down on the other content
                val mViewHolder: RecyclerView.ViewHolder = if (abs(dY) > abs(dX)) {
                            if (dY < 0) {
                                //swiping up
                                getViewHolder(1) ?: viewHolder
                            } else {
                                getViewHolder(0) ?: viewHolder
                            }
                        }else {
                    viewHolder
                }

                super.onChildDraw(c, recyclerView, mViewHolder, mdX, mdY, actionState, isCurrentlyActive)
            }
        }
    val itemTouchHelper = ItemTouchHelper(simpleItemTouchCallback)
    itemTouchHelper.attachToRecyclerView(recyclerViewClash)
}

enter image description here

1 Ответ

1 голос
/ 11 января 2020

Вот единственное, что работает, наконец-то нашел. Важно понимать, что ItemTouchHelper будет реализовывать onItemTouchListener:

OnItemTouchListener позволяет приложению перехватывать происходящие события касания на уровне иерархии представления RecyclerView до того, как эти события касания учитываются для собственного режима прокрутки в RecyclerView .

textView.setOnTouchListener { v, event ->
        //let the scrollView handle the scroll event
        scrollView.onTouchEvent(event)
        //this is the key feature
        v.parent.requestDisallowInterceptTouchEvent(true)
        //return true to consume the event (mandatory)
        true
}

Больше ничего не нужно. Также достаточно ScrollView, нет необходимости в NestedScrollView.

...