Android Recyclerview:侦听填充单击事件
我有一个水平的Android Recyclerview:侦听填充单击事件,android,android-recyclerview,kotlin,android-custom-view,android-touch-event,Android,Android Recyclerview,Kotlin,Android Custom View,Android Touch Event,我有一个水平的RecyclerView,其中leftPadding=48dp,topPadding=24dp和cliptoppadding=false。它从左边的空白处开始,但是当用户滚动列表时,它的项目会被绘制在该空白处(以前是空白的)。顶部空间总是空的 此RecyclerView位于具有前台=selectableItemBackground的框架布局内 我的问题来自这样一个事实,RecyclerView消耗并忽略了左侧和顶部空间的接触,这意味着无论是连接到FrameLayout还是连接到R
RecyclerView
,其中leftPadding=48dp
,topPadding=24dp
和cliptoppadding=false
。它从左边的空白处开始,但是当用户滚动列表时,它的项目会被绘制在该空白处(以前是空白的)。顶部空间总是空的
此RecyclerView
位于具有前台=selectableItemBackground
的框架布局内
我的问题来自这样一个事实,RecyclerView
消耗并忽略了左侧和顶部空间的接触,这意味着无论是连接到FrameLayout
还是连接到RecyclerView
,都不会触发OnClickListener
我已经在RecyclerView
上尝试了clickable=false
和focusable=false
,但它不起作用
我要找的是:
RecyclerView
RecyclerView
项目
FrameLayout
单击RecyclerView的
空白时单击事件RecyclerView的
空白
共有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())
}
}
类MyRecyclerView@JVM重载构造函数(
context:context,attrs:AttributeSet?=null,defStyleAttr:Int=0
):RecyclerView(上下文、属性、defStyleAttr){
私有变量isValid=false
私有变量x:Int=0
私有变量y:Int=0
//这将帮助我们了解该事件是否可以被视为触摸或滚动
private val delta:Int=ViewConfiguration.get(getContext()).scaledTouchSlop
覆盖事件(e:MotionEvent?):布尔值{
val onTouchEvent=super.onTouchEvent(e)
何时(e?行动){
MotionEvent.ACTION\u向下->{
//保存初始触摸位置
x=e.rawX.toInt()
y=e.rawY.toInt()
isValid=true
}
MotionEvent.ACTION\u MOVE->{
如果(数学abs(e.rawX-x)>delta||
数学abs(e.rawY-y)>三角洲){
//如果发生滚动-不再认为这个运动是有效的。
//这是处理“RecyclerView”内部的滚动条所必需的
isValid=false
}
}
MotionEvent.ACTION\u UP->{
如果(isValid&&Math.abs(e.rawX-x)
结果:
显示您的代码。您希望看到什么代码?在您的recyclerview适配器中,您必须放置一个全局单击列表器和项目单击列表器,确保您仅对项目执行此操作。发布更多详细信息的代码每个项目的视图都有自己的clickListener,而不是适配器(它不是视图,无法注册clickListener)。问题不在于项目的点击监听器,而在于点击没有在项目的范围外注册(他们的点击监听器没有权限)。这就是我告诉你的精心构造的问题,我很喜欢阅读它。它就像一个符咒。