android基于SwipeRefreshLayout實(shí)現(xiàn)類QQ的側(cè)滑刪除
前言
記得去年做一個(gè)聊天項(xiàng)目需要實(shí)現(xiàn)類似QQ的下拉刷新并且有側(cè)滑刪除的功能,在網(wǎng)上找了很久都沒有QQ的完美,多多少少存在各種的問題,最后把下拉刷新的功能去掉后,只保留了側(cè)滑刪除的功能才找到個(gè)完美的?;厝ズ蠛鸵慌笥延懻?,朋友找了以后說了一句,這種功能沒有8K以上的是寫不出來的(⊙﹏⊙)b?,F(xiàn)在看來當(dāng)時(shí)真的太天真了。而如今自己也沒有8K還是嘗試去寫寫,順便當(dāng)練練手。
還是效果圖優(yōu)先

效果圖當(dāng)中看不出來事件滑動(dòng)的解決方案(或者是我不會(huì)如何錄制手指在屏幕上滑動(dòng)方向和點(diǎn)擊,知道的大神請(qǐng)告訴下,謝謝)具體的可以去下方的GitHub上下載看。
還是先看怎么用
首先傳送門地址 SwipeMenuRefreshView
此項(xiàng)目中引用了一個(gè)側(cè)滑菜單的庫具體的地址 AndroidSwipeLayout (這是一個(gè)非常強(qiáng)大的庫可以上下左右的滑動(dòng)展示,具體可以去其GitHub上了解)
引用
compile 'com.nero.ren:SwipeMenu:1.2.0'
布局文件
<ren.widget.refresh.SwipeMenuRefreshView
android:id="@+id/refresh"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
android:id="@+id/listview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" />
</ren.widget.refresh.SwipeMenuRefreshView>
Item布局文件
<com.daimajia.swipe.SwipeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="80dp"
app:clickToClose="true">
//側(cè)滑出來的布局
<LinearLayout
android:id="@+id/bottom_wrapper_2"
android:layout_width="wrap_content"
android:layout_height="80dp"
android:tag="Bottom4">
<TextView
android:id="@+id/top"
android:layout_width="70dp"
android:layout_height="match_parent"
android:background="#cfcfcf"
android:gravity="center"
android:text="置頂" />
<TextView
android:id="@+id/noread"
android:layout_width="100dp"
android:layout_height="match_parent"
android:background="#ffa500"
android:gravity="center"
android:text="標(biāo)記未讀" />
<TextView
android:id="@+id/delete"
android:layout_width="70dp"
android:layout_height="match_parent"
android:background="#FF0000"
android:gravity="center"
android:text="刪除" />
</LinearLayout>
//默認(rèn)展示的布局
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="80dp">
<TextView
android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:text="aaaaa"
android:textSize="18sp" />
</RelativeLayout>
</com.daimajia.swipe.SwipeLayout>
具體實(shí)現(xiàn)
1、實(shí)現(xiàn)思路
思路其實(shí)也很簡單就是在實(shí)現(xiàn)自定義SwipeRefreshLayout重寫onInterceptTouchEvent根據(jù)左右還是上下滑動(dòng)進(jìn)行事件的攔截和下發(fā)
2、判斷滑動(dòng)方向
主要根據(jù)用戶滑動(dòng)的夾角來判斷是上下滑動(dòng)還是左右滑動(dòng)。判斷后設(shè)置一個(gè)標(biāo)記,下一次滑動(dòng)的時(shí)候如果上下滑動(dòng)(Listiview)的滑動(dòng)那么就調(diào)用父類的的onInterceptTouchEvent方法正?;瑒?dòng),此時(shí)事件在到達(dá)側(cè)滑菜單的時(shí)候已經(jīng)被消費(fèi)了所有不會(huì)滑出側(cè)滑菜單。如果是左右滑動(dòng)則return false 不攔截事件交由子控件處理,這是左右滑動(dòng)Listview是不會(huì)做消費(fèi)所以會(huì)到達(dá)讓側(cè)滑菜單來處理。
case MotionEvent.ACTION_DOWN:
pressX = (int) ev.getX(); //記錄按下的X坐標(biāo)
pressY = (int) ev.getY();//記錄按下的Y坐標(biāo)
break;
case MotionEvent.ACTION_MOVE:
//判斷滑動(dòng)距離是否是正常的滑動(dòng)
if (Math.abs(ev.getY() - pressY) < touchSlop && Math.abs(ev.getX() - pressX) < touchSlop)
return super.onInterceptTouchEvent(ev);
//如果用戶是滑動(dòng)listview則交由父類onInterceptTouchEvent處理
if (interceptStatus == REFRESH_STATUS)
return super.onInterceptTouchEvent(ev);
//用戶如果是滑出SwipeLayout則不攔截時(shí)間交由SwipeLayout處理
else if (interceptStatus == SWIPE_MENU_OPEN)
return false;
//根據(jù)滑動(dòng)角度判斷用戶是滑出SwipeLayout還是Listview
double angle = Math.atan((ev.getY() - pressY) / (ev.getX() - pressX));//計(jì)算滑動(dòng)的角度
int degrees = (int) Math.toDegrees(angle);
degrees = Math.abs(degrees);
//大于45度則判斷為Listview滑動(dòng)
if (degrees > 45) {
Log.d(TAG, "正在上下滑動(dòng)");
//如果當(dāng)前是SwipeLayout內(nèi)點(diǎn)擊的事件序列則不允許滑動(dòng)
if (interceptStatus == SWIPE_MENU_CLOSE)
return true;
interceptStatus = REFRESH_STATUS; //標(biāo)記為Listview滑動(dòng)
return super.onInterceptTouchEvent(ev);
} else { //小于45度則判斷為SwipeLayout滑動(dòng)
Log.e(TAG, "正在左右滑動(dòng)");
currentSwipeLayout = getCurrentSwipeLayout(); //獲取當(dāng)前滑出的SwipeLayout
interceptStatus = SWIPE_MENU_OPEN; //標(biāo)記為SwipeLayout滑動(dòng)
return false;
}
3點(diǎn)擊事件處理
點(diǎn)擊事件分為幾種情況
1.用戶普通的item點(diǎn)擊:此情況下不做任何處理
2.當(dāng)滑出側(cè)滑菜單欄以后,點(diǎn)擊其他的item時(shí),這是判斷是否是當(dāng)前滑出的側(cè)滑菜單的position如若不是在down事件的時(shí)候變將其關(guān)閉并且 return true當(dāng)在onInterceptTouchEvent中retur true 后此后所有的事件,直到手指抬起時(shí)的所有操作都交由自身的onTouchEvent處理而在onTouchEvent中也不做任何操作直接攔截即可達(dá)到需要的效果
判斷是否是點(diǎn)擊的當(dāng)前滑出菜單的Item
if (currentSwipeLayout != null && currentSwipeLayout.getOpenStatus() != SwipeLayout.Status.Close) { //如果當(dāng)前有打開或者正在打開的SwipeLayout
Log.d(TAG, "currentSwipeLayout.getOpenStatus() " + currentSwipeLayout.getOpenStatus());
interceptStatus = SWIPE_MENU_CLOSE;//此次用戶操作為關(guān)閉SwipeLayout
Rect rect = new Rect();
currentSwipeLayout.getHitRect(rect);
//判斷當(dāng)前點(diǎn)擊X Y坐標(biāo)是否在當(dāng)前SwipeLayout中,即用戶是否點(diǎn)擊這個(gè)SwipeLayout,有就不攔截時(shí)間交由SwipeLayout自己處理
if (rect.contains(pressX, pressY)) {
return false;
}
onInterceptTouchEvent中down事件
case MotionEvent.ACTION_DOWN:
//如果沒有就關(guān)閉并且攔截此時(shí)間順序中所有事件
currentSwipeLayout.close();
return true;
onTouchEvent中的move事件
case MotionEvent.ACTION_MOVE:
if (interceptStatus == SWIPE_MENU_CLOSE)//如果是SwipeLayout關(guān)閉事件序列則攔截事件
return true;
3.當(dāng)用戶點(diǎn)擊的是當(dāng)前側(cè)滑菜單,這里又有兩種情況如果點(diǎn)擊的范圍不是側(cè)滑菜單的范圍則return false這時(shí)如果抬手時(shí)是在側(cè)滑菜單的范圍內(nèi)將會(huì)觸發(fā)點(diǎn)擊事件(如果有)如果沒有在此范圍則關(guān)閉側(cè)滑菜單。如果此期間有move事件即用戶有滑動(dòng)會(huì)進(jìn)入之前說的move判斷邏輯。
簡而言之就是按下的范圍是滑出側(cè)滑菜單的Item則不攔截交由兒子你說了算,如果有滑動(dòng)就由父類進(jìn)行開始說的判斷,然后進(jìn)行相應(yīng)邏輯,此時(shí)就不是兒子說了算。
//判斷當(dāng)前點(diǎn)擊X Y坐標(biāo)是否在當(dāng)前SwipeLayout中,即用戶是否點(diǎn)擊這個(gè)SwipeLayout,有就不攔截時(shí)間交由SwipeLayout自己處理
if (rect.contains(pressX, pressY)) {
return false;
}
//如果沒有就關(guān)閉并且攔截此時(shí)間順序中所有事件
currentSwipeLayout.close();
return true;
結(jié)語
此文設(shè)計(jì)事件分發(fā)的許多知識(shí),加上這幾個(gè)控件都有自己的方法所有有許多內(nèi)容不太容易說的清楚(甚至自己都不一定弄的很清楚)加之本人表達(dá)能力不算好,所以可能云里霧里的,如果有興趣的朋友們可以去GitHub下載源碼看看。最后在給一次地址 SwipeMenuRefreshView
以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Android SwipeRefreshLayout超詳細(xì)講解
- Android 使用SwipeRefreshLayout控件仿抖音做的視頻下拉刷新效果
- Android SwipeRefreshLayout仿抖音app靜態(tài)刷新
- android使用SwipeRefreshLayout實(shí)現(xiàn)ListView下拉刷新上拉加載
- Android 中SwipeRefreshLayout與ViewPager滑動(dòng)事件沖突解決方法
- android中SwipeRefresh實(shí)現(xiàn)各種上拉,下拉刷新示例
- Android使用Item Swipemenulistview實(shí)現(xiàn)仿QQ側(cè)滑刪除功能
- Android實(shí)現(xiàn)SwipeRefreshLayout首次進(jìn)入自動(dòng)刷新
- Android 中 Swipe、Scroll 和 Fling 的區(qū)別解析
相關(guān)文章
往Android系統(tǒng)中添加服務(wù)的方法教程
最近因?yàn)槠脚_(tái)升級(jí),需要在系統(tǒng)中添加一些服務(wù),所以將整個(gè)過程總結(jié)一下,下面這篇文章主要給大家介紹了往Android系統(tǒng)中添加服務(wù)的方法教程,需要的朋友可以參考借鑒,下面來一起看看吧。2017-05-05
Android 防止過快(多次)點(diǎn)擊的實(shí)現(xiàn)方法
很多用戶經(jīng)常會(huì)出現(xiàn)過快且多次點(diǎn)擊同一按鈕的情況,本篇文章主要介紹了Android 防止過快點(diǎn)擊的實(shí)現(xiàn)方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-05-05
android教程之textview解析帶圖片的html示例
本文介紹的示例適用于android中需要解析帶圖片的htlm數(shù)據(jù),需要的朋友可以參考下2014-02-02
Android SharedPreferences數(shù)據(jù)存儲(chǔ)詳解
SharedPreferences是安卓平臺(tái)上一個(gè)輕量級(jí)的存儲(chǔ)類,用來保存應(yīng)用的一些常用配置,比如Activity狀態(tài),Activity暫停時(shí),將此activity的狀態(tài)保存到SharedPereferences中;當(dāng)Activity重載,系統(tǒng)回調(diào)方法onSaveInstanceState時(shí),再從SharedPreferences中將值取出2022-11-11
Android對(duì)EditTex的圖片實(shí)現(xiàn)監(jiān)聽
這篇文章主要為大家詳細(xì)介紹了Android如何對(duì)EditTex的圖片實(shí)現(xiàn)監(jiān)聽,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-10-10
android使用Jsoup 抓取頁面的數(shù)據(jù)
本篇文章主要介紹了android使用Jsoup 抓取頁面的數(shù)據(jù),jsoup 是一款Java的HTML解析器,有需要的朋友可以了解一下。2016-11-11

