框架?下拉刷新控件還能框架化?智能又怎麼回事?二話很少少先上Demo效果圖,我們再來探個究竟。html
Github 傳送門
注意:本文僅僅是博客文章,主要用於項目介紹和宣傳,因爲發佈時間關係,部份內容已通過期,詳細使用文檔請跳轉 githubjava
下載 APK-Demoandroid
若是手機上看不到圖片,能夠嘗試git
若是你看完了效果圖,或許框架的意思應該有所瞭解了~~SmartRefreshLayout對下拉刷新功能進行系統的拆分、組合,主要由四個部分組成:github
下面是UML關係類圖segmentfault
經過SmartRefreshLayout框架,你能夠在一個穩定強大的下拉布局中實現本身項目需求的 Header ,不用去關心滑動事件處理,不用關心子控件的回彈和滾動邊界,只需關注本身真正的項目需求Header的樣子和動畫。瀏覽器
這時你會問:網上其餘的開源下拉控件同樣的能夠自定義 Header 和 Footer ,SmartRefreshLayout 和它們比起來有什麼優點?微信
SmartRefreshLayout 的Header和Footer都有多種變換方式,適應不一樣風格的 Header 和 Footer,下面是不一樣變換方式Header的Demoapp
FixedBehind 固定在後面 和 Scale 拉伸形變框架
Screen 全屏幕 和 Translate 平行移動
Header和Footer 能夠獨立的處理手指滑動事件來爲動畫提供操做指令,也可使用RefreshLayout的核心接口來完成一些不尋常的操做指令。
下面的打磚塊 Header中 ,Header能夠獨立的使用滑動事件來爲遊戲擋板提供指令,並同時能夠調用核心接口來通知RefreshLayout上下滾動列表
智能是什麼玩意?有什麼用?智能主要體現 SmartRefreshLayout 對未知佈局的自動識別上,這樣可讓咱們更高效的實現咱們所需的功能,也能夠實現一些非尋常的功能。下面經過自定義Header 和 嵌套Layout做爲內容 來解釋 SmartRefreshLayout 的智能之處。
咱們來看這一下這個僞代碼例子:
<SmartRefreshLayout> <ClassicsHeader/> <TextView/> <ClassicsFooter/> </SmartRefreshLayout>
在Android Studio 中的預覽效果圖
對比代碼和咱們預想的同樣,那咱們來對代碼作一些改動,ClassicsHeader換成一個簡單的TextView,看看會發生什麼?
<SmartRefreshLayout> <TextView android:layout_width="match_parent" android:layout_height="100dp" android:gravity="center" android:background="#444" android:textColor="#fff" android:text="看看我會不會變成Header"/> <TextView/> <ClassicsFooter/> </SmartRefreshLayout>
在Android Studio 中的預覽效果圖 和 運行效果圖
這時發現咱們咱們替換的 TextView 自動就變成了Header,只是它還不會動。要動起來?那麼太簡單啦,網上隨便一搜索就一大堆的 gif 。如這裏:拖拖拖 ~~垃機C4D,相似的咱們還能夠找到不少,又如:環遊東京30天:GIF版旅行指南
那咱們就選擇 環遊東京30天:GIF版旅行指南 中的這張:
接着咱們來改代碼:
compile 'pl.droidsonroids.gif:android-gif-drawable:1.2.3'//一個開源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 中的預覽效果圖 和 運行效果圖
哈哈!一行Java代碼都不用寫,就完成了一個自定義的Header
若是boos要求在列表的前面固定一個廣告條怎麼辦?這好辦呀,通常咱們會開開心心的下下這樣的代碼:
<LinearLayout android:orientation="vertical"> <TextView android:layout_width="match_parent" android:layout_height="100dp" android:gravity="center" android:text="我就是boos要求加上的廣告條啦"/> <SmartRefreshLayout> <ListView/> </SmartRefreshLayout> </LinearLayout>
可是在運行下拉刷新的時候,咱們發現 Header是在廣告條之下的,看着會彆扭~,其實咱們能夠試試另外一種方式,把廣告條寫到 RefreshLayout內部,看看會發生什麼?
<SmartRefreshLayout> <LinearLayout android:orientation="vertical"> <TextView android:layout_width="match_parent" android:layout_height="100dp" android:gravity="center" android:text="我就是boos要求加上的廣告條啦"/> <ListView/> </LinearLayout> </SmartRefreshLayout>
因爲僞代碼過於簡單,並且運行效果過於醜陋,這裏仍是貼出在實際項目中的實際狀況吧~
咱們注意看右邊的圖,仔細觀察手指觸摸的位置和下拉效果。能夠看到在列表已經滾動到中部時,輕微下拉列表是不會觸發刷新的,可是若是是觸摸固定的佈局,則能夠觸發下拉。從這裏能夠看出 SmartRefreshLayout 對滾動邊界的判斷是動態的,智能的!固然若是 SmartRefreshLayout 的智能仍是不能知足你,能夠經過 setListener 本身實現滾動邊界的判斷,更爲準確!
簡單的介紹了兩大特色框架和智能,接下來也說說SmartRefreshLayout還具備的其餘經常使用功能吧~
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'//沒有使用特殊Header,能夠不加這行
<?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>
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); } });
public class App extends Application { static {//static 代碼段能夠防止內存泄露 //設置全局的Header構建器 SmartRefreshLayout.setDefaultRefreshHeaderCreater(new DefaultRefreshHeaderCreater() { @Override public RefreshHeader createRefreshHeader(Context context, RefreshLayout layout) { layout.setPrimaryColorsId(R.color.colorPrimary, android.R.color.white);//全局設置主題顏色 return new ClassicsHeader(context).setSpinnerStyle(SpinnerStyle.Translate);//指定爲經典Header,默認是 貝塞爾雷達Header } }); //設置全局的Footer構建器 SmartRefreshLayout.setDefaultRefreshFooterCreater(new DefaultRefreshFooterCreater() { @Override public RefreshFooter createRefreshFooter(Context context, RefreshLayout layout) { //指定爲經典Footer,默認是 BallPulseFooter return new ClassicsFooter(context).setSpinnerStyle(SpinnerStyle.Translate); } }); } }
注意:方法一 設置的Header和Footer的優先級是最低的,若是同時還使用了方法2、三,將會被其餘方法取代
<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 將會改變 Header 和 Footer 的主題顏色--> <!--srlEnablePreviewInEditMode 能夠開啓和關閉預覽功能--> <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設置的Header和Footer的優先級是中等的,會被方法三覆蓋。並且使用本方法的時候,Android Studio 會有預覽效果,以下圖:
不過不用擔憂,只是預覽效果,運行的時候只有下拉纔會出現~
final RefreshLayout refreshLayout = (RefreshLayout) findViewById(R.id.smartLayout); //設置 Header 爲 Material風格 refreshLayout.setRefreshHeader(new MaterialHeader(this).setShowBezierWave(true)); //設置 Footer 爲 球脈衝 refreshLayout.setRefreshFooter(new BallPulseFooter(this).setSpinnerStyle(SpinnerStyle.Scale));