如何設(shè)置item點(diǎn)擊水波紋效果:
- 在drawable文件夾下創(chuàng)建 linearlayout_water_selector.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
<corners android:radius="5dip"/>
<solid android:color="#ffffff"/>
</shape>
- 在drawable-v24文件夾下創(chuàng)建 linearlayout_water_selector.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
<corners android:radius="5dip"/>
<solid android:color="#ffffff"/>
</shape>
- 使用的顏色代碼添加到res-values-colors下
<color name="text_Grey">#c1c1c2</color>
<color name="colorWhite">#ffffff</color>
- 將布局引用到RecyclerView子項(xiàng)布局里
android:background="@drawable/linearlayout_water_selecto"
android:clickable="true"
android:focusable="true"
此時(shí)設(shè)置完水波紋的點(diǎn)擊效果
但是不要急鹏氧,我們再來看看RecyclerView中如何設(shè)置item可點(diǎn)擊渤涌,這里筆者采用的是addOnItemTouchListener方法,由api提供:
RecyclerView.addOnItemTouchListener(OnItemTouchListener listener)
接下來看看完整代碼
public abstract class OnRecyclerItemClickListener implements RecyclerView.OnItemTouchListener {
private GestureDetectorCompat mGestureDetector;
private RecyclerView recyclerView;
public OnRecyclerItemClickListener(RecyclerView recyclerView) {
this.recyclerView = recyclerView;
mGestureDetector = new GestureDetectorCompat(recyclerView.getContext(), new ItemTouchHelperGestureListener());
}
//處理事件攔截
@Override
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
mGestureDetector.onTouchEvent(e);
return false;
}
//處理點(diǎn)擊事件
@Override
public void onTouchEvent(RecyclerView rv, MotionEvent e) {
mGestureDetector.onTouchEvent(e);
}
//處理事件沖突把还,不用管
@Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
}
//OnGestureListener主要回調(diào)各種單擊事件实蓬,而OnDoubleTapListener回調(diào)各種雙擊事件
//sdk 還提供了一個(gè)外部類SimpleOnGestureListener,這個(gè)類實(shí)現(xiàn)了上面兩個(gè)接口的所有方法吊履。
// 但全都是空實(shí)現(xiàn)瞳秽,函數(shù)體里什么也沒寫,其中就是把上面兩個(gè)接口合并一下率翅,給出默認(rèn)的空實(shí)現(xiàn)练俐。
// 這樣繼承SimpleOnGestureListener的時(shí)候就不用實(shí)現(xiàn)每一個(gè)方法了。
private class ItemTouchHelperGestureListener extends GestureDetector.SimpleOnGestureListener {
//單擊
@Override
public boolean onSingleTapConfirmed(MotionEvent e) {
View child = recyclerView.findChildViewUnder(e.getX(), e.getY());
if (child != null) {
RecyclerView.ViewHolder vh = recyclerView.getChildViewHolder(child);
int position = recyclerView.getChildLayoutPosition(child);
onItemClick(vh,position);
}
return true;
}
//雙擊
public boolean onDoubleTap(MotionEvent e){
View child = recyclerView.findChildViewUnder(e.getX(), e.getY());
if (child != null) {
RecyclerView.ViewHolder vh = recyclerView.getChildViewHolder(child);
int position = recyclerView.getChildLayoutPosition(child);
onItemDoubleClick(vh,position);
}
return true;
}
//長按
public void onLongPress(MotionEvent e){
View child = recyclerView.findChildViewUnder(e.getX(), e.getY());
if (child != null) {
RecyclerView.ViewHolder vh = recyclerView.getChildViewHolder(child);
int position = recyclerView.getChildLayoutPosition(child);
onItemLongClick(vh, position);
}
}
}
public abstract void onItemClick(RecyclerView.ViewHolder vh,int position);
public abstract void onItemDoubleClick(RecyclerView.ViewHolder vh, int position);
public abstract void onItemLongClick(RecyclerView.ViewHolder vh, int position);
}
這段代碼很長冕臭,我們分析一下大概流程:
- 首先是自定義一個(gè)抽象類偶OnRecyclerItemClickListener實(shí)現(xiàn)接口RecyclerView.onItemTouchListener腺晾,并實(shí)例化手勢檢測對象和RecyclerView對象。
- 接著是一個(gè)構(gòu)造器辜贵,下面的三個(gè)方法一個(gè)處理事件攔截悯蝉,一個(gè)處理事件點(diǎn)擊,一個(gè)處理事件沖突托慨,都寫了注釋鼻由,相信了解事件分發(fā)的同學(xué)一定不陌生。
- 往下走是一個(gè)私有內(nèi)部類ItemTouchHelperGestureListener繼承了GestureDetector.SimpleOnGestureListener厚棵,注釋上也寫明了這個(gè)類可以實(shí)現(xiàn)OnGestureListener和OnDoubleTapListener兩個(gè)接口的全部方法蕉世,那我們就來看看這兩個(gè)接口分別實(shí)現(xiàn)了什么方法吧
OnGestureListener的回調(diào)接口如下:
//用戶按下屏幕就會(huì)觸發(fā)
public boolean onDown(MotionEvent e);
//如果是按下的時(shí)間超過瞬間,而且在按下的時(shí)候沒有松開或者是拖動(dòng)的婆硬,那么onShowPress就會(huì)執(zhí)行
public void onShowPress(MotionEvent e);
//一次單獨(dú)的輕擊抬起操作,也就是輕擊一下屏幕狠轻,就是普通點(diǎn)擊事件
public boolean onSingleTapUp(MotionEvent e);
//在屏幕上拖動(dòng)事件
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY);
//長按觸摸屏,超過一定時(shí)長彬犯,就會(huì)觸發(fā)這個(gè)事件
public void onLongPress(MotionEvent e);
//滑屏向楼,用戶按下觸摸屏查吊、快速移動(dòng)后松開
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY);
OnDoubleTapListener的回調(diào)接口如下:
//單擊事件。用來判定該次點(diǎn)擊是SingleTap而不是DoubleTap湖蜕,
//如果連續(xù)點(diǎn)擊兩次就是DoubleTap手勢逻卖,如果只點(diǎn)擊一次,
//系統(tǒng)等待一段時(shí)間后沒有收到第二次點(diǎn)擊則判定該次點(diǎn)擊為SingleTap而不是DoubleTap昭抒,
//然后觸發(fā)SingleTapConfirmed事件
public boolean onSingleTapConfirmed(MotionEvent e);
//雙擊事件
public boolean onDoubleTap(MotionEvent e);
//雙擊間隔中發(fā)生的動(dòng)作箭阶。指觸發(fā)onDoubleTap以后,在雙擊之間發(fā)生的其它動(dòng)作
public boolean onDoubleTapEvent(MotionEvent e);
- 關(guān)于分析我們一會(huì)再說戈鲁,接上步驟仇参,最后在你想要設(shè)置點(diǎn)擊的頁面添加如下代碼
//我自己實(shí)例化的對象,讀者按需修改
private RecyclerView recyclerViewForNews;
//添加點(diǎn)擊事件
recyclerViewForNews.addOnItemTouchListener(new OnRecyclerItemClickListener(recyclerViewForNews){
@Override
public void onItemClick(RecyclerView.ViewHolder vh,int position) {
//item點(diǎn)擊事件
String url = mUrlList.get(position);
// 跳轉(zhuǎn)傳值
Intent intent = new Intent(getActivity(), NewsActivity.class);
intent.putExtra("url", url);
startActivity(intent);
}
public void onItemDoubleClick(RecyclerView.ViewHolder vh, int position){
//item雙擊事件
String url = mUrlList.get(position);
// 跳轉(zhuǎn)傳值
Intent intent = new Intent(getActivity(), NewsActivity.class);
intent.putExtra("url", url);
startActivity(intent);
}
public void onItemLongClick(RecyclerView.ViewHolder vh, int position){
//item長按事件
String url = mUrlList.get(position);
// 跳轉(zhuǎn)傳值
Intent intent = new Intent(getActivity(), NewsActivity.class);
intent.putExtra("url", url);
startActivity(intent);
}
});
簡單說明一下婆殿,RecyclerView的對象是我自己設(shè)置的诈乒,僅服務(wù)于自己的項(xiàng)目,包括三個(gè)方法里的所有邏輯都是為了我自己項(xiàng)目中所需要的跳轉(zhuǎn)婆芦,讀者按需修改即可怕磨。
- 分析:為什么這篇文章的標(biāo)題叫做“反思與修改”呢?一般在別的文章中僅僅讓你重寫幾個(gè)方法消约,設(shè)置一下xml文件肠鲫,就完事了。但是細(xì)心的你一定會(huì)發(fā)現(xiàn)public boolean onSingleTapUp(MotionEvent e)和public boolean onSingleTapConfirmed(MotionEvent e)方法非常相似或粮,只差了一個(gè)Confirmed导饲,但是應(yīng)用在項(xiàng)目中效果是完全不同的。
public boolean onSingleTapUp(MotionEvent e)應(yīng)用在我們的項(xiàng)目中的話氯材,假設(shè)你點(diǎn)擊item時(shí)非常輕渣锦,幾乎不怎么用力觸摸屏幕,你會(huì)發(fā)現(xiàn)有時(shí)我們上述設(shè)置的水波紋效果是無法顯示出來的氢哮,這明顯與我們的需求不符袋毙。況且經(jīng)過筆者本身的試驗(yàn),點(diǎn)擊一些有水波紋效果的app無論是輕是重都會(huì)顯示出水波紋效果冗尤。
public boolean onSingleTapConfirmed(MotionEvent e)應(yīng)用于我們的項(xiàng)目中的話听盖,由于需要一段時(shí)間確認(rèn)你觸摸了屏幕幾次,所以無論你點(diǎn)擊屏幕是輕是重都會(huì)顯示出我們的水波紋效果裂七,于是我們在上述代碼中選擇重寫這個(gè)方法皆看。
接下來重寫的兩個(gè)方法就非常符合邏輯了,假如用戶真的點(diǎn)了兩次呢碍讯?或者假如用戶長按不放呢悬蔽?于是我們選擇重寫public boolean onDoubleTap(MotionEvent e)和public void onLongPress(MotionEvent e)方法,也就完成了基本的點(diǎn)擊捉兴,雙擊蝎困,長按都可以顯示出水波紋效果的基本需求了。
歡迎指正倍啥。