• 瀑布流ListView


    前言  

      终于忙完了一段时间,现在前段时间写的一个瀑布流ListView到想法分享下,这个东西是扩展自Listview,当列表内容拉到最后后触发刷新操作,以便抓取更多到数据。

    先贴下整个代码,先有个整体到概念,然后再进一步细聊。代码如下

      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 }
    View Code

    底部视图  

      为了完成滑动到底部后触发刷新事件,为此给Listview增加了一个底部view,代码如下

     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>

    很简单,只是用来展示一个获取状态。

    接口

       除此之外,还增加了一个内部接口,IOnRefresh,表示相关事件,代码如下所示

    1 public interface IOnRefresh{
    2         public void beforeRefresh();
    3         /**
    4          * 执行完doRefresh操作后,必须调用completeRefresh方法来清理刷新状态
    5          * */
    6         public void doRefresh();
    7 }

     这两个方法的含义根据名字来看就很清楚了,beforeRefresh,在刷新之前调用,让client有机会做一些事情;doRefresh,真正执行刷新到部分,另外需要注意到时候,当执行完刷新到时候,要掉用下widget的completeRefresh方法来清理刷新状态,标示真正执行完了刷新操作

    completeRefresh方法

    很简单到一个方法,有两个主要功能,一是置状态,二是取消listview底部的view,代码如下

    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;        //刷新完成

    然后整个widget到逻辑就是控制这四个状态,然后在不同到状态执行不同到操作,比如在执行beforeRefresh函数时,此时状态处于REFRESH_PREPARE,
    当执行doRefresh时状态处于REFRESH_ING,当我们调用completeRefresh后,状态改为REFRESH_IDEL,其实当初设计的时候还希望有一个REFRESH_End状态,但是实现过程中没有发现此状态的用处,暂时为保留状态,以便以后扩充用。

    控制状态

    控制状态,主要是在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

      有需要到朋友可以前去下载查看

  • 相关阅读:
    【win10系统问题】远程桌面登录一次后,第二次登录看不到用户名和密码输入框
    如何更改Arcmap里经纬度小数点后面的位数?
    腾讯视频qlv格式转换MP4普通视频方法
    kettle_Spoon 修改共享DB连接带汉字引发的错误
    AutoCAD2015激活码和密钥
    SQL获取本周,上周,本月,上月第一天和最后一天[注:本周从周一到周天]
    SQL语句 不足位数补0
    c# winform 服务器提交了协议冲突. Section=ResponseStatusLine
    java.net.ProtocolException: Server redirected too many times
    MarkDown空格缩进的方法
  • 原文地址:https://www.cnblogs.com/luoaz/p/4237491.html
Copyright © 2020-2023  润新知