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