处理 RecyclerView 项目的点击事件和项目内按钮的点击事件。避免同时听两者

Posted

技术标签:

【中文标题】处理 RecyclerView 项目的点击事件和项目内按钮的点击事件。避免同时听两者【英文标题】:Handling click events of a RecyclerView Item and the click events of buttons inside the item. Avoid listening to both at the same time 【发布时间】:2020-11-19 04:06:19 【问题描述】:

我有一个带有按钮的 recyclerview 项目。

    <?xml version="1.0" encoding="utf-8"?>
    <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_
        android:layout_
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_margin="1dp">
 
            <LinearLayout
                android:layout_
                android:layout_
                android:padding="1dp">
    
                <LinearLayout
                    android:layout_
                    android:layout_
                    android:orientation="vertical"
                    android:layout_weight="1"
                    android:id ="@+id/layLeft">
    
                    <TextView
                        android:id="@+id/txtName"
                        android:layout_
                        android:layout_
                        android:layout_marginLeft="2dp"
                        android:layout_marginRight="2dp"
                        android:layout_marginTop="2dp"
                        android:textColor="@android:color/black" />
    
                    <TextView
                        android:id="@+id/txtDesc"
                        android:layout_
                        android:layout_
                        android:layout_marginStart="2dp"
                        android:layout_marginLeft="2dp"
                        android:layout_marginTop="2dp"
                        android:layout_marginRight="2dp"
                        android:ellipsize="end"
                        android:maxLines="1" />
    
                    <TextView
                        android:id="@+id/txtCategory"
                        android:layout_
                        android:layout_
                        android:layout_marginLeft="2dp"
                        android:layout_marginStart="2dp"
                        android:layout_marginTop="2dp"
                        android:textColor="@android:color/holo_red_dark" />
                </LinearLayout>
    
                <LinearLayout
                    android:layout_
                    android:layout_
                    android:orientation="vertical"
                    >
    
                    <ImageButton
                        android:id="@+id/btn_mark_done"
                        android:layout_
                        android:layout_
                        android:background="@null"
                        android:padding="4dp"
                        android:src="@android:drawable/ic_menu_set_as"
                        android:layout_centerHorizontal="true"
                        android:adjustViewBounds="true"
                        android:scaleType="fitXY"/>
    
                    <ImageButton
                        android:id="@+id/btn_delete"
                        android:layout_
                        android:layout_
                        android:background="@null"
                        android:padding="4dp"
                        android:src="@android:drawable/ic_menu_delete"
                        android:layout_centerHorizontal="true"
                        android:adjustViewBounds="true"
    
                        android:scaleType="fitXY"/>
    
                </LinearLayout>
            </LinearLayout>
    
    </FrameLayout>

为处理 RecyclerView 项目和单个按钮的单击事件创建了一个自定义侦听器。单击按钮时,单击事件侦听器可以正常工作。而且 RecyclerView itemclick 监听器也被监听。这会导致双重执行。

下面给出了监听器


    class RecyclerTouchListener implements RecyclerView.OnItemTouchListener

        private ClickListener clicklistener;
        private GestureDetector gestureDetector;

        public RecyclerTouchListener(Context context, final RecyclerView recycleView, final ClickListener clicklistener)

            this.clicklistener=clicklistener;
            gestureDetector=new GestureDetector(context,new GestureDetector.SimpleOnGestureListener()
                @Override
                public boolean onSingleTapUp(MotionEvent e) 
                    return true;
                

                @Override
                public void onLongPress(MotionEvent e) 
                    View child=recycleView.findChildViewUnder(e.getX(),e.getY());

                    if(child!=null && clicklistener!=null)
                        clicklistener.onLongPress(recycleView.getChildAdapterPosition(child));
                    
                
            );
        

        @Override
        public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) 
            View child=rv.findChildViewUnder(e.getX(),e.getY());

            if(child!=null && clicklistener!=null && gestureDetector.onTouchEvent(e))
                clicklistener.launchIntent(rv.getChildAdapterPosition(child));
            
            return false;
        

        @Override
        public void onTouchEvent(RecyclerView rv, MotionEvent e) 

        @Override
        public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept)  
    

对于按钮

 btnMarkDone.setOnClickListener(new View.OnClickListener() 
                @Override
                public void onClick(View v) 
                    clickListener.onMarkDone( 0);
                
            );

            btnDelete.setOnClickListener(new View.OnClickListener() 
                @Override
                public void onClick(View v) 
                    clickListener.onDeleteItem( 0);
                
            );

有什么办法可以避免吗?

【问题讨论】:

【参考方案1】:

我猜你应该尽量避免实现 RecyclerView.OnItemTouchListener,请按如下方式使用带有适配器的回收视图并在 recycleView 项目单击时使用 TouchListener,代码如下 -

public class RecycleAdapter extends RecyclerView.Adapter<RecycleAdapter.CustomViewHolder> 

    private Context context;
    // your data variables

    public RecycleAdapter(Context context) 
        this.context = context;
    

    // implement your click and touch listeners here

    @NonNull
    @Override
    public CustomViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) 
        return new CustomViewHolder(LayoutInflater.from(context).inflate(R.layout.item_layout, parent, false));
    

    @Override
    public void onBindViewHolder(@NonNull CustomViewHolder holder, int position) 
       //data binding code
    

    @Override
    public int getItemCount()  
        // return size;
    


    public class CustomViewHolder extends RecyclerView.ViewHolder 

        ImageView btnMarkDone, btnMarkDone;

        public CustomViewHolder(@NonNull View itemView) 
            super(itemView);

            btnMarkDone = itemView.findViewById(R.id.btnMarkDone);
            btnMarkDone = itemView.findViewById(R.id.btnMarkDone);

            btnMarkDone.setOnClickListener(new View.OnClickListener() 
                @Override
                public void onClick(View v) 
                    // click listener here
                
            );

            btnDelete.setOnClickListener(new View.OnClickListener() 
                @Override
                public void onClick(View v) 
                    // click listener here
                
            );

            itemView.setOnTouchListener(new View.OnTouchListener() 
                @Override
                public boolean onTouch(View v, MotionEvent event) 
                    //implement touch listener action here
                    return false;
                
            );

        
    

如果您想对回收视图滚动进行操作,那么用户 RecyclerView.OnScrollListener

编码愉快!

【讨论】:

以上是关于处理 RecyclerView 项目的点击事件和项目内按钮的点击事件。避免同时听两者的主要内容,如果未能解决你的问题,请参考以下文章

RecyclerView | 处理 RecyclerView 中的点击事件

RecyclerView | 处理 RecyclerView 中的点击事件

Android零基础入门第66节:RecyclerView点击事件处理

父控件的点击事件被Recyclerview拦截

Recyclerview:监听填充点击事件

Recyclerview点击事件,更新item的UI+更新Recyclerview外的控件