自定義組件之MoreListView

前言android

本文針對自定義組件進行一些分析。仍是那句老話「授之於魚不如授之以漁」。今天要講的是一個自定義的能夠分頁的ListViewapp

網上都講了些ListView分頁的方法,那麼爲何我在這裏還須要本身寫一個呢?ide

①分頁功能是不少時候都須要的;佈局

②網上的不少代碼和數據綁定在一塊兒的,要使用的話還須要改些東西,更重要的是代碼很囉嗦、很糟糕(固然只是我的風格問題,至少我是這麼認爲);學習

③或者是功能太強大而咱們僅僅是須要分頁功能,可是又很差分離出來。測試

因此寫個分頁的listview就頗有必要了,尤爲是能夠直接使用的listviewthis

 

效果圖spa

說得再多都是蒼白無力的理論,先給個效果圖看看吧。code

 

 

分析xml

這個組件看上去簡單,不過須要處理的細節仍是挺多的。首先要明確這個組件是作什麼的。簡單地講就是作分頁顯示或分頁加載的。那麼須要考慮這兩個問題:

一、何時須要分頁?

那麼何時須要分頁呢,這個答案是很明朗的。當數據數量不能填滿一屏的時候那麼就不用分頁。在這個組件中我是這麼來定分頁的:首次加載的數量大於一屏顯示數量時那麼就認爲有分頁的可能,滑動到底部就須要「more」這個按鈕。

 

二、什麼時候加載分頁信息?

至於什麼時候進行分頁,這是這個組件的關鍵。理論上是滑動到listview最底部的時候就須要顯示一個「more」按鈕,點擊後進行分頁,可是實際上咱們須要作必定的小改動,也就是提早加載,及尚未滑動到最底部就開始加載。這樣看來主要的問題就落在瞭如何判斷是否滑動到了最底部。這問題在代碼中討論吧。

 

代碼實現

MoreListView 組件代碼:

  1 /***********************************************************
  2  *@description : This class function is you can load more datas
  3  *
  4  * @create author : kwzhang    
  5  * @create date   :2013-6-19
  6  * @modify author :
  7  * @modify date   :
  8  * @contact: vanezkw@163.com
  9  *
 10  **********************************************************/
 11 package com.example.demo;
 12 
 13 import android.content.Context;
 14 import android.util.AttributeSet;
 15 import android.view.View;
 16 import android.widget.AbsListView;
 17 import android.widget.Button;
 18 import android.widget.ListAdapter;
 19 import android.widget.ListView;
 20 
 21 /**
 22  * @author kwzhang
 23  * 
 24  */
 25 public class MoreListView extends ListView {
 26 
 27     private View mFooter;
 28     private LoadingListener mListener;
 29     private boolean mShowMore = true;
 30 
 31     /**
 32      * @param context
 33      * @param attrs
 34      */
 35     public MoreListView(Context context, AttributeSet attrs) {
 36         super(context, attrs);
 37         initFooter(context);
 38     }
 39 
 40     /**
 41      * @param mListener
 42      *            the mListener to set
 43      */
 44     public void setListener(LoadingListener mListener) {
 45         this.mListener = mListener;
 46         setOnScrollListener(innerOnScrollListener);
 47     }
 48 
 49     /**
 50      * @return the mShowMore
 51      */
 52     public boolean isShowMore() {
 53         return mShowMore;
 54     }
 55 
 56     /**
 57      * @param mShowMore
 58      *            the mShowMore to set
 59      */
 60     public void setShowMore(boolean mShowMore) {
 61         this.mShowMore = mShowMore;
 62     }
 63 
 64     /**
 65      * @description :TODO
 66      * @author : kwzhang
 67      * @create :2013-6-19
 68      * @param context
 69      * @return :void
 70      */
 71     protected void initFooter(Context context, View footer) {
 72         if (null == footer) {
 73             Button bt = new Button(context);
 74             bt.setText("More ...");
 75             mFooter = bt;
 76         } else {
 77             mFooter = footer;
 78         }
 79         mFooter.setOnClickListener(new OnClickListener() {
 80             @Override
 81             public void onClick(View v) {
 82                 if (getFooterViewsCount() > 0) {
 83                     removeFooterView(mFooter);
 84                 }
 85                 if (null != mListener) {
 86                     mListener.loadingMore(MoreListView.this);
 87                 }
 88             }
 89         });
 90         addFooterView(mFooter);
 91     }
 92 
 93     private void initFooter(Context context) {
 94         initFooter(context, null);
 95     }
 96 
 97     @Override
 98     public void setAdapter(ListAdapter adapter) {
 99         super.setAdapter(adapter);
100         removeFooterView(mFooter);
101     }
102 
103     /**
104      * @param context
105      * @param attrs
106      * @param defStyle
107      */
108     public MoreListView(Context context, AttributeSet attrs, int defStyle) {
109         super(context, attrs, defStyle);
110         initFooter(context);
111     }
112 
113     /**
114      * @param context
115      */
116     public MoreListView(Context context) {
117         super(context);
118         initFooter(context);
119     }
120 
121     private OnScrollListener innerOnScrollListener = new OnScrollListener() {
122         @Override
123         public void onScrollStateChanged(AbsListView view, int scrollState) {
124             // mLastVisibleItemIndex+1 == getAdapter().getCount()時說明滑動到最底端。
125             // mLastVisibleItemIndex+3 是爲了在倒數第二個就開始預先加載。不過此方法是採樣調用,不必定及時執行。
126             if (mShowMore) {
127                 int count = getAdapter().getCount();
128                 if ((mVisibleItemCount < count) && ((mLastVisibleItemIndex + 3) >= count) && (getFooterViewsCount() == 0)) {
129                     addFooterView(mFooter);
130                 }
131             }
132         }
133 
134         private int mLastVisibleItemIndex;
135         private int mVisibleItemCount = -1;
136 
137         @Override
138         public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
139             mLastVisibleItemIndex = firstVisibleItem + visibleItemCount - 1;
140 
141             mVisibleItemCount = visibleItemCount;
142 
143         }
144     };
145 
146     public static interface LoadingListener {
147         public void loadingMore(View view);
148     }
149 }
View Code

測試Demo Activity:

 

 1 package com.example.demo;
 2 
 3 import android.app.Activity;
 4 import android.os.Bundle;
 5 import android.view.View;
 6 import android.widget.ArrayAdapter;
 7 
 8 public class ActDemo extends Activity implements MoreListView.LoadingListener {
 9 
10     private MoreListView listView;
11     private ArrayAdapter<String> mAdapter;
12 
13     @Override
14     protected void onCreate(Bundle savedInstanceState) {
15         super.onCreate(savedInstanceState);
16         setContentView(R.layout.activity_main);
17         listView = (MoreListView) findViewById(R.id.listview);
18         mAdapter = getAdapter();
19         listView.setAdapter(mAdapter);
20         listView.setListener(this);
21     }
22 
23     private ArrayAdapter<String> getAdapter() {
24         ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1);
25         for (int i = 0; i < 20; i++) {
26             adapter.add("測試數據" + i);
27         }
28         return adapter;
29     }
30 
31     @Override
32     public void loadingMore(View view) {
33         for (int i = 0; i < 10; i++) {
34             mAdapter.add("新數據" + i);
35         }
36         if (mAdapter.getCount() > 60) {
37             listView.setShowMore(false);
38         }
39     }
40 }
View Code

 

測試Demo XML佈局:

<com.example.demo.MoreListView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/listview"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" />
View Code

 

從上面的測試demo中能夠看出使用起來很是方便。

1protected void initFooter(Context context, View footer)方法說明一下。這個方法是給外部提供傳遞view的,這個view就是顯示「more」的那個view,傳null的話就有個默認的Button

2public void setListener(LoadingListener mListener)須要分頁的話就必須調用這個方法。點擊「more」按鈕的時候其實去調用了LoadingListener.loadingMore(View view)方法。你能夠根據須要進行實現。

 

總結

這樣的組件就比較簡單實用,也沒有太複雜的代碼,一看就能懂。咱們須要的不正是這樣簡單的代碼嗎。隨便說一下若是你須要更強的的Listview的話能夠去看看AmazingListView項目。下拉刷新你能夠看看johannilsson-android-pulltorefresh項目

 

PS:對文中有不解之處歡迎交流,有什麼好的建議也能夠留言。留下個QQ學習羣:196761677。

相關文章
相關標籤/搜索