Как добавить прослушиватель кликов для ItemDecoration в RecyclerView Android?

Я пытался добавить прослушиватель кликов к элементу украшений, как показано ниже, но все равно не повезло. Пожалуйста помоги.

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) {

    }

})

3 ответа

ItemDecoration поможет вам нарисовать что-то между предметами, но View вы рисуете на самом деле RecyclerView сам (согласно Layout Inspector) через его Canvas. Таким образом, вы не сможете добавить базовыйonClickListener на этом украшения.

В соответствии с вашим кодом, я думаю, у вас есть украшение для каждого заголовка?

Для этого я бы не стал рассматривать мой заголовок как ItemDecoration но как предмет (другого типа) я бы накормил RecyclerView с.

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

В вашем адаптере (с элементами: RecyclerViewItem) вы отменяете getItemViewTypeметод с использованием пользовательских идентификаторов. Затем вonBindViewHolder вы можете проверить тип представления элемента и добавить свой onClickListener на ваш взгляд, если это Header.

Для получения дополнительной информации вы можете выполнить поиск сборки RecyclerView с другим типом элемента.

Вы можете настроить 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)
        }
    }
}

Вы можете добавить обратный вызов в адаптер, как показано ниже.

Сначала создайте интерфейс в классе Adapter:

public interface OnRecycleItemClickListener {
    void onClick(View v, int position,String type);
}

Второй шаг - создание метода внутри класса адаптера для установки интерфейса.

 public void setOnRecycleItemClickListener(OnRecycleItemClickListener onRecycleItemClickListener){
    this.onRecycleItemClickListener = onRecycleItemClickListener;
}

Теперь установите onClick of Viewholder itemView.it является родительским макетом в каждом видоискателе.

viewHolder.itemView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            if (onRecycleItemClickListener!=null)
            onRecycleItemClickListener.onClick(view, viewHolder.getAdapterPosition(),"parent");
        }
    });

Для просмотра текста

viewHolder.textview.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            if (onRecycleItemClickListener!=null)
            onRecycleItemClickListener.onClick(view, viewHolder.getAdapterPosition(),"textview");
        }
    });

Теперь установите интерфейс из действия или фрагмента, используя объект адаптера.

 adapter.setOnRecycleItemClickListener(new BeaconListAdapter.OnRecycleItemClickListener() {
            @Override
            public void onClick(View v, int position,String type) {
              if (type.equals("parent")){

                }else if(type.equals("textview")){

                }
            }
        });
Другие вопросы по тегам