I have an horizontal RecyclerView with leftPadding = 48dp, topPadding = 24dp and clipToPadding = false. It starts with an empty space on the left, but when the user scrolls the list its items are drawn on that (previously empty) space. The top space is always empty.

enter image description here

RecyclerView是在一个框架布局内与foreground = selectableItemBackground.

My problem comes from the fact that the RecyclerView consumes and ignores touches on the left and top spaces, meaning an OnClickListener won't be triggered, both when attached to the FrameLayout or to the RecyclerView.

I already tried with clickable = false and focusable = false on the RecyclerView, it doesn't work.

What I'm looking for:

  1. 可滚动RecyclerView enter image description here
  2. 可点击RecyclerView
  3. FrameLayout click events when RecyclerView's empty spaces are clicked
  4. (替代3)可点击的RecyclerView's个空格 enter image description hereenter image description here

EDIT: I've created a simple project that shows the problem I'm talking about: https://github.com/dadino/recyclerviewemptyspacestest There are 2 commits, on the first one I try to catch the click on the parent view, on the second one I try to catch the click on the RecyclerView itself. Neither of them works.

推荐答案

You have to create your custom RecyclerView implementation, where you would listen to touch events and perform filtering based on that.

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

}

结果:

enter image description here

Kotlin相关问答推荐

如何在Kotlin中反射多个对象以查找特定类型的属性

有什么原因,我得到一个空相关的错误在这个代码

Android前台服务 list —Altbeacon

使用数据存储首选项Kotlin Jetpack Compose

Kotlin是否针对范围和进度优化sum()?

在Kotlin中求n个ClosedRange实例相交的最常用方法是什么?

在 Kotlin 中将 Array 转换为 IntArray 时丢失值

Kotlin Path.useLines { } - 如何不获取 IOException("Stream closed")?

从带有 Room 和 Flows 的 SQLite 表中获取祖先树

如何使用 Kotlin KClass 属性 simpleName 生成空值

DatabaseManager_Impl 不是抽象的,不会覆盖 RoomDatabase 中的抽象方法 clearAllTables()

如何解决此错误请Kotlin:[Internal Error] java.lang.ExceptionInInitializerError

如何在 Android Studio 3.1.3 中查看 Kotlin 中有趣的源代码?

将协同路由调用放在存储库或ViewModel中哪个更好?

从 Spring WebFlux 返回 Flux 返回一个字符串而不是 JSON 中的字符串数组

kotlin RecyclerView分页

修改扩展函数中的this

如何让数据类在Kotlin中实现接口/扩展超类属性?

类型不匹配推断类型为单位,但应为空

Kotlin 是否支持部分应用程序?