Android ScrollView inside RecyclerView.ViewHolder: 阻止 ItemTouchHelper 获取触摸事件?
Android ScrollView inside RecyclerView.ViewHolder: prevent ItemTouchHelper from getting touch event?
设置:我有一个 RecyclerView
和一个 vertical LinearLayoutManager
。每个ViewHolder
有2个TextViews
(图中绿色和红色),可以很长。由于 HorizontalScrollView
,RED
可以水平滚动。由于 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
.
设置:我有一个 RecyclerView
和一个 vertical LinearLayoutManager
。每个ViewHolder
有2个TextViews
(图中绿色和红色),可以很长。由于 HorizontalScrollView
,RED
可以水平滚动。由于 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
.