1

Setup: I have a RecyclerView with a vertical LinearLayoutManager. Each ViewHolder has 2 TextViews (green and red in the picture), which can be very long. RED can be scrolled horizontally thanks to a HorizontalScrollView. GREEN can be scrolled vertically thanks to a ScrollView.

Now I have implemented ItemTouchHelper, to swipe LEFT, UP or DOWN. The problem is that my ScrollViews don't work anymore. Instead, even when I swipe GREEN UP or DOWN, it is my ViewHolder that moves. How do I prevent my ItemTouchHelper from getting the touch event?

I've tried:

-android:descendantFocusability="blocksDescendants"

-NestedScrollView instead of ScrollView

-implementing setOnTouchListener inside my adapter to return true (the listener is triggered, but the event is not consumed)

-thought about using RecyclerView.findChildViewUnder inside onChildDraw to scroll manually and block the super method but I can't find a way to get the coordinates

Nothing works so far. How do I do this? Here is my 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

mrj
  • 589
  • 1
  • 7
  • 17

1 Answers1

1

Here is the only thing that works, finally found it. It is important to understand that the ItemTouchHelper will implement onItemTouchListener:

An OnItemTouchListener allows the application to intercept touch events in progress at the view hierarchy level of the RecyclerView before those touch events are considered for RecyclerView's own scrolling behavior.

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
}

Nothing else is needed. Also, a ScrollView is enough, no need for a NestedScrollView.

mrj
  • 589
  • 1
  • 7
  • 17