Material Design 實(shí)戰(zhàn) 之第五彈 —— 下拉刷新(SwipeRefreshLayout)


本模塊共有六篇文章,參考郭神的《第一行代碼》,對(duì)Material Design的學(xué)習(xí)做一個(gè)詳細(xì)的筆記,大家可以一起交流一下:






引子:



文章提要與總結(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ì)更新了。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容