为 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(…) .

猜你喜欢

转载自blog.csdn.net/niuzhucedenglu/article/details/69948378