Android ScrollView inside RecyclerView.ViewHolder: 阻止 ItemTouchHelper 获取触摸事件?

Android ScrollView inside RecyclerView.ViewHolder: prevent ItemTouchHelper from getting touch event?

设置:我有一个 RecyclerView 和一个 vertical LinearLayoutManager。每个ViewHolder有2个TextViews(图中绿色和红色),可以很长。由于 HorizontalScrollViewRED 可以水平滚动。由于 ScrollView.

GREEN 可以垂直滚动

现在我已经实现了 ItemTouchHelper,可以向左、向上或向下滑动。问题是我的 ScrollViews 不再工作了。相反,即使我向上或向下滑动 GREEN,移动的也是我的 ViewHolder如何防止我的 ItemTouchHelper 获得触摸事件?

我试过:

-android:descendantFocusability="blocksDescendants"

-NestedScrollView 而不是 ScrollView

-在我的适配器中实现 setOnTouchListener 到 return true(监听器被触发,但事件没有被消耗)

-考虑过在onChildDraw中使用RecyclerView.findChildViewUnder手动滚动并阻止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)
}

这是唯一有效的方法,终于找到了。重要的是要了解 ItemTouchHelper 将实施 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
}

不需要其他任何东西。此外,ScrollView 就足够了,不需要 NestedScrollView.