爲 RecyclerView 添加 OnItemClickListener

由於 RecyclerView 沒有提供 OnItemClickListener ,只提供了一個 OnItemTouchListener ,導致網上各種方式實現 OnItemClickListener ,看了幾篇 blog 也沒有符合我口味的代碼…還是自己實現一遍吧。

1.自定義 RecyclerView

自定義 RecyclerView 直接繼承 v7 的 RecyclerView 即可,不需要複雜的代碼,以後統一使用該 RecyclerView,代碼如下:

    public class CustomRecyclerView extends RecyclerView {

    private Context context;
    private CustomRecyclerViewDivider customRecyclerViewDivider;// ItemView 的分割線,不是本文重點,請自動忽略

    private List<OnItemClickListener> onItemClickListenerList;// OnItemClickListener 用 add 的方式比較好

    public CustomRecyclerView(Context context) {
        this(context, null);
    }

    public CustomRecyclerView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public CustomRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init(context);
    }

    /**
     * 如果沒有其他操作,默認添加水平分割線,豎直分佈
     * 仿 ListView
     *
     * @param context
     */
    private void init(Context context) {
        this.context = context;
        onItemClickListenerList = new ArrayList<>();
        LinearLayoutManager manager = new LinearLayoutManager(context);
        setHasFixedSize(true);
        customRecyclerViewDivider = new CustomRecyclerViewDivider(new ColorDrawable(0xeeeeeeee), OrientationHelper.VERTICAL);
        //單位:px
        customRecyclerViewDivider.setMargin(0, 0, 0, 0);
        customRecyclerViewDivider.setHeight(ConvertTool.dp2px(1));
        addItemDecoration(customRecyclerViewDivider);
        setLayoutManager(manager);
    }

    @Override
    public void setAdapter(Adapter adapter) {
        super.setAdapter(adapter);
    }

    public void addOnItemClickListener(OnItemClickListener onItemClickListener) {
        if (null != onItemClickListener) {
            onItemClickListenerList.add(onItemClickListener);
        }
    }

    /**
     * 清空所有 onItemClickListener
     * @param onItemClickListener
     */
    public void clearAllOnItemClickListeners() {
        onItemClickListenerList.clear();
    }

    /**
     * 自定義 OnItemClickListener
     */
    public static abstract class OnItemClickListener {

        public void onClick(View view, int position) {
        }
    }

    public List<OnItemClickListener> getOnItemClickListenerList() {
        return onItemClickListenerList;
    }

}

2.自定義 OnClickListener

爲了更簡潔地實現 OnItemClickListener ,我們可以爲每個 ItemView 設置 OnclickListener ,由於 OnItemClickListener 需要 view 和 position ,所以自定義一個 OnclickListener 是最好的選擇,其代碼如下:

    // CustomOnClickListener 在我的代碼裏被多處使用,所以使用了泛型,當用於 
    // RecyclerView 時,需要將 T 傳入 Integer 以記錄點擊的位置,即: position
    public class CustomOnClickListener<T> implements View.OnClickListener {

    private T t;

    public CustomOnClickListener() {

    }

    public CustomOnClickListener(T t) {
        this.t = t;
    }

    @Override
    public void onClick(View v) {
        TraceKeeper.addTrace(v);
        this.onClick(v , t);
    }

    public void onClick(View view, T t) {
    }

    public void setT(T t) {
        this.t = t;
    }
    }

3.自定義 Adapter

要使 CustomRecyclerView 可以通過 addOnItemClickListener 設置監聽器,我們需要對 v7 提供的 RecyclerView.Adapter 略微改造一下,代碼如下:

    public abstract class RecyclereViewBaseAdapter<T extends RecyclereViewBaseAdapter.BaseViewHolder>
        extends RecyclerView.Adapter<T> {

    private CustomRecyclerView customRecyclerView;

    // 用於保存 customRecyclerView 中的 OnItemClickListener
    private List<CustomRecyclerView.OnItemClickListener> onItemClickListenerList;

    @Override
    public T onCreateViewHolder(ViewGroup parent, int viewType) {
        if (null != parent) {
            // 這裏執行一次即可
            customRecyclerView = (CustomRecyclerView) parent;
            onItemClickListenerList = customRecyclerView.getOnItemClickListenerList();
        }
        return null;
    }

    @Override
    public void onBindViewHolder(T holder, int position) {
        // 由於 RecyclerView 的 ItemView 會被複用,所以顯示新的 ItemView 時都需要更新
        // ItemView OnClickListener 的狀態,確保 position 是當前位置
        holder.getCustomOnClickListener().setT(position);
    }

    public class BaseViewHolder extends RecyclerView.ViewHolder {

        private View itemView;
        // 確保每個 ItemView 都有 CustomOnClickListener ,由於每個 View 只存在一個 OnClickListener 所以,使用了 
        // OnItemClickListener 就不要爲 ItemView 再設置 OnClickListener了。基於 RecyclerView 的原理(不做展開),
        // 在這裏設置 CustomOnClickListener 是最好的選擇。
        private CustomOnClickListener customOnClickListener = new CustomOnClickListener<Integer>(0) {
            @Override
            public void onClick(View view, Integer integer) {
                super.onClick(view, integer);
                if (null != onItemClickListenerList && onItemClickListenerList.size() > 0) {
                    for (CustomRecyclerView.OnItemClickListener onItemClickListener : onItemClickListenerList) {
                        onItemClickListener.onClick(view, integer);
                    }
                }
            }
        };

        public BaseViewHolder(View itemView) {
            super(itemView);
            this.itemView = itemView;
            this.itemView.setOnClickListener(customOnClickListener);
        }

        public CustomOnClickListener getCustomOnClickListener() {
            return customOnClickListener;
        }

    }

}

4.OnItemClickListener 的使用

自定義的 RecyclerView 設置 OnItemClickListener 和 ListView 沒有區別,可以直接設置:

    // 導包時注意     onItemClickListener 繼承的是 CustomRecyclerView.OnItemClickListener

    customRecyclerView .addOnItemClickListener(onItemClickListener);

另外,extends RecyclereViewBaseAdapter 時,不要忘記各個 method 中要 super(…) .

發佈了89 篇原創文章 · 獲贊 67 · 訪問量 21萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章