优雅的方式,无侵入式的为 RecyclerView 设置点击事件,包括 Item 点击、子控件点击


public class ItemClickSupport {
    private final RecyclerView mRecyclerView;
    private OnItemClickListener mOnItemClickListener;
    private OnItemLongClickListener mOnItemLongClickListener;

    private HashMap<Integer, OnChildClickListener> childListenerMap = new HashMap<>();

    private View.OnClickListener mOnClickListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if (mOnItemClickListener != null) {
                RecyclerView.ViewHolder holder = mRecyclerView.getChildViewHolder(v);
                mOnItemClickListener.onItemClicked(mRecyclerView, holder.getAdapterPosition(), v);
            }
        }
    };

    private View.OnLongClickListener mOnLongClickListener = new View.OnLongClickListener() {
        @Override
        public boolean onLongClick(View v) {
            if (mOnItemLongClickListener != null) {
                RecyclerView.ViewHolder holder = mRecyclerView.getChildViewHolder(v);
                return mOnItemLongClickListener.onItemLongClicked(mRecyclerView, holder.getAdapterPosition(), v);
            }
            return false;
        }
    };


    private RecyclerView.OnChildAttachStateChangeListener mAttachListener = new RecyclerView.OnChildAttachStateChangeListener() {
        @Override
        public void onChildViewAttachedToWindow(@NonNull View view) {
            if (mOnItemClickListener != null) {
                view.setOnClickListener(mOnClickListener);
            }
            if (mOnItemLongClickListener != null) {
                view.setOnLongClickListener(mOnLongClickListener);
            }

            //子 View 点击
            if (!childListenerMap.isEmpty()) {
                for (final Integer key : childListenerMap.keySet()) {
                    view.findViewById(key).setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            RecyclerView.ViewHolder holder = mRecyclerView.findContainingViewHolder(v);
                            if (holder != null && holder.getAdapterPosition() != -1) {
                                OnChildClickListener listener = childListenerMap.get(key);
                                if (listener != null) {
                                    listener.onChildClicked(mRecyclerView, holder.getAdapterPosition(), v);
                                }
                            }
                        }
                    });
                }
            }
        }

        @Override
        public void onChildViewDetachedFromWindow(@NonNull View view) {

        }
    };

    private ItemClickSupport(RecyclerView recyclerView) {
        mRecyclerView = recyclerView;
        mRecyclerView.setTag(R.id.item_click_support, this);
        mRecyclerView.addOnChildAttachStateChangeListener(mAttachListener);
    }

    public static ItemClickSupport addTo(RecyclerView view) {
        ItemClickSupport support = (ItemClickSupport) view.getTag(R.id.item_click_support);
        if (support == null) {
            support = new ItemClickSupport(view);
        }
        return support;
    }

    public static ItemClickSupport removeFrom(RecyclerView view) {
        ItemClickSupport support = (ItemClickSupport) view.getTag(R.id.item_click_support);
        if (support != null) {
            support.detach(view);
        }
        return support;
    }

    public ItemClickSupport setOnItemClickListener(OnItemClickListener listener) {
        mOnItemClickListener = listener;
        return this;
    }

    public ItemClickSupport setOnItemLongClickListener(OnItemLongClickListener listener) {
        mOnItemLongClickListener = listener;
        return this;
    }

    public ItemClickSupport setOnChildClickListener(int resId, OnChildClickListener listener) {
        childListenerMap.put(resId,listener);
        return this;
    }

    private void detach(RecyclerView view) {
        view.removeOnChildAttachStateChangeListener(mAttachListener);
        view.setTag(R.id.item_click_support, null);
    }

    public interface OnItemClickListener {

        void onItemClicked(RecyclerView recyclerView, int position, View v);
    }

    public interface OnItemLongClickListener {

        boolean onItemLongClicked(RecyclerView recyclerView, int position, View v);
    }

    public interface OnChildClickListener {
        void onChildClicked(RecyclerView recyclerView, int position, View v);
    }
}

使用方式:

ItemClickSupport.addTo(rvUnfinishedPlans).setOnChildClickListener(R.id.img_finish, new ItemClickSupport.OnChildClickListener() {
    @Override
    public void onChildClicked(RecyclerView recyclerView, int position, View v) {
        Log.d(TAG, "完成: "  + position);
    }
});
ItemClickSupport.addTo(rvUnfinishedPlans).setOnChildClickListener(R.id.img_plan_alarm, new ItemClickSupport.OnChildClickListener() {
    @Override
    public void onChildClicked(RecyclerView recyclerView, int position, View v) {
        Log.d(TAG, "闹钟: "  + position);
    }
});
ItemClickSupport.addTo(rvUnfinishedPlans).setOnItemClickListener(new ItemClickSupport.OnItemClickListener() {
    @Override
    public void onItemClicked(RecyclerView recyclerView, int position, View v) {
        Log.d(TAG, "Item:" + position);
    }
});