Material Design 實戰 之第五彈 —— 下拉重新整理(SwipeRefreshLayout)
本模組共有六篇文章,參考郭神的《第一行程式碼》,對Material Design的學習做一個詳細的筆記,大家可以一起交流一下:
- 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,表示重新整理事件結束同時隱藏重新整理進度條。
重新執行一下程式,在螢幕的主介面向下拖動,會出現下拉重新整理的進度條,鬆手後就會自動進行重新整理了,效果如圖:
重新整理後
下拉重新整理進度條會停留兩秒鐘,隨後自動消失,水果列表也會更新了。