ListView加载更多demo

原文链接找不到了,

效果如下:


代码如下

package net.example.listdemo;


import java.util.ArrayList;
import java.util.List;


import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;


public class MainActivity extends Activity implements OnScrollListener{
private ListView lv;//ListView
private int totalCount;// 数据总条数
private List<String> lists = new ArrayList<String>();//这是数据源
private ArrayAdapter<String> adapter;
private View view_more;
private ProgressBar pb;
private TextView tvLoad;
private int lastVisibleIndex;
int start=0;
int end=0;
//写个handler机制。处理问题
private Handler handler=new Handler(){
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);
switch(msg.what){
case 0:
if(null==adapter){
adapter=new ArrayAdapter<>(MainActivity.this,android.R.layout.simple_list_item_1,lists);
lv.setAdapter(adapter);
lv.addFooterView(view_more);
//设置监听
setListeners();
}else{
adapter.notifyDataSetChanged();
}

break;
}


}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initViews();
initData();
}
/**
* 模拟网络请求数据,一次获取15条
*/
private void initData() {
// TODO Auto-generated method stub
   new Thread(){
  public void run() {
  totalCount = 100;// 假设数据一共有100条,将来调接口可以获取到这个值
  for(int i=0;i<15;i++){
  lists.add("数据"+(i+1));
  }
  Message msg=new Message();
  msg.what=0;
 handler.sendMessage(msg);
  
  };
   }.start();
}
private void initData(final int start, final int end) {
        // 模拟网络请求获取数据,一次获取15条
        new Thread() {
            public void run() {
                try {
                    Thread.sleep(4000);// 模拟获取数据时的耗时3s
                    for (int i = start; i < end; i++) {
                        lists.add(i, "数据" + (i + 1));
                    }
                    // 给handler发消息更新UI,子线程不可以更新UI
                    Message message = new Message();
                    message.what = 0;
                    handler.sendMessage(message);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            };
        }.start();
    }
/**
* 初始化控件
*/
private void initViews() {
   lv = (ListView) findViewById(R.id.lv);
   // 构建底部加载布局
   view_more = (View) getLayoutInflater()
           .inflate(R.layout.view_more, null);
   // 进度条
   pb = (ProgressBar) view_more.findViewById(R.id.progressBar);
   // “正在加载...”文本控件
   tvLoad = (TextView) view_more.findViewById(R.id.tv_Load);
}
 public void setListeners() {
if(totalCount>15){
lv.setOnScrollListener(this);
}else{
lv.removeFooterView(view_more);
}
};
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
// TODO Auto-generated method stub
Log.e("sunlei", "lastVisibleIndex = " + lastVisibleIndex);
       Log.e("sunlei", "adapter.getCount() = " + adapter.getCount());
       // 滑到底部后自动加载,判断listView已经停止滚动并且最后可视的条目等于adapter的条目
       // 注意这里在listView设置好adpter后,加了一个底部加载布局。
       // 所以判断条件为:lastVisibleIndex == adapter.getCount()
       if (scrollState == SCROLL_STATE_IDLE
               && lastVisibleIndex == adapter.getCount()) {
           /**
            * 这里也要设置为可见,是因为当你真正从网络获取数据且获取失败的时候。
            * 我在失败的方法里面,隐藏了底部的加载布局并提示用户加载失败。所以再次监听的时候需要
            * 继续显示隐藏的控件。因为我模拟的获取数据,失败的情况这里不给出。实际中简单的加上几句代码就行了。
            */
           pb.setVisibility(View.VISIBLE);
           tvLoad.setVisibility(View.VISIBLE);
           loadMoreData();// 加载更多数据
       }
}
private void loadMoreData() {
 
// 获取此时adapter中的总条目数
       int count = adapter.getCount();
       // 一次加载15条数据,即下拉加载的执行
       if (count +15< totalCount) {
           start = count;
           end = start + 15;
           initData(start, end);// 模拟网络获取数据操作
       } else {// 数据不足15条直接加载到结束
           start = count;
           end = totalCount;
           initData(start, end);// 模拟网络获取数据曹祖
           // 数据全部加载完成后,移除底部的view
           lv.removeFooterView(view_more);
           Toast.makeText(MainActivity.this, "数据已经全部加载", 1).show();
       }


   }
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
// TODO Auto-generated method stub
Log.d("sunlei","firstVisibleItem="+firstVisibleItem);
Log.d("sunlei","totalItemCount="+totalItemCount);
Log.d("sunlei"," visibleItemCount+"+visibleItemCount);
// 计算最后可见条目的索引
        lastVisibleIndex = firstVisibleItem + visibleItemCount -1;
        // 当adapter中的所有条目数已经和要加载的数据总条数相等时,则移除底部的View
        if (totalItemCount == totalCount +1) {
            // 移除底部的加载布局
            lv.removeFooterView(view_more);
        }
}



}


布局文件如下:主页布局

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >


    <ListView
        android:id="@+id/lv"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        />


</RelativeLayout>


加载更多布局:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="80dp"
    
     android:background="#8888" 
     >
    <TextView
        android:id="@+id/tv_Load"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hasmore"
        android:layout_centerInParent="true"
      
        />
      <ProgressBar
        android:id="@+id/progressBar"
         style="?android:attr/progressBarStyleSmall"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:layout_toLeftOf="@id/tv_Load"
        android:padding="10dp"                            
        android:visibility="visible" />
</RelativeLayout>

这里面有些方法参数是需要额外了解的,如下:

 假设一共有10条数据需要加载在ListView 展示。我们定义为    A  。还有个加载更多部分位于ListView底部,我们定义为B。

此时ListView由A和B俩部分组成。

文中 public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) 方法中参数解释如下:

firstVisibleItem:表示在当前屏幕显示的第一个listItem在整个listView里面的位置(下标从0开始);

visibleItemCount:表示在现时屏幕可以见到的ListItem(部分显示的ListItem也算)总数(注意如果B存在,那么B也是1个,包含B)

totalItemCount:表示的是当前ListView中数据的长度(注意如果B存在,那么B也是1个,包含B。所以应该是A+B)

adapter.getCount():表示的是当前ListView中数据的长度(注意如果B存在,那么B也是1个,不包含B。所以应该是A的长度,注意和上面的区别)








评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值