我有一个水平的RecyclerView
with leftPadding = 48dp
, topPadding = 24dp
and clipToPadding = false
。它从左侧的空白空间开始,但是当用户滚动列表时,其项目将绘制在该(以前是空的)空间上。顶部空间始终是空的。
This RecyclerView
位于 FrameLayout 内foreground = selectableItemBackground
.
我的问题来自于这样一个事实RecyclerView
消耗并忽略左侧和顶部空间的触摸,这意味着OnClickListener
不会被触发,无论是连接到FrameLayout
或到RecyclerView
.
我已经尝试过clickable = false
and focusable = false
on the RecyclerView
,它不起作用。
我正在寻找什么:
- Scrollable
RecyclerView
- Clickable
RecyclerView
items
-
FrameLayout
点击事件时RecyclerView's
单击空白处
- (alternative to 3) Clickable
RecyclerView's
empty spaces
编辑:我创建了一个简单的项目来显示我正在讨论的问题:https://github.com/dadino/recyclerviewemptyspacestest https://github.com/dadino/recyclerviewemptyspacestest有 2 个提交,在第一个提交中,我尝试捕获对父视图的点击,在第二个提交中,我尝试捕获对 RecyclerView 本身的点击。它们都不起作用。
您必须创建您的自定义RecyclerView
实现,您可以在其中监听触摸事件并基于该事件执行过滤。
class MyRecyclerView @JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : RecyclerView(context, attrs, defStyleAttr) {
private var isValid = false
private var x: Int = 0
private var y: Int = 0
// this will help us to understand whether the event can be considered a touch or scroll
private val delta: Int = ViewConfiguration.get(getContext()).scaledTouchSlop
override fun onTouchEvent(e: MotionEvent?): Boolean {
val onTouchEvent = super.onTouchEvent(e)
when (e?.action) {
MotionEvent.ACTION_DOWN -> {
// saving initial touch location
x = e.rawX.toInt()
y = e.rawY.toInt()
isValid = true
}
MotionEvent.ACTION_MOVE -> {
if (Math.abs(e.rawX - x) > delta ||
Math.abs(e.rawY - y) > delta) {
// if a scroll happens - no longer consider this movement as valid
// this is needed for handling scroll on the inner part of `RecyclerView`
isValid = false
}
}
MotionEvent.ACTION_UP -> {
if (isValid && Math.abs(e.rawX - x) < delta &&
Math.abs(e.rawY - y) < delta &&
isInRightArea(e)) {
// 1. if the movement is still valid
// 2. we have actually performed a click
// 3. the click is in expected rectangle
// then perform click
performClick()
}
}
}
return onTouchEvent
}
// This is needed in order to handle the edge case, when a click listener
// would be fired when performing a click between the items of `RecyclerView`
private fun isInRightArea(e: MotionEvent): Boolean {
val r = Rect()
getGlobalVisibleRect(r)
r.left = paddingLeft
r.top = r.top + paddingTop
return !r.contains(e.rawX.toInt(), e.rawY.toInt())
}
}
Result:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)