Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android 仿QQ側滑刪除—一個滿足ListView、RecyclerView以及其他View通用的側滑刪除

Android 仿QQ側滑刪除—一個滿足ListView、RecyclerView以及其他View通用的側滑刪除

編輯:關於Android編程

對於側滑刪除已經是見慣不慣的了,我也一直有寫類似QQ那樣的側滑刪除控件的想法,雖然研究一段時間的自定義View,然對自定義ViewGroup實戰還是較少,並且側滑刪除還要考慮大量的事件分發機制,比如如何處理子控件與父控件之間的滑動沖突以及一系列的down->move..move.. ->up操作等等。童哥剛好寫了這麼一個側滑刪除,使用起來不但簡單方便,更重要的是更加優雅的實現了解耦,也就是說我們不管是使用ListView還是RecyclerView還是其他ViewGroup中的子View都可以使用此方式實現側滑,具體使用方法是:只需要在XML布局文件中用這個自定義側滑刪除類去包裹我們要執行側滑刪除的item即可(比如我們要對ListView實現側滑刪除功能,我們只需要在定義ListView的item布局文件時,用我們的自定義類作為item的根布局即可)

既然已經有輪子了,為啥還要再重復一遍呢?原因很簡單,因為上面已經說過了,首先對ViewGroup實戰偏少,加之對事件分發機制想了解的深入些,剛好童哥的文章中實現的側滑刪除demo中包含了我的知識薄弱點,所以便有了此篇博客,自己跟著敲一遍確實比只看收獲的多。

扯了這麼多,由於童哥的博客中介紹的很詳細了,那麼我就把自己在調試中理解的一些知識以及對事件分發機制大致說一下,因為童哥並沒有主要介紹事件分發這塊

這裡寫圖片描述

主要解決的問題如下:

1 側滑拉出菜單。

2 點擊除了這個item的其他位置,菜單關閉。並加上了屬性動畫,菜單關閉有回彈效果。

3 側滑過程中,不許父控件上下滑動(事件攔截)。

4 多指同時滑動,屏蔽後觸摸的幾根手指。

5 不會同時展開兩個側滑菜單。

6 側滑菜單時 攔截了長按事件。

7 側滑時,攔截了點擊事件

8 通過開關 isLeftSwipe支持左滑右滑

9 判斷手指起始落點,如果距離屬於滑動了,就屏蔽一切點擊事件(和QQ交互一樣)

主要是自定義ViewGroup的知識點,通過重寫onMeasure()方法來告訴父控件需要多大尺寸,在onLayout()方法中確定子View(即:childView)的位置。我們需要來遍歷我們的childView

int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
View childView = getChildAt(i);
if (childView.getVisibility() != GONE) {
//具體的操作邏輯
}
}

下面我們來看下onLayout()方法是如何確定每一個子view的位置的
先把我們的item布局貼出來,方便理解,注意:引用我們自定義ViewGroup包裹布局時要設置android:clickable=”true”這一屬性




    
    
        
        
    

    
@Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        //LogUtils.e(TAG, "onLayout() called with: " + "changed = [" + changed + "], l = [" + l + "], t = [" + t + "], r = [" + r + "], b = [" + b + "]");
        int childCount = getChildCount();
        int left = 0 + getPaddingLeft();
        int right = 0;
        for (int i = 0; i < childCount; i++) {
            View childView = getChildAt(i);
            if (childView.getVisibility() != GONE) {
                if (i == 0) {//第一個子View是內容 寬度設置為全屏
                    childView.layout(left, getPaddingTop(), left + mMaxWidth, getPaddingTop() + childView.getMeasuredHeight());
                    left = left + mMaxWidth;
                } else {
                    if (isLeftSwipe) {
                        childView.layout(left, getPaddingTop(), left + childView.getMeasuredWidth(), getPaddingTop() + childView.getMeasuredHeight());
                        left = left + childView.getMeasuredWidth();
                    } else {
                        childView.layout(right - childView.getMeasuredWidth(), getPaddingTop(), right, getPaddingTop() + childView.getMeasuredHeight());
                        right = right - childView.getMeasuredWidth();
                    }

                }
            }
        }
    }

這裡需要注意的是,我們側滑刪除根布局下有三部分(一個用來顯示ListView數據內容的,一個是置頂,一個是刪除)。所以childCount的值為3,因此,需要判斷,當 i = 0時,拿到的是第一個子view,即用來顯示數據內容的,所以設置它的寬為全屏,所以left = getPaddingLeft(),如果沒有設置左內邊距則left = 0;當 i 的值不為0時,分為左側滑菜單和右側滑菜單,這裡只說左側滑,i 不為0 接著確定第二個子view的位置,由於這三部分是橫向排列的,雖然此時側滑還處於隱藏狀態,但是第二個子view的left肯定是自身的寬 + 第一個子view的寬,從而來確定第二個子view的左邊距位置。第三個childView則依次累加。

側滑時,攔截了點擊事件

增加一個變量存儲scaleTouchSlop,這個值是系統定義的,超過這個值即判斷此次動作是在滑動。我們利用這個值判斷是否處於側滑。

我們知道對於ViewGroup中事件分發包括三部分:dispatchTouchEvent()、onInterceptTouchEvent()、onTouchEvent(),也就是常說的:事件分發、事件攔截、事件處理。
下面我們假設一個場景:
這裡寫圖片描述
當我們點擊中間的view內中的某一點時:<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjxibG9ja3F1b3RlPg0KCTxwPjGhorzZyei2vMrHt7W72MSsyM/WtbXEx+m/9s/Co6zKwrz+t9a3orXEy7PQ8srHtNPJz835z8KjukFjdGl2aXR5tcRkaXNwYXRjaFRvdWNoRXZlbnQoKSZtZGFzaDsmZ3Q7Vmlld0dyb3VwtcRkaXNwYXRjaFRvdWNoRXZlbnQoKSZtZGFzaDsmZ3Q7Vmlld7XEZGlzcGF0Y2hUb3VjaEV2ZW50KCk8YnIgLz4NCgkyoaK82cnotrzKx7e1u9jErMjP1rW1xMfpv/bPwqOsysK8/rSmwO21xMuz0PLKx7TTz8LN+cnPo7pWaWV3tcRvblRvdWNoRXZlbnQoKSZtZGFzaDsmZ3Q7Vmlld0dyb3VwtcRvblRvdWNoRXZlbnQoKSZtZGFzaDsmZ3Q7QWN0aXZpdHm1xG9uVG91Y2hFdmVudCgpPGJyIC8+DQoJM6GiZGlzcGF0Y2hUb3VjaEV2ZW50KCnS1Lywb25Ub3VjaEV2ZW50KCnT0NK7uPa5ss2steO+zcrHo7q1sbe1u9jWtc6qdHJ1Zcqxo6zU8s/7t9G0y7TOysK8/qOssrvU2bSrtd24+MjOus52aWV3PGJyIC8+DQoJNKGiQWN0aXZpdHm1xGRpc3BhdGNoVG91Y2hFdmVudCgpsru53Le1u9h0cnVlu7nKx2ZhbHNltrzKx8/7t9G19MrCvP6jrLe1u9hzdXBlci54eHi1xMqxuvKyxbvht9a3orj4z8LSu7y2Vmlld0dyb3VwtcRkaXNwYXRjaFRvdWNoRXZlbnQoKaOsVmlld0dyb3VwtcRkaXNwYXRjaFRvdWNoRXZlbnQoKbe1u9hmYWxzZcqxo6zU8srCvP672Mvdtb24uMDgKEFjdGl2aXR5KbXEb25Ub3VjaEV2ZW50KCm0psDtoaM8YnIgLz4NCgk1oaJWaWV3R3JvdXC1xGRpc3BhdGNoVG91Y2hFdmVudCgpt7W72HN1cGVyLnh4eMqxo6zKwrz+tKu13bj419S8urXEb25JbnRlcmNlcHRUb3VjaEV2ZW50KCm0psDto6zI57n7b25JbnRlcmNlcHRUb3VjaEV2ZW50KCm3tbvYdHJ1ZaOsse3KvsC5vdijrMi7uvO9u7j419S8urXEb25Ub3VjaEV2ZW50KCm0psDto6hvblRvdWNoRXZlbnQoKbe1u9h0cnVl1PLP+7fRtfTKwrz+o6zLrdKyvdPK1bK7tb20y8rCvP6jrLe1u9hmYWxzZbvy1d9zdXBlci54eHjKsaOs1PK9u7j4uLjA4LXEb25Ub3VjaEV2ZW50KCm0psDtoaOjqaOst7W72GZhbHNlu/LV33N1cGVyLnh4eMqxu+G9q8rCvP69u7j4z8LSu7y2Vmlld7XEZGlzcGF0Y2hUb3VjaEV2ZW50KCm0psDtoaM8YnIgLz4NCgk2oaJWaWV3tcRkaXNwYXRjaFRvdWNoRXZlbnQoKb3TytW1vcrCvP7Wrrrzo6y3tbvY1rXOqmZhbHNlo6zU8rvYy924+Li4wOCjqFZpZXdHcm91cKOptcRvblRvdWNoRXZlbnQoKbSmwO2jrLe1u9jWtc6qc3VwZXIueHh4yrGjrNTyvbu4+NfUvLq1xG9uVG91Y2hFdmVudCgptKbA7aGjb25Ub3VjaEV2ZW50KCm3tbvYdHJ1ZdTyz/u30bX0ysK8/qOsy63Ssr3TytWyu7W9tMvKwrz+o6y3tbvYZmFsc2W78tXfc3VwZXIueHh4yrGjrNTyvbu4+Li4wOC1xG9uVG91Y2hFdmVudCgptKbA7aGjPC9wPg0KPC9ibG9ja3F1b3RlPg0KPGg0IGlkPQ=="上面簡單的介紹了down的情況下activityviewgroupview的事件分發機制有篇文章通過圖文並茂的介紹了事件分發機制推薦給大家圖解-android-事件分發機制">上面簡單的介紹了down的情況下Activity、ViewGroup、View的事件分發機制。有篇文章通過圖文並茂的介紹了事件分發機制,推薦給大家圖解 Android 事件分發機制

由效果圖可以發現,我們的側滑菜單在展開和關閉的時候會有回彈的效果,很炫酷,實現方式是通過屬性動畫實現的,設置了動畫的變化率setInterpolator,展開時設置了:mExpandAnim.setInterpolator(new OvershootInterpolator());關於這幾個屬性動畫變化效果簡單說下:

AccelerateDecelerateInterpolator 在動畫開始與結束的地方速率改變比較慢,在中間的時候加速
AccelerateInterpolator 在動畫開始的地方速率改變比較慢,然後開始加速
AnticipateInterpolator 開始的時候向後然後向前甩
AnticipateOvershootInterpolator 開始的時候向後然後向前甩一定值後返回最後的值
BounceInterpolator 動畫結束的時候彈起
CycleInterpolator 動畫循環播放特定的次數,速率改變沿著正弦曲線
DecelerateInterpolator 在動畫開始的地方快然後慢
LinearInterpolator 以常量速率改變
OvershootInterpolator 向前甩一定值後再回到原來位置

如果你不想設置帶回彈效果,你可以不用設置setInterpolator或者你直接設置mExpandAnim.setInterpolator(new LinearInterpolator()); LinearInterpolator():表示勻速

最後非常感謝你能耐住性子聽我啰嗦半天,有些不懂得,自己可以先下載代碼斷點調試編譯下,就會明白很多。如果想直接使用,那麼請下載源代碼,源代碼隨後奉上,使用起來也相當簡單,在你需要進行側滑刪除的item中用我們的自定義ViewGroup包裹即可。最後,非常感謝原作者的無私奉獻

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved