Recyclerview: escucha los events de clic de relleno

Tengo un RecyclerView horizontal con leftPadding = 48dp , topPadding = 24dp y clipToPadding = false . Comienza con un espacio vacío a la izquierda, pero cuando el usuario se desplaza por la list, sus elementos se dibujan en ese espacio (previamente vacío). El espacio superior siempre está vacío.

enter image description here

Este RecyclerView está dentro de FrameLayout con foreground = selectableItemBackground .

Mi problema proviene del hecho de que RecyclerView consume e ignora los toques en los espacios izquierdo y superior, lo que significa que no se activará un OnClickListener , tanto si está conectado a FrameLayout como a RecyclerView .

Ya lo intenté con clickable = false y focusable = false en RecyclerView , no funciona.

Lo que estoy buscando:

  1. Scroll RecyclerView enter image description here
  2. Clickable RecyclerView elementos enter image description here
  3. FrameLayout clic en events cuando se hace clic en los espacios vacíos RecyclerView's
  4. (alternativa a 3) Espacios vacíos de Clickable RecyclerView's enter image description here enter image description here

EDITAR: He creado un proyecto simple que muestra el problema del que estoy hablando: https://github.com/dadino/recyclerviewemptyspacestest Hay 2 commits, en el primero bash capturar el clic en la vista principal, en el segundo trato de ver el clic en el RecyclerView. Ninguno de los dos funciona.

Tienes que crear tu implementación personalizada de RecyclerView , donde escucharías events táctiles y realizarías filters basados ​​en eso.

 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 considenetworking 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 finetworking 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()) } } 

Resultado:

enter image description here

  • Cómo integrar Admob Native Advanced Ads usando Kotlin - Android
  • ¿Por qué onclick en los ítems de RecyclerView se devuelve una identificación de artículo incorrecta?
  • RecyclerView: implementa correctamente la eliminación de SnackBar UNDO (Kotlin)
  • Llame a getMeasunetworkingWidth () o getWidth () para RecyclerView return 0 en data binding
  • ¿Cómo cambiar el color de background de una vista de carta cuando se selecciona?
  • Cómo proteger el oyente de desplazamiento sin fin de un reciclador
  • My RecyclerView no se notifica adecuadamente
  • java.lang.IllegalStateException: TextView no debe ser nulo (Android / Kotlin)
  • Intentando crear un reciclador simple en Kotlin, pero el adaptador no se está aplicando correctamente
  • Genéricos para RecyclerView.Adapter Android
  • SortedList IndexOutBoundsException: Inconsistencia detectada. La position del artículo no es válida al eliminar el último elemento