RecyclerView并沒(méi)有像ListView那樣提供了OnItemClick预愤,OnItemLongClick等事件回調(diào)接口沟于,所以,我們需要自己去實(shí)現(xiàn)植康。
為了后面的幾種方式都可以用同一的回調(diào)接口來(lái)實(shí)現(xiàn)Click和LongClick事件旷太,我們先定義一個(gè)回調(diào)事件接口。
public static interface OnItemClickListener {
void onItemClick(View view);
void onItemLongClick(View view);
}
1 . 通過(guò)Adapter來(lái)處理
在Adapter的onCreateViewHolder和onBindViewHolder函數(shù)添加如下代碼
@Override
public ListViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
ListViewHolder viewHolder = new ListViewHolder(
mInflater.inflate(R.layout.list_item, parent, false));
viewHolder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mItemClickListener.onItemClick(V);
}
});
viewHolder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
mItemClickListener.onItemLongClick(v);
return true;
}
});
return viewHolder;
}
@Override
public void onBindViewHolder(ListViewHolder holder, final int position) {
if (mData != null) {
holder.mIndex.setText(Integer.toString(position));
holder.mTitle.setText(mData.get(position).getTitle());
holder.itemView.setTag(mData.get(position).getId());
}
}
其中销睁,mItemClickListener為注冊(cè)進(jìn)來(lái)的Click回調(diào)監(jiān)聽(tīng)供璧,一般為對(duì)應(yīng)的Activity或Fragment。在onBindViewHolder中冻记,我們對(duì)ItemView設(shè)置了Tag屬性睡毒,將數(shù)據(jù)的ID設(shè)置進(jìn)去,在Activity或Fragment中可以通過(guò)獲取view的Tag來(lái)獲取當(dāng)前點(diǎn)擊item的Id值檩赢。另外,在中,可以直接通過(guò)RecyclerView.getChildAdapterPosition獲取到當(dāng)前點(diǎn)擊的Item的列表索引贞瞒。
mListAdapter.setOnViewItemClickListener(new ListAdapter.OnItemClickListener() {
@Override
public void onItemClick(View view) {
int position = mRecyclerView.getChildAdapterPosition(view);
Toast.makeText(this, "onItemClick : " + position, Toast.LENGTH_SHORT).show();
}
@Override
public void onItemLongClick(View view) {
int position = mRecyclerView.getChildAdapterPosition(view);
Toast.makeText(this, "onItemLongClick : " + position, Toast.LENGTH_SHORT).show();
}
}
2 . 通過(guò)OnItemTouchListener來(lái)監(jiān)聽(tīng)touch事件并轉(zhuǎn)化為點(diǎn)擊事件
創(chuàng)建類RecyclerViewItemTouchListener繼承RecyclerView.SimpleOnItemTouchListener
public class RecyclerViewItemTouchListener extends RecyclerView.SimpleOnItemTouchListener {
private OnItemClickListener mClickListener;
private GestureDetectorCompat mGestureDetector;
public RecyclerViewItemTouchListener(final RecyclerView recyclerView,
OnItemClickListener listener) {
this.mClickListener = listener;
mGestureDetector = new GestureDetectorCompat(recyclerView.getContext(),
new GestureDetector.SimpleOnGestureListener() {
@Override
public boolean onSingleTapUp(MotionEvent e) {
View childView = recyclerView.findChildViewUnder(e.getX(), e.getY());
if (childView != null && mClickListener != null) {
mClickListener.onItemClick(childView);
}
return true;
}
@Override
public void onLongPress(MotionEvent e) {
View childView = recyclerView.findChildViewUnder(e.getX(), e.getY());
if (childView != null && mClickListener != null) {
mClickListener.onItemLongClick(childView);
}
}
});
}
@Override
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
mGestureDetector.onTouchEvent(e);
return false;
}
}
在Activity或Fragment中添加OnItemTouchListener偶房。
mRecyclerView.addOnItemTouchListener(new RecyclerViewItemTouchListener(mRecyclerView, new RecyclerViewItemTouchListener.OnItemClickListener() {
@Override
public void onItemClick(View view) {
}
@Override
public void onItemLongClick(View view, int position) {
}
});
3 . 通過(guò)OnChildAttachStateChangeListener在Item在Attach時(shí)添加點(diǎn)擊事件
創(chuàng)建RecyclerViewClickSupport類,繼承RecyclerView.OnChildAttachStateChangeListener
public class RecyclerViewClickSupport implements RecyclerView.OnChildAttachStateChangeListener {
private View.OnClickListener mItemClickListener = null;
private View.OnLongClickListener mItemLongClickListener = null;
private RecyclerView mRecyclerView = null;
public RecyclerViewClickSupport(RecyclerView view, View.OnClickListener listener,
View.OnLongClickListener listener2){
mRecyclerView = view;
mItemClickListener = listener;
mItemLongClickListener = listener2;
view.addOnChildAttachStateChangeListener(this);
}
@Override
public void onChildViewAttachedToWindow(View view) {
if (mItemClickListener != null){
view.setOnClickListener(mItemClickListener);
}
if (mItemLongClickListener != null){
view.setOnLongClickListener(mItemLongClickListener);
}
}
@Override
public void onChildViewDetachedFromWindow(View view) {
}
}
在Activity或Fragment中添加RecyclerViewClickSupport實(shí)現(xiàn)對(duì)RecyclerView的Item的點(diǎn)擊事件的監(jiān)聽(tīng)军浆。
mRCClickSupport = new RecyclerViewClickSupport(mRecyclerView, new View.OnClickListener() {
@Override
public void onClick(View v) {
}
}, new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
return false;
}
});
以上的三種實(shí)現(xiàn)方式中棕洋,其中:
- 方式二沒(méi)有辦法對(duì)item的子view進(jìn)行事件監(jiān)聽(tīng),而且因?yàn)闆](méi)有為item真正的添加Click事件監(jiān)聽(tīng)乒融,所以Item的Click按下效果出不來(lái)掰盘。
- 方法一和方法三,更建議使用方法一赞季,畢竟Adapter對(duì)Item的數(shù)據(jù)以及布局都有處理愧捕。
- 方法三可以封裝為獨(dú)立的類,但如果要處理子view申钩,難免還要加入布局相關(guān)的代碼次绘,這樣就進(jìn)一個(gè)降低了代碼的耦合。