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