• 自定义组件之MoreListView


    前言

    本文针对自定义组件进行一些分析。还是那句老话“授之于鱼不如授之以渔”。今天要讲的是一个自定义的可以分页的ListView

    网上都讲了些ListView分页的方法,那么为什么我在这里还需要自己写一个呢?

    ①分页功能是很多时候都需要的;

    ②网上的很多代码和数据绑定在一起的,要使用的话还需要改些东西,更重要的是代码很啰嗦、很糟糕(当然只是个人风格问题,至少我是这么认为);

    ③或者是功能太强大而我们仅仅是需要分页功能,但是又不好分离出来。

    所以写个分页的listview就很有必要了,尤其是可以直接使用的listview

     

    效果图

    说得再多都是苍白无力的理论,先给个效果图看看吧。

     

     

    分析

    这个组件看上去简单,不过需要处理的细节还是挺多的。首先要明确这个组件是做什么的。简单地讲就是做分页显示或分页加载的。那么需要考虑这两个问题:

    1、什么时候需要分页?

    那么什么时候需要分页呢,这个答案是很明朗的。当数据数量不能填满一屏的时候那么就不用分页。在这个组件中我是这么来定分页的:首次加载的数量大于一屏显示数量时那么就认为有分页的可能,滑动到底部就需要“more”这个按钮。

     

    2、何时加载分页信息?

    至于何时进行分页,这是这个组件的关键。理论上是滑动到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。

     

  • 相关阅读:
    Aria2任意文件写入漏洞
    webpack添加node_path不是('webpack' 不是内部或外部命令,也不是可运行的程序或批处理文件?)
    闭包的7种形式
    首页 多级展示
    velocity模板入门
    AngularJs 时间控件
    mybatis按时间条件搜索
    数据结构之线性表(双向循环链表)
    数据结构之线性表(链表)
    数据结构之线性表(顺序表)
  • 原文地址:https://www.cnblogs.com/vanezkw/p/3146174.html
Copyright © 2020-2023  润新知