本模塊共有六篇文章,參考郭神的《第一行代碼》,對(duì)Material Design的學(xué)習(xí)做一個(gè)詳細(xì)的筆記,大家可以一起交流一下:
- Material Design 實(shí)戰(zhàn) 之第一彈——Toolbar(即本文)
- Material Design 實(shí)戰(zhàn) 之第二彈——滑動(dòng)菜單詳解&實(shí)戰(zhàn)
- Material Design 實(shí)戰(zhàn) 之第三彈—— 懸浮按鈕和可交互提示(FloatingActionButton & Snackbar & CoordinatorLayout)
- Material Design 實(shí)戰(zhàn) 之第四彈 —— 卡片布局以及靈動(dòng)的標(biāo)題欄(CardView & AppBarLayout)
- Material Design 實(shí)戰(zhàn) 之第五彈 —— 下拉刷新(SwipeRefreshLayout)
- Material Design 實(shí)戰(zhàn) 之 第六彈 —— 可折疊式標(biāo)題欄(CollapsingToolbarLayout) & 系統(tǒng)差異型的功能實(shí)現(xiàn)(充分利用系統(tǒng)狀態(tài)欄空間)
引子:
文章提要與總結(jié)
SwipeRefreshLayout ?。痵wa?p/
1.SwipeRefreshLayout即是實(shí)現(xiàn)下拉刷新功能的核心類,它由support-v4庫(kù)提供的;
2.把想要實(shí)現(xiàn)下拉刷新功能的控件放置到SwipeRefreshLayout里邊,即可迅速讓這個(gè)控件支持下拉刷新了;
3.接下來(lái)在對(duì)應(yīng)的java代碼中處理具體的刷新邏輯:
3.1 實(shí)例化SwipeRefreshLayout;
3.2 調(diào)用setcolorSchemeResources()方法來(lái)設(shè)置下拉刷新進(jìn)度條的顏色;
3.3 調(diào)用setonRefreshListener()方法設(shè)置一個(gè)下拉刷新的監(jiān)聽器,
傳入一個(gè)SwipeRefreshLayout.OnRefreshListener()并重寫onRefresh()來(lái)處理具體的刷新邏輯;
3.4 刷新邏輯使用中可以使用如下多線程結(jié)構(gòu):
new Thread(new Runnable() {
@Override
public void run() {
try{
}catch (InterruptedException e){
e.printStackTrace();
}
runOnUiThread(new Runnable() {
@Override
public void run() {
}
});
}
}).start();
其中try中書寫耗時(shí)操作,然后在 runOnUiThread() 中的 run() 中獲取到數(shù)據(jù),
并adapter.notifyDataSetChanged()調(diào)用刷新數(shù)據(jù);
最后調(diào)用swipeRefreshLayout的setRefreshing()并傳入false,表示刷新事件結(jié)束同時(shí)隱藏刷新進(jìn)度條;
效果圖:
正文
SwipeRefreshLayout
(英 [swa?p])
SwipeRefreshLayout即是實(shí)現(xiàn)下拉刷新功能的核心類,它由support-v4庫(kù)提供的。
把想要實(shí)現(xiàn)下拉刷新功能的控件放置到SwipeRefreshLayout里邊,即可迅速讓這個(gè)控件支持下拉刷新了。
而在這里的實(shí)戰(zhàn)項(xiàng)目(MaterialTest)中,應(yīng)該支持下拉刷新功能的控件是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實(shí)現(xiàn)下拉刷新功能。
另注意,
由于RecyclerView現(xiàn)在變成了Swipe-RefreshLayout的子控件,
因此之前使用app:layout_behavxor聲明的布局行為現(xiàn)在也要移到SwipeRefreshLayout中才行。
當(dāng)然,雖RecyclerView已經(jīng)支持下拉刷新功能,但還要在代碼中處理具體的刷新邏輯才行。
下面修改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();
}
這里,
首先實(shí)例化SwipeRefreshLayout,
然后調(diào)用setcolorSchemeResources()方法來(lái)設(shè)置下拉刷新進(jìn)度條的顏色,這里使用主題中的colorPrimary作為進(jìn)度條的顏色。
接著調(diào)用setonRefreshListener()方法設(shè)置一個(gè)下拉刷新的監(jiān)聽器,當(dāng)觸發(fā)了下拉刷新操作的時(shí)候就會(huì)回調(diào)這個(gè)監(jiān)聽器的onRefresh()方法,在這個(gè)方法中處理具體的刷新邏輯。(這里可以類比setOnClickListener理解)
通常onRefresh()方法中應(yīng)該是去網(wǎng)絡(luò)上請(qǐng)求最新的數(shù)據(jù),然后再將這些數(shù)據(jù)展示出來(lái)。
這里就不和網(wǎng)絡(luò)交互了,簡(jiǎn)單地寫一個(gè)refreshFruits()方法并調(diào)用它進(jìn)行本地刷新操作。
refreshFruits()方法中先是開啟了一個(gè)線程,然后將線程沉睡兩秒鐘,模擬刷新的等待過程。
因?yàn)楸镜厮⑿虏僮魉俣确浅??,如果不將線程沉睡的話,刷新會(huì)即刻結(jié)束而看不到刷新的過程。
沉睡結(jié)束后使用run0nUiThread()方法將線程切換回主線程,
調(diào)用initFruits()方法重新生成數(shù)據(jù),
接著調(diào)用FruitAdapter的notifyDataSetChanged()通知數(shù)據(jù)發(fā)生了變化并刷新adapter里面的數(shù)據(jù),
最后調(diào)用swipeRefreshLayout的setRefreshing()并傳入false,表示刷新事件結(jié)束同時(shí)隱藏刷新進(jìn)度條。
重新運(yùn)行一下程序,在屏幕的主界面向下拖動(dòng),會(huì)出現(xiàn)下拉刷新的進(jìn)度條,松手后就會(huì)自動(dòng)進(jìn)行刷新了,效果如圖:


下拉刷新進(jìn)度條會(huì)停留兩秒鐘,隨后自動(dòng)消失,水果列表也會(huì)更新了。

