Material Design 實戰 之第五彈 —— 下拉重新整理(SwipeRefreshLayout)
本模組共有六篇文章,參考郭神的《第一行程式碼》,對Material Design的學習做一個詳細的筆記,大家可以一起交流一下:
- ofollow,noindex">Material Design 實戰 之第一彈——Toolbar(即本文)
- Material Design 實戰 之第二彈——滑動選單詳解&實戰
- Material Design 實戰 之第三彈—— 懸浮按鈕和可互動提示(FloatingActionButton & Snackbar & CoordinatorLayout)
- Material Design 實戰 之第四彈 —— 卡片佈局以及靈動的標題欄(CardView & AppBarLayout)
- Material Design 實戰 之第五彈 —— 下拉重新整理(SwipeRefreshLayout)
- Material Design 實戰 之 第六彈 —— 可摺疊式標題欄(CollapsingToolbarLayout) & 系統差異型的功能實現(充分利用系統狀態列空間)
引子:

文章提要與總結
SwipeRefreshLayout 1.SwipeRefreshLayout即是實現下拉重新整理功能的核心類,它由support-v4庫提供的; 2.把想要實現下拉重新整理功能的控制元件放置到SwipeRefreshLayout裡邊,即可迅速讓這個控制元件支援下拉重新整理了; 3.接下來在對應的java程式碼中處理具體的重新整理邏輯: 3.1 例項化SwipeRefreshLayout; 3.2 呼叫setcolorSchemeResources()方法來設定下拉重新整理進度條的顏色; 3.3 呼叫setonRefreshListener()方法設定一個下拉重新整理的監聽器, 傳入一個SwipeRefreshLayout.OnRefreshListener()並重寫onRefresh()來處理具體的重新整理邏輯;
3.4 重新整理邏輯使用中可以使用如下多執行緒結構: new Thread(new Runnable() { @Override public void run() { try{ }catch (InterruptedException e){ e.printStackTrace(); } runOnUiThread(new Runnable() { @Override public void run() { } }); } }).start();
其中try中書寫耗時操作,然後在 runOnUiThread() 中的 run() 中獲取到資料, 並adapter.notifyDataSetChanged()呼叫重新整理資料; 最後呼叫swipeRefreshLayout的setRefreshing()並傳入false,表示重新整理事件結束同時隱藏重新整理進度條;
正文
SwipeRefreshLayout
SwipeRefreshLayout即是實現下拉重新整理功能的核心類,它由support-v4庫提供的。
把想要實現下拉重新整理功能的控制元件放置到SwipeRefreshLayout裡邊,即可迅速讓這個控制元件支援下拉重新整理了。
而在這裡的實戰專案(MaterialTest)中,應該支援下拉重新整理功能的控制元件是RecyclerView。
下面直接開始使用它。修改activity-main.xml:

<?xml version="1.0" encoding="utf-8"?> <android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/drawer_layout" android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.design.widget.CoordinatorLayout android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.design.widget.AppBarLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="?attr/colorPrimary" android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" app:popupTheme="@style/ThemeOverlay.AppCompat.Light" app:layout_scrollFlags="scroll|enterAlways|snap"/> </android.support.design.widget.AppBarLayout> <android.support.v4.widget.SwipeRefreshLayout android:id="@+id/swipe_refresh" android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior = "@string/appbar_scrolling_view_behavior"> <android.support.v7.widget.RecyclerView android:id="@+id/recycler_view" android:layout_width="match_parent" android:layout_height="match_parent" /> </android.support.v4.widget.SwipeRefreshLayout> <android.support.design.widget.FloatingActionButton android:id="@+id/fab" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom|end" android:layout_margin="16dp" android:src="@drawable/ic_done" app:elevation="8dp"/> </android.support.design.widget.CoordinatorLayout> <android.support.design.widget.NavigationView android:id="@+id/nav_view" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_gravity="start" app:menu="@menu/nav_menu" app:headerLayout="@layout/nav_header"> </android.support.design.widget.NavigationView> </android.support.v4.widget.DrawerLayout>
這裡在RecyclerView的外面再巢狀一層SwipeRefreshLayout,讓RecyclerView實現下拉重新整理功能。
另注意,
由於RecyclerView現在變成了Swipe-RefreshLayout的子控制元件,
因此之前使用app:layout_behavxor宣告的佈局行為現在也要移到SwipeRefreshLayout中才行。
當然,雖RecyclerView已經支援下拉重新整理功能,但還要在程式碼中處理具體的重新整理邏輯才行。
下面修改MainActivity:



//下拉重新整理 private SwipeRefreshLayout swipeRefresh; ------------------------------------ //下拉重新整理邏輯處理 swipeRefresh = (SwipeRefreshLayout) findViewById(R.id.swipe_refresh); swipeRefresh.setColorSchemeResources(R.color.colorPrimary); swipeRefresh.setOnRefreshListener(new SwipeRefreshLayout. OnRefreshListener(){ @Override public void onRefresh() { refreshFruits(); } }); ------------------------------------ private void refreshFruits(){ new Thread(new Runnable() { @Override public void run() { try{ Thread.sleep(2000); }catch (InterruptedException e){ e.printStackTrace(); } runOnUiThread(new Runnable() { @Override public void run() { initFruits(); adapter.notifyDataSetChanged(); swipeRefresh.setRefreshing(false); } }); } }).start(); }
這裡,
首先例項化SwipeRefreshLayout,
然後呼叫setcolorSchemeResources()方法來設定下拉重新整理進度條的顏色,這裡使用主題中的colorPrimary作為進度條的顏色。
接著呼叫setonRefreshListener()方法設定一個下拉重新整理的監聽器,當觸發了下拉重新整理操作的時候就會回撥這個監聽器的onRefresh()方法,在這個方法中處理具體的重新整理邏輯。(這裡可以類比setOnClickListener理解)
通常onRefresh()方法中應該是去網路上請求最新的資料,然後再將這些資料展示出來。
這裡就不和網路互動了,簡單地寫一個refreshFruits()方法並呼叫它進行本地重新整理操作。
refreshFruits()方法中先是開啟了一個執行緒,然後將執行緒沉睡兩秒鐘,模擬重新整理的等待過程。
因為本地重新整理操作速度非常快,如果不將執行緒沉睡的話,重新整理會即刻結束而看不到重新整理的過程。
沉睡結束後使用run0nUiThread()方法將執行緒切換回主執行緒,
呼叫initFruits()方法重新生成資料,
接著呼叫FruitAdapter的notifyDataSetChanged()通知資料發生了變化並重新整理adapter裡面的資料,
最後呼叫swipeRefreshLayout的setRefreshing()並傳入false,表示重新整理事件結束同時隱藏重新整理進度條。
重新執行一下程式,在螢幕的主介面向下拖動,會出現下拉重新整理的進度條,鬆手後就會自動進行重新整理了,效果如圖:

重新整理中

重新整理後