Android智能下拉刷新框架-SmartRefreshLayout

框架?下拉刷新控件還能框架化?智能又怎么回事?二話不多少先上Demo效果圖,咱們?cè)賮?lái)探個(gè)究竟。

Github 傳送門(mén)
注意:本文僅僅是博客文章,主要用于項(xiàng)目介紹和宣傳,由于發(fā)布時(shí)間關(guān)系,部分內(nèi)容已經(jīng)過(guò)期,詳細(xì)使用文檔請(qǐng)?zhí)D(zhuǎn) github


Demo

下載 APK-Demo

如果手機(jī)上看不到圖片,可以嘗試

項(xiàng)目演示

個(gè)人首頁(yè) 微博列表
餐飲美食 個(gè)人中心

刷新樣式

Delivery DropBox
Refresh-your-delivery Dropbox-Refresh

上面這兩個(gè)是我自己實(shí)現(xiàn)的,下面的是我把github上其它優(yōu)秀的Header進(jìn)行的整理和集合還有優(yōu)化:

BezierRadar BezierCircle
Pull To Refresh Pull Down To Refresh
FlyRefresh Classics
FlyRefresh ClassicsHeader
Phoenix Taurus
Yalantis/Phoenix Yalantis/Taurus
BattleCity HitBlock
FunGame/BattleCity FunGame/HitBlock
WaveSwipe Material
WaveSwipeRefreshLayout MaterialHeader
StoreHouse WaterDrop
CRefreshLayout WaterDrop

框架

如果你看完了效果圖,或許框架的意思應(yīng)該有所了解了~~SmartRefreshLayout對(duì)下拉刷新功能進(jìn)行系統(tǒng)的拆分、組合,主要由四個(gè)部分組成:

  • RefreshLayout 下拉的基本功能,包括布局測(cè)量、滑動(dòng)事件處理、參數(shù)設(shè)定等等
  • RefreshContent 對(duì)不同內(nèi)容的統(tǒng)一封裝,包括判斷是否可滾動(dòng)、回彈判斷、智能識(shí)別
  • RefreshHeader 下拉頭部的實(shí)現(xiàn)和顯示
  • RefreshFooter 上拉底部的實(shí)現(xiàn)和顯示

下面是UML關(guān)系類圖

jpg_uml.jpg

通過(guò)SmartRefreshLayout框架,你可以在一個(gè)穩(wěn)定強(qiáng)大的下拉布局中實(shí)現(xiàn)自己項(xiàng)目需求的 Header ,不用去關(guān)心滑動(dòng)事件處理,不用關(guān)心子控件的回彈和滾動(dòng)邊界,只需關(guān)注自己真正的項(xiàng)目需求Header的樣子和動(dòng)畫(huà)。

特點(diǎn)

這時(shí)你會(huì)問(wèn):網(wǎng)上其他的開(kāi)源下拉控件一樣的可以自定義 Header 和 Footer ,SmartRefreshLayout 和它們比起來(lái)有什么優(yōu)勢(shì)?

變換方式

  • Translate 平行移動(dòng) 特點(diǎn): 最常見(jiàn),HeaderView高度不會(huì)改變,
  • Scale 拉伸形變 特點(diǎn):在下拉和上彈(HeaderView高度改變)時(shí)候,會(huì)自動(dòng)觸發(fā)OnDraw事件
  • FixedFront 固定在前面 特點(diǎn):不會(huì)上下移動(dòng),HeaderView高度不會(huì)改變
  • FixedBehind 固定在后面 特點(diǎn):不會(huì)上下移動(dòng),HeaderView高度不會(huì)改變(類似微信瀏覽器效果)
  • Screen 全屏幕 特點(diǎn):固定在前面,尺寸充滿整個(gè)布局

SmartRefreshLayout 的Header和Footer都有多種變換方式,適應(yīng)不同風(fēng)格的 Header 和 Footer,下面是不同變換方式Header的Demo

FixedBehind 固定在后面Scale 拉伸形變

Screen 全屏幕Translate 平行移動(dòng)

獨(dú)立事件

Header和Footer 可以獨(dú)立的處理手指滑動(dòng)事件來(lái)為動(dòng)畫(huà)提供操作指令,也可以使用RefreshLayout的核心接口來(lái)完成一些不尋常的操作指令。
下面的打磚塊 Header中 ,Header可以獨(dú)立的使用滑動(dòng)事件來(lái)為游戲擋板提供指令,并同時(shí)可以調(diào)用核心接口來(lái)通知RefreshLayout上下滾動(dòng)列表


智能

智能是什么玩意?有什么用?智能主要體現(xiàn) SmartRefreshLayout 對(duì)未知布局的自動(dòng)識(shí)別上,這樣可以讓我們更高效的實(shí)現(xiàn)我們所需的功能,也可以實(shí)現(xiàn)一些非尋常的功能。下面通過(guò)自定義Header嵌套Layout作為內(nèi)容 來(lái)解釋 SmartRefreshLayout 的智能之處。

自定義Header

我們來(lái)看這一下這個(gè)偽代碼例子:

    <SmartRefreshLayout>
        <ClassicsHeader/>
        <TextView/>
        <ClassicsFooter/>
    </SmartRefreshLayout>

在Android Studio 中的預(yù)覽效果圖

對(duì)比代碼和我們預(yù)想的一樣,那我們來(lái)對(duì)代碼做一些改動(dòng),ClassicsHeader換成一個(gè)簡(jiǎn)單的TextView,看看會(huì)發(fā)生什么?

    <SmartRefreshLayout>
        <TextView
            android:layout_width="match_parent"
            android:layout_height="100dp"
            android:gravity="center"
            android:background="#444"
            android:textColor="#fff"
            android:text="看看我會(huì)不會(huì)變成Header"/>
        <TextView/>
        <ClassicsFooter/>
    </SmartRefreshLayout>

在Android Studio 中的預(yù)覽效果圖 和 運(yùn)行效果圖

這時(shí)發(fā)現(xiàn)我們我們替換的 TextView 自動(dòng)就變成了Header,只是它還不會(huì)動(dòng)。要?jiǎng)悠饋?lái)?那么太簡(jiǎn)單啦,網(wǎng)上隨便一搜索就一大堆的 gif 。如這里:拖拖拖 ~~垃機(jī)C4D,類似的我們還可以找到很多,又如:環(huán)游東京30天:GIF版旅行指南

那我們就選擇 環(huán)游東京30天:GIF版旅行指南 中的這張:

image

接著我們來(lái)改代碼:

compile 'pl.droidsonroids.gif:android-gif-drawable:1.2.3'//一個(gè)開(kāi)源gif控件
    <SmartRefreshLayout>
        <pl.droidsonroids.gif.GifImageView
            android:layout_width="match_parent"
            android:layout_height="150dp"
            android:scaleType="centerCrop"
            android:src="@mipmap/gif_header_repast"/>
        <ListView/>
        <ClassicsFooter/>
    </SmartRefreshLayout>

在 Android Studio 中的預(yù)覽效果圖 和 運(yùn)行效果圖

哈哈!一行Java代碼都不用寫(xiě),就完成了一個(gè)自定義的Header

嵌套Layout作為內(nèi)容

如果boos要求在列表的前面固定一個(gè)廣告條怎么辦?這好辦呀,一般我們會(huì)開(kāi)開(kāi)心心的下下這樣的代碼:

<LinearLayout
    android:orientation="vertical">
    <TextView
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:gravity="center"
        android:text="我就是boos要求加上的廣告條啦"/>
    <SmartRefreshLayout>
        <ListView/>
    </SmartRefreshLayout>
</LinearLayout>

但是在運(yùn)行下拉刷新的時(shí)候,我們發(fā)現(xiàn) Header是在廣告條之下的,看著會(huì)別扭~,其實(shí)我們可以試試另一種方式,把廣告條寫(xiě)到 RefreshLayout內(nèi)部,看看會(huì)發(fā)生什么?

<SmartRefreshLayout>
    <LinearLayout
        android:orientation="vertical">
        <TextView
            android:layout_width="match_parent"
            android:layout_height="100dp"
            android:gravity="center"
            android:text="我就是boos要求加上的廣告條啦"/>
        <ListView/>
    </LinearLayout>
</SmartRefreshLayout>

由于偽代碼過(guò)于簡(jiǎn)單,而且運(yùn)行效果過(guò)于丑陋,這里還是貼出在實(shí)際項(xiàng)目中的實(shí)際情況吧~

我們注意看右邊的圖,仔細(xì)觀察手指觸摸的位置和下拉效果??梢钥吹皆?strong>列表已經(jīng)滾動(dòng)到中部時(shí),輕微下拉列表是不會(huì)觸發(fā)刷新的,但是如果是觸摸固定的布局,則可以觸發(fā)下拉。從這里可以看出 SmartRefreshLayout 對(duì)滾動(dòng)邊界的判斷是動(dòng)態(tài)的,智能的!當(dāng)然如果 SmartRefreshLayout 的智能還是不能滿足你,可以通過(guò) setListener 自己實(shí)現(xiàn)滾動(dòng)邊界的判斷,更為準(zhǔn)確!

功能

簡(jiǎn)單的介紹了兩大特點(diǎn)框架和智能,接下來(lái)也說(shuō)說(shuō)SmartRefreshLayout還具有的其他常用功能吧~

  • 支持所有的 View(AbsListView、RecyclerView、WebView....View) 和多層嵌套的 Layout
  • 支持自定義并且已經(jīng)集成了很多炫酷的 Header 和 Footer
  • 支持和ListView的同步滾動(dòng) 和 RecyclerView、AppBarLayout、CoordinatorLayout 的嵌套滾動(dòng) NestedScrolling.
  • 支持在Android Studio Xml 編輯器中預(yù)覽 效果
  • 支持分別在 Default(默認(rèn))、Xml、JavaCode 等三個(gè)地方設(shè)置 Header 和 Footer.
  • 支持自動(dòng)刷新、自動(dòng)上拉加載(自動(dòng)檢測(cè)列表滾動(dòng)到底部,而不用手動(dòng)上拉).
  • 支持通用的刷新監(jiān)聽(tīng)器 OnRefreshListener 和更詳細(xì)的滾動(dòng)監(jiān)聽(tīng) OnMultiPurposeListener.
  • 支持自定義回彈動(dòng)畫(huà)的插值器,實(shí)現(xiàn)各種炫酷的動(dòng)畫(huà)效果.
  • 支持設(shè)置主題來(lái)適配任何場(chǎng)景的App,不會(huì)出現(xiàn)炫酷但很尷尬的情況.
  • 支持設(shè)置多種滑動(dòng)方式來(lái)適配各種效果的Header和Footer:位置平移、尺寸拉伸、背后固定、頂層固定、全屏
  • 支持內(nèi)容尺寸自適應(yīng) Content-wrap_content
  • 支持繼承重寫(xiě)和擴(kuò)展功能,內(nèi)部實(shí)現(xiàn)沒(méi)有 private 方法和字段,繼承之后都可以重寫(xiě)覆蓋
  • 支持越界回彈(Listview、RecyclerView、ScrollView、WebView...View)

使用

簡(jiǎn)單用例

1.在 buld.gradle 中添加依賴

compile 'com.android.support:appcompat-v7:25.3.1'//版本隨意
compile 'com.scwang.smartrefresh:SmartRefreshLayout:1.0.4'
compile 'com.scwang.smartrefresh:SmartRefreshHeader:1.0.4'//沒(méi)有使用特殊Header,可以不加這行

2.在XML布局文件中添加 SmartRefreshLayout

<?xml version="1.0" encoding="utf-8"?>
<com.scwang.smartrefresh.layout.SmartRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/refreshLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <android.support.v7.widget.RecyclerView
        android:id="@+id/recyclerview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:overScrollMode="never"
        android:background="#fff" />
</com.scwang.smartrefresh.layout.SmartRefreshLayout>

3.在 Activity 或者 Fragment 中添加代碼

RefreshLayout refreshLayout = (RefreshLayout)findViewById(R.id.refreshLayout);
refreshLayout.setOnRefreshListener(new OnRefreshListener() {
    @Override
    public void onRefresh(RefreshLayout refreshlayout) {
        refreshlayout.finishRefresh(2000);
    }
});
refreshLayout.setOnLoadmoreListener(new OnLoadmoreListener() {
    @Override
    public void onLoadmore(RefreshLayout refreshlayout) {
        refreshlayout.finishLoadmore(2000);
    }
});

使用指定的 Header 和 Footer

1.方法一 全局設(shè)置

public class App extends Application {
    static {//static 代碼段可以防止內(nèi)存泄露
        //設(shè)置全局的Header構(gòu)建器
        SmartRefreshLayout.setDefaultRefreshHeaderCreater(new DefaultRefreshHeaderCreater() {
                @Override
                public RefreshHeader createRefreshHeader(Context context, RefreshLayout layout) {
                    layout.setPrimaryColorsId(R.color.colorPrimary, android.R.color.white);//全局設(shè)置主題顏色
                    return new ClassicsHeader(context).setSpinnerStyle(SpinnerStyle.Translate);//指定為經(jīng)典Header,默認(rèn)是 貝塞爾雷達(dá)Header
                }
            });
        //設(shè)置全局的Footer構(gòu)建器
        SmartRefreshLayout.setDefaultRefreshFooterCreater(new DefaultRefreshFooterCreater() {
                @Override
                public RefreshFooter createRefreshFooter(Context context, RefreshLayout layout) {
                    //指定為經(jīng)典Footer,默認(rèn)是 BallPulseFooter
                    return new ClassicsFooter(context).setSpinnerStyle(SpinnerStyle.Translate);
                }
            });
    }
}

注意:方法一 設(shè)置的Header和Footer的優(yōu)先級(jí)是最低的,如果同時(shí)還使用了方法二、三,將會(huì)被其他方法取代

2.方法二 XML布局文件指定

    <com.scwang.smartrefresh.layout.SmartRefreshLayout
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:id="@+id/smartLayout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#444444"
        app:srlPrimaryColor="#444444"
        app:srlAccentColor="@android:color/white"
        app:srlEnablePreviewInEditMode="true">
        <!--srlAccentColor srlPrimaryColor 將會(huì)改變 Header 和 Footer 的主題顏色-->
        <!--srlEnablePreviewInEditMode 可以開(kāi)啟和關(guān)閉預(yù)覽功能-->
        <com.scwang.smartrefresh.layout.header.ClassicsHeader
            android:layout_width="match_parent"
            android:layout_height="wrap_content"/>
        <TextView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:padding="@dimen/padding_common"
            android:background="@android:color/white"
            android:text="@string/description_define_in_xml"/>
        <com.scwang.smartrefresh.layout.footer.ClassicsFooter
            android:layout_width="match_parent"
            android:layout_height="wrap_content"/>
    </com.scwang.smartrefresh.layout.SmartRefreshLayout>

注意:方法二 XML設(shè)置的Header和Footer的優(yōu)先級(jí)是中等的,會(huì)被方法三覆蓋。而且使用本方法的時(shí)候,Android Studio 會(huì)有預(yù)覽效果,如下圖:

不過(guò)不用擔(dān)心,只是預(yù)覽效果,運(yùn)行的時(shí)候只有下拉才會(huì)出現(xiàn)~

3.方法三 Java代碼設(shè)置

final RefreshLayout refreshLayout = (RefreshLayout) findViewById(R.id.smartLayout);
//設(shè)置 Header 為 Material風(fēng)格
refreshLayout.setRefreshHeader(new MaterialHeader(this).setShowBezierWave(true));
//設(shè)置 Footer 為 球脈沖
refreshLayout.setRefreshFooter(new BallPulseFooter(this).setSpinnerStyle(SpinnerStyle.Scale));

最后編輯于
?著作權(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)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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