RecyclerView 系統自帶點擊和長按事件(可複用)
- 寫在前面
我們用過RecyclerView的朋友都知道,它是不能直接設置其點擊事件的,系統並沒有給我們提供api,不像TextView,Button等控件,可以直接setOnClickListener(),所以退而求其次,利用曲線救國的策略,通過回調,我們一般都是在adapter裏面,單獨設置每一個控件的點擊事件,然後回調出來,但是,這並不能複用,每次都得重新設計,所以,今天我們說一下,系統自帶的可複用的RecyclerView的點擊事件設置。
- 關鍵類
RecyclerView.OnItemTouchListener (接口)
我們需要新建類,實現RecyclerView.OnItemTouchListener 這個接口,重寫onInterceptTouchEvent(RecyclerView rv, MotionEvent e)方法,當我們通過事件傳遞,捕捉到手勢事件之後,將它交給手勢處理的方法,就能夠實現單擊及長按的事件監聽。
@Override
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
View childView = rv.findChildViewUnder(e.getX(), e.getY());
if (childView == null) {
return false;
}
selectView = childView;
selectPosition = rv.getChildAdapterPosition(childView);
/**
* 交給手勢控制類來處理
*/
return mGestureDetector.onTouchEvent(e);
}
@Override
public void onTouchEvent(RecyclerView rv, MotionEvent e) {
}
@Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
}
childView就是被點擊的itemView,selectPosition就是被點擊的position。
- 設置監聽
設置回調監聽,將GestureDetector方法(手勢操作方法)的處理結果回調回去,就能夠在我們的activity中得到對應的點擊事件。
1. 定義監聽接口
設置builder是爲了方便只重寫點擊事件,或者只重寫長按事件。 又定義一個normal接口是爲了區別於其他的點擊事件,這裏並沒有定義其他的點擊事件。如果擴展,定義內部接口會比較好。
public interface OnItemClickListener {
interface Normal {
void onItemClick(View view, int position);
void onItemLongClick(View view, int position);
class Builder implements Normal {
@Override
public void onItemClick(View view, int position) {
}
@Override
public void onItemLongClick(View view, int position) {
}
}
}
}
2. 添加監聽構造方法
這是一個構造方法,將此方法作爲一個實例,傳入被調用的方法即可,調用方法見3.
public RecyclerItemClickListener(Context context, final OnItemClickListener.Normal mListener) {
mGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
/**
* 點擊
*/
@Override
public boolean onSingleTapUp(MotionEvent e) {
if (selectView != null && mListener != null){
mListener.onItemClick(selectView, selectPosition);
return true;
}
return super.onSingleTapUp(e);
}
/**
* 長按
*/
@Override
public void onLongPress(MotionEvent e) {
if (selectView != null && mListener != null){
mListener.onItemLongClick(selectView, selectPosition);
}
}
});
}
3. 調用點擊事件方法
// recyclerView 調用自己的addOnItemTouchListener方法,參數傳入我們定義的類RecyclerItemClickListener的實例
recycleView.addOnItemTouchListener(new RecyclerItemClickListener(context, onItemClickListener));
// 這是回調方法,在下面的回調裏面添加自己的處理邏輯,這裏有三種寫法
// 1.只回調單擊事件
private RecyclerItemClickListener.OnItemClickListener.Normal onItemClickListener = new RecyclerItemClickListener.OnItemClickListener.Normal.Builder() {
@Override
public void onItemClick(View view, int position) {
// 在這裏寫自己的單擊事件邏輯
}
};
// 2.只回調長按事件
private RecyclerItemClickListener.OnItemClickListener.Normal onItemClickListener = new RecyclerItemClickListener.OnItemClickListener.Normal.Builder() {
@Override
public void onItemLongClick(View view, int position) {
// 在這裏寫自己的長按事件邏輯
}
};
// 3.同時回調點擊和長按事件
private RecyclerItemClickListener.OnItemClickListener.Normal onItemClickListener = new RecyclerItemClickListener.OnItemClickListener.Normal() {
@Override
public void onItemClick(View view, int position) {
// 在這裏寫自己的單擊事件邏輯
}
@Override
public void onItemLongClick(View view, int position) {
// 在這裏寫自己的長按事件邏輯
}
};
- 結束語
好了,可點擊,可長按,可複用的RecyclerView的點擊事件就介紹到這裏了,歡迎大家指正批評。
附上完整代碼
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
public class RecyclerItemClickListener implements RecyclerView.OnItemTouchListener {
private GestureDetector mGestureDetector;
/**
* 被選擇的view
*/
private View selectView;
/**
* 被選擇view的position
*/
private int selectPosition;
@Override
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
View childView = rv.findChildViewUnder(e.getX(), e.getY());
if (childView == null) {
return false;
}
selectView = childView;
selectPosition = rv.getChildAdapterPosition(childView);
/**
* 交給手勢控制類來處理
*/
return mGestureDetector.onTouchEvent(e);
}
@Override
public void onTouchEvent(RecyclerView rv, MotionEvent e) {
}
@Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
}
public RecyclerItemClickListener(Context context, final OnItemClickListener.Normal mListener) {
mGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
/**
* 點擊
*/
@Override
public boolean onSingleTapUp(MotionEvent e) {
if (selectView != null && mListener != null){
mListener.onItemClick(selectView, selectPosition);
return true;
}
return super.onSingleTapUp(e);
}
/**
* 長按
*/
@Override
public void onLongPress(MotionEvent e) {
if (selectView != null && mListener != null){
mListener.onItemLongClick(selectView, selectPosition);
}
}
});
}
public interface OnItemClickListener {
interface Normal {
void onItemClick(View view, int position);
void onItemLongClick(View view, int position);
class Builder implements Normal {
@Override
public void onItemClick(View view, int position) {
}
@Override
public void onItemLongClick(View view, int position) {
}
}
}
}
}