終於忙完了一段時間,如今前段時間寫的一個瀑布流ListView到想法分享下,這個東西是擴展自Listview,當列表內容拉到最後後觸發刷新操做,以便抓取更多到數據。android
先貼下整個代碼,先有個總體到概念,而後再進一步細聊。代碼以下git
1 package cn.bitlove.waterfalllistview.widget; 2 3 import cn.bitlove.waterfalllistview.R; 4 import android.content.Context; 5 import android.util.AttributeSet; 6 import android.view.LayoutInflater; 7 import android.view.View; 8 import android.view.ViewGroup; 9 import android.widget.AbsListView; 10 import android.widget.FrameLayout; 11 import android.widget.AbsListView.OnScrollListener; 12 import android.widget.ListView; 13 14 /** 15 * 瀑布流Listview 16 * */ 17 public class WaterfallListview extends ListView implements OnScrollListener { 18 19 final private String tag="WaterfallListView"; 20 private Context mContext; 21 private LayoutInflater mInflater; 22 final int REFRESH_IDEL=0; //空閒中 23 final int REFRESH_PREPARE=1; //準備刷新 24 final int REFRESH_ING=2; //刷新中 25 final int REFRESH_End=3; //刷新完成 26 private int mRefreshState = REFRESH_IDEL; //刷新狀態 27 private int mScrollState; //滾動狀態 28 29 private FrameLayout mFooterLayout; //ListView 的footer 30 private View mListFoot; //底部刷新區域 31 32 private IOnRefresh mRefreshListener = null; //刷新監聽器 33 public WaterfallListview(Context context) { 34 super(context); 35 } 36 public WaterfallListview(Context context, AttributeSet attrs) { 37 super(context,attrs); 38 init(); 39 } 40 @Override 41 public void onScrollStateChanged(AbsListView view, int scrollState) { 42 mScrollState = scrollState; 43 } 44 45 @Override 46 public void onScroll(AbsListView view, int firstVisibleItem, 47 int visibleItemCount, int totalItemCount) { 48 if(totalItemCount==0 || mScrollState==SCROLL_STATE_IDLE){ 49 return; 50 } 51 //最後一個item 52 int lastItemCount = firstVisibleItem+visibleItemCount; 53 if(lastItemCount==totalItemCount && mRefreshState==REFRESH_IDEL){ 54 prepareRefresh(); 55 doRefresh(); 56 } 57 } 58 59 private void init(){ 60 mContext = getContext(); 61 mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 62 initFooter(); 63 setOnScrollListener(this); 64 } 65 /** 66 * 設置刷新器 67 * */ 68 public void setRefreshListener(IOnRefresh refresher){ 69 mRefreshListener = refresher; 70 } 71 72 /** 73 * 初始化底部刷新內容 74 * */ 75 private void initFooter(){ 76 mListFoot = mInflater.inflate(R.layout.foot_waterfall_listview, null); 77 mFooterLayout = new FrameLayout(mContext); 78 addFooterView(mFooterLayout); 79 } 80 /** 81 * 準備刷新 82 * */ 83 private void prepareRefresh(){ 84 //Log.i(tag,"prepareRefresh"); 85 mRefreshState = REFRESH_PREPARE; 86 ViewGroup vg = (ViewGroup) mListFoot.getParent(); 87 if(vg!=null){ 88 vg.removeView(mListFoot); 89 } 90 91 mFooterLayout.addView(mListFoot); 92 93 if(mRefreshListener!=null){ 94 mRefreshListener.beforeRefresh(); 95 } 96 } 97 /** 98 * 執行刷新 99 * */ 100 private void doRefresh(){ 101 //Log.i(tag,"doRefresh"); 102 mRefreshState=REFRESH_ING; 103 104 if(mRefreshListener!=null){ 105 mRefreshListener.doRefresh(); 106 } 107 108 } 109 /** 110 * 完成刷新 111 * */ 112 public void completeRefresh(){ 113 mRefreshState = REFRESH_IDEL; 114 mFooterLayout.removeAllViews(); 115 } 116 117 public interface IOnRefresh{ 118 public void beforeRefresh(); 119 /** 120 * 執行完doRefresh操做後,必須調用completeRefresh方法來清理刷新狀態 121 * */ 122 public void doRefresh(); 123 } 124 }
爲了完成滑動到底部後觸發刷新事件,爲此給Listview增長了一個底部view,代碼以下github
1 <?xml version="1.0" encoding="utf-8"?> 2 <!-- waterfallListview 底部刷新區域 --> 3 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 4 android:layout_width="match_parent" 5 android:layout_height="match_parent" 6 > 7 8 <TextView 9 android:layout_height="40dp" 10 android:layout_width="match_parent" 11 android:text="加載更多數據..." 12 android:gravity="center" 13 /> 14 </RelativeLayout>
很簡單,只是用來展現一個獲取狀態。ide
除此以外,還增長了一個內部接口,IOnRefresh,表示相關事件,代碼以下所示函數
1 public interface IOnRefresh{ 2 public void beforeRefresh(); 3 /** 4 * 執行完doRefresh操做後,必須調用completeRefresh方法來清理刷新狀態 5 * */ 6 public void doRefresh(); 7 }
這兩個方法的含義根據名字來看就很清楚了,beforeRefresh,在刷新以前調用,讓client有機會作一些事情;doRefresh,真正執行刷新到部分,另外須要注意到時候,當執行完刷新到時候,要掉用下widget的completeRefresh方法來清理刷新狀態,標示真正執行完了刷新操做this
很簡單到一個方法,有兩個主要功能,一是置狀態,二是取消listview底部的view,代碼以下spa
1 public void completeRefresh(){ 2 mRefreshState = REFRESH_IDEL; 3 mFooterLayout.removeAllViews(); 4 }
大致到內容就是以上那些,下面來看下實現的思路。
爲了完成這個功能,增長了一個刷新狀態mRefreshState,這個狀態用來表示當前控件所處到刷新狀態,以便在不一樣狀態下作不一樣處處理,其有如下四個狀態設計
final int REFRESH_IDEL=0; //空閒中
final int REFRESH_PREPARE=1; //準備刷新
final int REFRESH_ING=2; //刷新中
final int REFRESH_End=3; //刷新完成3d
而後整個widget到邏輯就是控制這四個狀態,而後在不一樣到狀態執行不一樣到操做,好比在執行beforeRefresh函數時,此時狀態處於REFRESH_PREPARE,
當執行doRefresh時狀態處於REFRESH_ING,當咱們調用completeRefresh後,狀態改成REFRESH_IDEL,其實當初設計的時候還但願有一個REFRESH_End狀態,可是實現過程當中沒有發現此狀態的用處,暫時爲保留狀態,以便之後擴充用。code
控制狀態,主要是在onScroll函數中操做的,代碼以下
1 @Override 2 public void onScroll(AbsListView view, int firstVisibleItem, 3 int visibleItemCount, int totalItemCount) { 4 if(totalItemCount==0 || mScrollState==SCROLL_STATE_IDLE){ 5 return; 6 } 7 //最後一個item 8 int lastItemCount = firstVisibleItem+visibleItemCount; 9 if(lastItemCount==totalItemCount && mRefreshState==REFRESH_IDEL){ 10 prepareRefresh(); 11 doRefresh(); 12 } 13 }
主要實現思路就是監測最後一個item是否出現。
好了,到此爲止,主要到思路就完了。
這個控件到Demo程序下載地址:https://github.com/xiaoai-opensource/WaterfallListview
有須要到朋友能夠前去下載查看