Android RecyclerView自帶原生點選和長按事件
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) {
}
}
}
}
}