简体   繁体   English

如何在 RecyclerView Android 中向 ItemDecoration 添加点击监听器?

[英]How to add a click listener to ItemDecoration in RecyclerView Android?

I have tried to add a click listener to itemdecoration like below but still no luck.我试图向 itemdecoration 添加一个点击监听器,如下所示,但仍然没有运气。 Please help.请帮忙。

recyclerview.addOnItemTouchListener( object : RecyclerView.OnItemTouchListener{
    override fun onTouchEvent(rv: RecyclerView?, e: MotionEvent?) {

    }

    override fun onInterceptTouchEvent(rv: RecyclerView?, e: MotionEvent?): Boolean {
        val view = rv!!.findChildViewUnder(e!!.x, e!!.y)
        if(view == null) return false
        when(view.id){
            R.id.list_item_section_text->{
                Log.d("Clicked","Header")
            }
        }
        return false
    }

    override fun onRequestDisallowInterceptTouchEvent(disallowIntercept: Boolean) {

    }

})

ItemDecoration will help you draw something between items, but the View you're drawing in is actually the RecyclerView itself (according to Layout inspector), via its Canvas . ItemDecoration将帮助您在项目之间绘制一些东西,但您正在绘制的View实际上是RecyclerView本身(根据布局检查器),通过其Canvas So you won't be able to add an basic onClickListener on that decorations.因此,您将无法在该装饰上添加基本的onClickListener

According to your code, I guess you have an item decoration for each of your items header?根据您的代码,我猜您的每个项目标题都有一个项目装饰?

What I would do for this would be not to consider my header as an ItemDecoration but as an item (with different type) I would feed my RecyclerView with.我会为此做的不是将我的标头视为ItemDecoration而是将其视为一个项目(具有不同类型),我会用它来提供我的RecyclerView

sealed class RecyclerViewItem
object MainItem : RecyclerViewItem()
object Header : RecyclerViewItem()

In your adapter (with items: RecyclerViewItem ) you override getItemViewType method using custom ids.在您的适配器(带有项目: RecyclerViewItem )中,您使用自定义 ID 覆盖getItemViewType方法。 Then in onBindViewHolder you can check the item view type and add your onClickListener on your view if it's a Header .然后在onBindViewHolder您可以检查项目视图类型并在您的视图上添加您的onClickListener如果它是Header

For more info, you can search for building RecyclerView with different item type .有关更多信息,您可以搜索具有不同项目类型的构建 RecyclerView

You can customize a RecyclerView and check if touch event arrives to ItemDecorator or no:您可以自定义 RecyclerView 并检查触摸事件是否到达 ItemDecorator :

class YourRecyclerView @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : RecyclerView(context, attrs, defStyleAttr) {

    private val clicksFlow: MutableSharedFlow<ClickEvent> = MutableSharedFlow(
        extraBufferCapacity = 1, onBufferOverflow = BufferOverflow.DROP_OLDEST
    )

    fun getClicksFlow() = clicksFlow as Flow<RecyclerClickEvent>

    @SuppressLint("ClickableViewAccessibility")
    override fun onTouchEvent(e: MotionEvent) : Boolean{
        if (e.action == MotionEvent.ACTION_DOWN) {
            for (i in 0 until itemDecorationCount) {
                val decor = getItemDecorationAt(i)
                if (decor is YourDecoration && decor.isOnTouched(this, e)) {
                    clicksFlow.tryEmit(ClickEvent(e.x, e.y))
                    return true
                }
            }
        }
        return super.onTouchEvent(e)
    }

    override fun onInterceptTouchEvent(e: MotionEvent): Boolean {
        if (e.action == MotionEvent.ACTION_DOWN) {
            for (i in 0 until itemDecorationCount) {
                val decor = getItemDecorationAt(i)
                if (decor is YourDecoration && decor.isOnTouched(this, e)) {
                    return true
                }
            }
        }
        return super.onInterceptTouchEvent(e)
    }
}

class YourDecoration(/*some stuff*/) : RecyclerView.ItemDecoration() {

    fun isOnTouched(parent: YourRecyclerView , e: MotionEvent): Boolean {
        val w = abs(scaleX * width)
        val h = abs(scaleY * height)
        val top = topMargin - height / 2F - parent.paddingTop
        return if (scaleX > 0) {
            val side = parent.measuredWidth - sideMargin
            e.y >= top && e.y <= (top + h) && side >= e.x && (side - w) <= e.x
        } else {
            val side = sideMargin
            e.y >= top && e.y <= (top + h) && side <= e.x && e.x <= (side + w)
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM