本模塊共有六篇文章哮兰,參考郭神的《第一行代碼》聚磺,對Material Design的學(xué)習(xí)做一個詳細(xì)的筆記,大家可以一起交流一下:
- Material Design 實戰(zhàn) 之第一彈——Toolbar(即本文)
- Material Design 實戰(zhàn) 之第二彈——滑動菜單詳解&實戰(zhàn)
- Material Design 實戰(zhàn) 之第三彈—— 懸浮按鈕和可交互提示(FloatingActionButton & Snackbar & CoordinatorLayout)
- Material Design 實戰(zhàn) 之第四彈 —— 卡片布局以及靈動的標(biāo)題欄(CardView & AppBarLayout)
- Material Design 實戰(zhàn) 之第五彈 —— 下拉刷新(SwipeRefreshLayout)
- Material Design 實戰(zhàn) 之 第六彈 —— 可折疊式標(biāo)題欄(CollapsingToolbarLayout) & 系統(tǒng)差異型的功能實現(xiàn)(充分利用系統(tǒng)狀態(tài)欄空間)
引子:
文章提要與總結(jié)
SwipeRefreshLayout ÷赘/swa?p/
1.SwipeRefreshLayout即是實現(xiàn)下拉刷新功能的核心類泄伪,它由support-v4庫提供的挫望;
2.把想要實現(xiàn)下拉刷新功能的控件放置到SwipeRefreshLayout里邊立润,即可迅速讓這個控件支持下拉刷新了;
3.接下來在對應(yīng)的java代碼中處理具體的刷新邏輯:
3.1 實例化SwipeRefreshLayout媳板;
3.2 調(diào)用setcolorSchemeResources()方法來設(shè)置下拉刷新進(jìn)度條的顏色桑腮;
3.3 調(diào)用setonRefreshListener()方法設(shè)置一個下拉刷新的監(jiān)聽器,
傳入一個SwipeRefreshLayout.OnRefreshListener()并重寫onRefresh()來處理具體的刷新邏輯蛉幸;
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中書寫耗時操作破讨,然后在 runOnUiThread() 中的 run() 中獲取到數(shù)據(jù),
并adapter.notifyDataSetChanged()調(diào)用刷新數(shù)據(jù)奕纫;
最后調(diào)用swipeRefreshLayout的setRefreshing()并傳入false提陶,表示刷新事件結(jié)束同時隱藏刷新進(jìn)度條;
效果圖:正文
SwipeRefreshLayout
(英 [swa?p])
SwipeRefreshLayout即是實現(xiàn)下拉刷新功能的核心類匹层,它由support-v4庫提供的隙笆。
把想要實現(xiàn)下拉刷新功能的控件放置到SwipeRefreshLayout里邊凭豪,即可迅速讓這個控件支持下拉刷新了天揖。
而在這里的實戰(zhàn)項目(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實現(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();
}
這里担锤,
首先實例化SwipeRefreshLayout蔚晨,
然后調(diào)用setcolorSchemeResources()方法來設(shè)置下拉刷新進(jìn)度條的顏色,這里使用主題中的colorPrimary作為進(jìn)度條的顏色。
接著調(diào)用setonRefreshListener()方法設(shè)置一個下拉刷新的監(jiān)聽器铭腕,當(dāng)觸發(fā)了下拉刷新操作的時候就會回調(diào)這個監(jiān)聽器的onRefresh()方法银择,在這個方法中處理具體的刷新邏輯。(這里可以類比setOnClickListener理解)
通常onRefresh()方法中應(yīng)該是去網(wǎng)絡(luò)上請求最新的數(shù)據(jù)累舷,然后再將這些數(shù)據(jù)展示出來浩考。
這里就不和網(wǎng)絡(luò)交互了,簡單地寫一個refreshFruits()方法并調(diào)用它進(jìn)行本地刷新操作被盈。
refreshFruits()方法中先是開啟了一個線程析孽,然后將線程沉睡兩秒鐘,模擬刷新的等待過程只怎。
因為本地刷新操作速度非惩嗨玻快,如果不將線程沉睡的話身堡,刷新會即刻結(jié)束而看不到刷新的過程邓尤。
沉睡結(jié)束后使用run0nUiThread()方法將線程切換回主線程,
調(diào)用initFruits()方法重新生成數(shù)據(jù)贴谎,
接著調(diào)用FruitAdapter的notifyDataSetChanged()通知數(shù)據(jù)發(fā)生了變化并刷新adapter里面的數(shù)據(jù)汞扎,
最后調(diào)用swipeRefreshLayout的setRefreshing()并傳入false,表示刷新事件結(jié)束同時隱藏刷新進(jìn)度條擅这。
重新運行一下程序澈魄,在屏幕的主界面向下拖動,會出現(xiàn)下拉刷新的進(jìn)度條仲翎,松手后就會自動進(jìn)行刷新了一忱,效果如圖:
下拉刷新進(jìn)度條會停留兩秒鐘,隨后自動消失谭确,水果列表也會更新了帘营。