ListView Scroll: 动态加载列表内容

本文介绍如何实现在ListView滚动时动态加载内容,特别是在列表即将接近底部时就开始预加载,确保用户在正常滚动速度下几乎感觉不到加载过程。关键点在于当距离底部还有15条数据时开始加载,提升用户体验。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目标:当一个ListView在上下滑动时(scroll up / scroll down),当List中的内容比较多时,会分批load进其中的内容。这在各类型App中很常见。我们现在就是做一个动态加载列表内容功能。

特点: 与平时的到了页底再load data不同,假如每次翻页为20条数据,我做的是当ListView滚动停下来时,离页底还有15条数据时就准备load data。也就是说在正常翻页速度下,用户是看不到load data的状态的(为了调试,要设置长一点sleep time以便观察)。


以下是部分关键代码,e.g.

		listView.setOnScrollListener(new OnScrollListener() {
			@Override
			public void onScrollStateChanged(AbsListView view, int scrollState) {
				switch (scrollState) {
				case OnScrollListener.SCROLL_STATE_IDLE:
					int firstVisiblePosition = view.getFirstVisiblePosition();
		            if (sideData.size() < getDataCount()) { // current accumulated items count < total items count
		            	canLoad = true;
		            } else {
		            	canLoad = false;
		            }
		            
		            if (firstVisiblePosition >= currentPage.get() * pageSize - 15) {	// 离页底还有15条数据时就准备load data
			            int maxPage = getDataCount() / pageSize;
			            if (currentPage.get() + 1 <= maxPage && canLoad) {
	                        /* 每次翻页前添加页脚 */
	                        listView.addFooterView(footer);
	                        listView.setAdapter(adapter);
	                        /* 创建子线程,执行翻页 */
	                        new Thread(new Runnable() {
	                            public void run() {
	                                try {
	                                    Thread.sleep(3000);
	                                } catch (InterruptedException e) {
	                                    e.printStackTrace();
	                                }
	                                List<String> sideDataByPage = getData(currentPage.get() + 1);
	                                mHandler.sendMessage(mHandler.obtainMessage(1, sideDataByPage));	//add new items
	                            }
	                        }).start();
	                    } else if (canLoad) {
	                    	List<String> sideDataByPage = getData(currentPage.get() + 1);
	                    	mHandler.sendMessage(mHandler.obtainMessage(2, sideDataByPage));	//add last items
	                    }
		            }
					break;
				case OnScrollListener.SCROLL_STATE_TOUCH_SCROLL:
					break;
				case OnScrollListener.SCROLL_STATE_FLING:
					break;
				default:
					break;
				}
			}

	private Handler mHandler = new Handler() {
		@SuppressWarnings("unchecked")
		public void handleMessage(Message msg) {
			switch (msg.what) {
				case 1:
					/* 页脚显示完就删掉 */
					if (listView.getFooterViewsCount() > 0)
						listView.removeFooterView(footer);
					sideData.addAll((List<String>) msg.obj);
					adapter.notifyDataSetChanged();
					currentPage.getAndIncrement();
					break;
				case 2:
					sideData.addAll((List<String>) msg.obj);
					adapter.notifyDataSetChanged();
					currentPage.getAndIncrement();
					break;
				default:
					break;
			}
		}
	};


XML

- side.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="@android:color/background_dark"
    android:orientation="vertical" >

    <ListView
        android:id="@+id/side_list"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="2"
        >
    </ListView>
        
</LinearLayout>

- side_items.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="@android:color/background_dark"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/side_text_view"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:textSize="18sp"
        android:textColor="@android:color/white"
        android:lineSpacingExtra="3dp"
        android:lineSpacingMultiplier="1.5"
        android:layout_weight="2"
        >
    </TextView>
        
</LinearLayout>

- side_footer.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="@android:color/background_dark"
    android:orientation="horizontal" >

    <ProgressBar
        style="?android:attr/process"
        android:layout_width="18dp"
        android:layout_height="wrap_content" />
 
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="正在加载....."
        android:textSize="18sp"
        android:textColor="@android:color/white"
        android:lineSpacingExtra="3dp"
        android:lineSpacingMultiplier="1.5"
         />
		 
</LinearLayout>



一些以便调试用到的辅助代码,e.g.

	public List<String> getData(int currentPage) {
		List<String> sideDataByPage = new ArrayList<String>();
		int maxPosition = currentPage * pageSize;
		if (maxPosition > getDataCount()) {
			maxPosition = getDataCount();
		}
		for (int position = (currentPage - 1) * pageSize; position < maxPosition; position++) {
			sideDataByPage.add(mStrings[position].substring(0, (mStrings[position].length() < 12)?mStrings[position].length():12));  // 防止字符过长换行
		}
		return sideDataByPage;
	}
private String[] mStrings = {"test", "test1", ...}
	public int getDataCount() {
		// total items count
		return mStrings.length;
	}
public class Side {
	private View sideView;
	private ListView listView;
	private View footer;
	final private int pageSize = 20;
	private List<String> sideData = new ArrayList<String>();
	private BaseAdapter adapter;
	private boolean canLoad = true;
	private AtomicInteger currentPage = new AtomicInteger(1);
	private SlidingViewGroup slidingViewGroup;
	
	public Side(final Activity activity, final Context context, final SlidingViewGroup slidingViewGroup) {
		setSlidingViewGroup(slidingViewGroup);
		sideView = LayoutInflater.from(context).inflate(R.layout.side, null);
		footer = LayoutInflater.from(context).inflate(R.layout.side_footer, null);
		sideData.addAll(getData(1));
		adapter = new ArrayAdapter<String>(context, R.layout.side_items,
				R.id.side_text_view, sideData);
		listView = (ListView) this.sideView.findViewById(R.id.side_list);
		listView.setAdapter(adapter);
...


效果图



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值