首先講原理: java
ListView 能夠設置一個滾動監聽器 android
android.widget.AbsListView.setOnScrollListener(OnScrollListener l)有個方法
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount)這裏面有三個參數:
而後咱們須要在列表底部增長一個 item 顯示:點擊加載更多 或者 正在加載中請稍後 或者 沒有更多數據了
這個咱們要用到
數組
ListView.addFooterView(View v)
添加了 footView ,footView 就成了列表最後一行,也就說相對於你的總數據增長了一行,全部這裏有一點要注意的地方:
調用這個方法必須在 ListView.SetAdapter() 以前,不然將會影響 Cursor 類適配器 網絡
知道了原理就很簡單了,下面奉上我封裝的 LoaderListView ide
/** * 下拉自動加載的 Listview * * @author Yichou * @建立日期 2013-3-19 16:01:10 * * 2013-6-30 */ public class LoaderListView extends ListView implements OnScrollListener, OnItemClickListener, OnClickListener { public interface LoadNotifyer { public void load(); } public interface OnScrollStateChangedListener { public void onScrollStateChanged(int oldState, int newState); } private LinearLayout footViewLoading, footViewRetry, footViewNomore; private LoadNotifyer loadNotifyer; private int scrollState; private OnScrollStateChangedListener onScrollStateChangedListener; public LoaderListView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(context); } public LoaderListView(Context context, AttributeSet attrs) { super(context, attrs); init(context); } public LoaderListView(Context context) { super(context); init(context); } @Override public void onClick(View v) { if(v.getId() == 0x1001){ //從新加載 setFootviewType(FOOTVIEW_TYPE.LOADING); if(loadNotifyer != null) loadNotifyer.load(); }else if (v.getId() == 0x1002) { setSelection(0); } } private void init(Context context) { footViewLoading = new LinearLayout(context); footViewLoading.setOrientation(LinearLayout.HORIZONTAL); footViewLoading.setGravity(Gravity.CENTER); ProgressBar bar = new ProgressBar(context); TextView textView = new TextView(context); textView.setText("加載中..."); footViewLoading.addView(bar, new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); footViewLoading.addView(textView, new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); footViewRetry = new LinearLayout(context); footViewRetry.setOrientation(LinearLayout.HORIZONTAL); footViewRetry.setGravity(Gravity.CENTER); textView = new TextView(context); textView.setId(0x1001); textView.setGravity(Gravity.CENTER); textView.setText("網絡不給力,請重試 o(︶︿︶)o"); textView.setOnClickListener(this); footViewRetry.addView(textView, new LayoutParams(LayoutParams.WRAP_CONTENT, getFixPx(50))); footViewNomore = new LinearLayout(context); footViewNomore.setOrientation(LinearLayout.HORIZONTAL); footViewNomore.setGravity(Gravity.CENTER); footViewNomore.setId(0x1002); textView = new TextView(context); textView.setText("返回頂部↑"); textView.setGravity(Gravity.CENTER); footViewNomore.setClickable(true); footViewNomore.setOnClickListener(this); footViewNomore.addView(textView, new LayoutParams(LayoutParams.WRAP_CONTENT, getFixPx(50))); setFootviewType(FOOTVIEW_TYPE.LOADING); setOnScrollListener(this); scrollState = SCROLL_STATE_IDLE; super.setOnItemClickListener(this); } public enum FOOTVIEW_TYPE { /** 加載中 */ LOADING, /** 沒有更多了,返回頂部 */ NOMOR, /** 加載失敗重試 */ RETRY, /**無*/ NONE } private View curFootView; public void setFootviewType(FOOTVIEW_TYPE type) { if(curFootView != null && curFootView.getTag() == type) return; if(curFootView != null) removeFooterView(curFootView); switch (type) { case LOADING: curFootView = footViewLoading; break; case NOMOR: curFootView = footViewNomore; break; case RETRY: curFootView = footViewRetry; break; case NONE: return; } addFooterView(curFootView); curFootView.setTag(type); } private View curHeadView; public void setHeadView(View v) { if(curHeadView!=null) return; curHeadView=v; addHeaderView(v); } @Override public void onScrollStateChanged(AbsListView view, int scrollState) { if (scrollState != this.scrollState) { if(onScrollStateChangedListener != null){ onScrollStateChangedListener.onScrollStateChanged(this.scrollState, scrollState); } this.scrollState = scrollState; } } protected int firstVisibleItem, visibleItemCount, totalItemCount; @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { if(totalItemCount < 2 ) //footview 也算 return; // System.out.println("first=" + firstVisibleItem + ",visible=" + visibleItemCount + ",total=" + totalItemCount); if(firstVisibleItem + visibleItemCount >= totalItemCount){ //說明 footView 可見,通知加載更多 if (loadNotifyer != null && (curFootView != footViewNomore)) { loadNotifyer.load(); } } this.firstVisibleItem = firstVisibleItem; this.visibleItemCount = visibleItemCount; this.totalItemCount = totalItemCount; } public int getFirstVisibleItem() { return firstVisibleItem; } public int getVisibleItemCount() { return visibleItemCount; } public int getScrollState() { return scrollState; } public void setLoadNotifyer(LoadNotifyer loadNotifyer) { this.loadNotifyer = loadNotifyer; } public void setOnScrollStateChangedListener(OnScrollStateChangedListener onScrollStateChangedListener) { this.onScrollStateChangedListener = onScrollStateChangedListener; } public int getFixPx(int dp){ float scale=getContext().getResources().getDisplayMetrics().density; return (int)(scale*dp+0.5); } private OnItemClickListener listener; @Override public void setOnItemClickListener(OnItemClickListener listener) { this.listener = listener; // super.setOnItemClickListener(listener); } @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { if(listener==null)return; if(curHeadView != null){ if(position==0)return; listener.onItemClick(parent, view, position-1, id); }else{ listener.onItemClick(parent, view, position, id); } } }
使用很方便,只需調用
LoaderListView.setLoadNotifyer(LoadNotifyer loadNotifyer)
而後每次滑到底部須要加載更多數據的時候,就會回調
LoadNotifyer.load()
而後你在 load() 方法里加載下一頁數據,加載完畢調用
Adapter.notifyDataSetChanged()
列表就展現新數據了! this
此外我這裏面還封裝了一個神奇的功能是設置 FootView 狀態:
這裏有四種狀態: spa
public enum FOOTVIEW_TYPE { /** 加載中 */ LOADING, /** 沒有更多了,返回頂部 */ NOMOR, /** 加載失敗重試 */ RETRY, /**無*/ NONE }在加載下一頁失敗的時候,調用
同理
當你沒有更多數據的時候調用
listView.setFootviewType(FOOTVIEW_TYPE.NOMOR)
列表底部顯示改成 回到頂部 用戶點擊後自動跳到第一行! code
嗯,很好!很強大!必須就頂一個!歡迎拍磚! rem