Adroid 动态加载 ListView 实现

转自 :http://my.oschina.net/edroid/blog/142598

Adroid 动态加载 ListView 实现


摘要:  如今动态加载成为app 必有的功能,本质上我并不需要一次性加载所有东西,尤其是联网加载时候,前几天看到一篇博文讲国外一个开源解决方案,感觉他的做法并不完美于是发表自己的一些拙见!

首先讲原理:

ListView 可以设置一个滚动监听器

1 android.widget.AbsListView.setOnScrollListener(OnScrollListener l)
有个方法


1 public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount)
这里面有三个参数: 
firstVisibleItem:  第一个可见Item在所有Item中的位置(即屏幕上显示的第一行,在你的数据数组中的位置) 
visibleItemCount:  可见Item个数(屏幕内可以显示多少行) 
totalItemCount:  总共有多少行数据 
通过这个3个参数容易想到,如果   firstVisibleItem +   visibleItemCount >=   totalItemCount 不就表明 列表已经滑到了底部么?这个时候就是我们加载数据的时机了!


然后我们需要在列表底部增加一个 item 显示:点击加载更多 或者 正在加载中请稍后 或者 没有更多数据了
这个我们要用到

1 ListView.addFooterView(View v)

添加了 footView ,footView 就成了列表最后一行,也就说相对于你的总数据增加了一行,所有这里有一点要注意的地方:
调用这个方法必须在 ListView.SetAdapter() 之前,否则将会影响 Cursor 类适配器

知道了原理就很简单了,下面奉上我封装的 LoaderListView

001 /**
002  * 下拉自动加载的 Listview
003  *
004  * @author Yichou
005  * @创建日期 2013-3-19 16:01:10
006  *
007  * 2013-6-30
008  */
009 public class LoaderListView extends ListView implements
010         OnScrollListener,
011         OnItemClickListener,
012         OnClickListener {
013     public interface LoadNotifyer {
014         public void load();
015     }
016      
017     public interface OnScrollStateChangedListener {
018         public void onScrollStateChanged(int oldState, int newState);
019     }
020      
021     private LinearLayout footViewLoading, footViewRetry, footViewNomore;
022     private LoadNotifyer loadNotifyer;
023     private int scrollState;
024     private OnScrollStateChangedListener onScrollStateChangedListener;
025      
026  
027     public LoaderListView(Context context, AttributeSet attrs, int defStyle) {
028         super(context, attrs, defStyle);
029         init(context);
030     }
031  
032     public LoaderListView(Context context, AttributeSet attrs) {
033         super(context, attrs);
034         init(context);
035     }
036  
037     public LoaderListView(Context context) {
038         super(context);
039         init(context);
040     }
041      
042     @Override
043     public void onClick(View v) {
044         if(v.getId() == 0x1001){ //重新加载
045             setFootviewType(FOOTVIEW_TYPE.LOADING);
046             if(loadNotifyer != null)
047                 loadNotifyer.load();
048         }else if (v.getId() == 0x1002) {
049             setSelection(0);
050         }
051     }
052      
053     private void init(Context context) {
054         footViewLoading = new LinearLayout(context);
055         footViewLoading.setOrientation(LinearLayout.HORIZONTAL);
056         footViewLoading.setGravity(Gravity.CENTER);
057         ProgressBar bar = new ProgressBar(context);
058         TextView textView = new TextView(context);
059         textView.setText("加载中...");
060         footViewLoading.addView(bar, new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
061         footViewLoading.addView(textView, new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
062          
063         footViewRetry = new LinearLayout(context);
064         footViewRetry.setOrientation(LinearLayout.HORIZONTAL);
065         footViewRetry.setGravity(Gravity.CENTER);
066         textView = new TextView(context);
067         textView.setId(0x1001);
068         textView.setGravity(Gravity.CENTER);
069         textView.setText("网络不给力,请重试 o(︶︿︶)o");
070         textView.setOnClickListener(this);
071         footViewRetry.addView(textView, new LayoutParams(LayoutParams.WRAP_CONTENT, getFixPx(50)));
072          
073         footViewNomore = new LinearLayout(context);
074         footViewNomore.setOrientation(LinearLayout.HORIZONTAL);
075         footViewNomore.setGravity(Gravity.CENTER);
076         footViewNomore.setId(0x1002);
077  
078         textView = new TextView(context);
079         textView.setText("返回顶部↑");
080         textView.setGravity(Gravity.CENTER);
081          
082         footViewNomore.setClickable(true);
083         footViewNomore.setOnClickListener(this);
084         footViewNomore.addView(textView, new LayoutParams(LayoutParams.WRAP_CONTENT, getFixPx(50)));
085          
086         setFootviewType(FOOTVIEW_TYPE.LOADING);
087          
088         setOnScrollListener(this);
089         scrollState = SCROLL_STATE_IDLE;
090          
091         super.setOnItemClickListener(this);
092     }
093      
094     public enum FOOTVIEW_TYPE {
095         /** 加载中 */
096         LOADING,
097         /** 没有更多了,返回顶部 */
098         NOMOR,
099         /** 加载失败重试 */
100         RETRY,
101         /**无*/
102         NONE
103     }
104      
105     private View curFootView;
106     public void setFootviewType(FOOTVIEW_TYPE type) {
107         if(curFootView != null && curFootView.getTag() == type)
108             return;
109          
110         if(curFootView != null)
111             removeFooterView(curFootView);
112          
113         switch (type) {
114         case LOADING:
115             curFootView = footViewLoading;
116             break;
117         case NOMOR:
118             curFootView = footViewNomore;
119             break;
120         case RETRY:
121             curFootView = footViewRetry;
122             break;
123         case NONE:
124             return;
125         }
126          
127         addFooterView(curFootView);
128         curFootView.setTag(type);
129     }
130  
131     private View curHeadView;
132     public void setHeadView(View v) {
133         if(curHeadView!=null)
134             return;
135         curHeadView=v;
136         addHeaderView(v);
137     }
138      
139     @Override
140     public void onScrollStateChanged(AbsListView view, int scrollState) {
141         if (scrollState != this.scrollState) {
142             if(onScrollStateChangedListener != null){
143                 onScrollStateChangedListener.onScrollStateChanged(this.scrollState, scrollState);
144             }
145             this.scrollState = scrollState;
146         }
147     }
148  
149     protected int firstVisibleItem, visibleItemCount, totalItemCount;
150      
151     @Override
152     public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
153         if(totalItemCount < 2 //footview 也算
154             return;
155          
156 //      System.out.println("first=" + firstVisibleItem + ",visible=" + visibleItemCount + ",total=" + totalItemCount);
157          
158         if(firstVisibleItem + visibleItemCount >= totalItemCount){ //说明 footView 可见,通知加载更多
159             if (loadNotifyer != null && (curFootView != footViewNomore)) {
160                 loadNotifyer.load();
161             }
162         }
163         this.firstVisibleItem = firstVisibleItem;
164         this.visibleItemCount = visibleItemCount;
165         this.totalItemCount = totalItemCount;
166     }
167      
168     public int getFirstVisibleItem() {
169         return firstVisibleItem;
170     }
171      
172     public int getVisibleItemCount() {
173         return visibleItemCount;
174     }
175      
176     public int getScrollState() {
177         return scrollState;
178     }
179      
180     public void setLoadNotifyer(LoadNotifyer loadNotifyer) {
181         this.loadNotifyer = loadNotifyer;
182     }
183      
184     public void setOnScrollStateChangedListener(OnScrollStateChangedListener onScrollStateChangedListener) {
185         this.onScrollStateChangedListener = onScrollStateChangedListener;
186     }
187      
188     public int getFixPx(int dp){
189         float scale=getContext().getResources().getDisplayMetrics().density;
190         return (int)(scale*dp+0.5);
191     }
192  
193     private OnItemClickListener listener;
194     @Override
195     public void setOnItemClickListener(OnItemClickListener listener) {
196         this.listener = listener;
197 //      super.setOnItemClickListener(listener);
198     }
199      
200     @Override
201     public void onItemClick(AdapterView<?> parent, View view, int position,
202             long id) {
203         if(listener==null)return;
204         if(curHeadView != null){
205             if(position==0)return;
206             listener.onItemClick(parent, view, position-1, id);
207         }else{
208             listener.onItemClick(parent, view, position, id);
209         }
210     }
211 }

使用很方便,只需调用
LoaderListView.setLoadNotifyer(LoadNotifyer loadNotifyer)
然后每次滑到底部需要加载更多数据的时候,就会回调 
LoadNotifyer.load()
然后你在 load() 方法里加载下一页数据,加载完毕调用 
Adapter.notifyDataSetChanged()
列表就展示新数据了!

此外我这里面还封装了一个神奇的功能是设置 FootView 状态:
这里有四种状态:

01 public enum FOOTVIEW_TYPE {
02         /** 加载中 */
03         LOADING,
04         /** 没有更多了,返回顶部 */
05         NOMOR,
06         /** 加载失败重试 */
07         RETRY,
08         /**无*/
09         NONE
10     }
在加载下一页失败的时候,调用 
listView.setFootviewType(FOOTVIEW_TYPE.RETRY) 
列表底部显示改为,加载失败,点击重试,用户点击之后,会再次回调你的 load() 方法


同理
当你没有更多数据的时候调用
listView.setFootviewType(FOOTVIEW_TYPE.NOMOR)
列表底部显示改为 回到顶部 用户点击后自动跳到第一行!

嗯,很好!很强大!必须就顶一个!欢迎拍砖!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值