自定义组件之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。

相关文章
相关标签/搜索