Android应用开发中,采用ListView组件来展示数据是很常用的功能,当一个应用要展现很多的数据时,一般情况下都不会把所有的数据一次就展示出来,而是通过分页的形式来展示数据,个人觉得这样会有更好的用户体验。因此,很多应用都是采用分批次加载的形式来获取用户所需的数据。例如:微博客户端可能会在用户滑动至列表底端时自动加载下一页数据,也可能在底部放置一个"查看更多"按钮,用户点击后,加载下一页数据。

下面通过一个Demo来展示ListView功能如何实现:该Demo通过在ListView列表的底部添加一个“查看更多...”按钮来加载新闻(模拟新闻客户端)分页数据。同时限定每次加载10条记录,但完全加载完数据后,就把ListView列表底部视图“查看更多...”删除。假设加载的数据总数为 38 条记录。先看下该Demo工程的程序结构图:


其中包 com.listviewpager中News.java类是新闻实体类,包com.listviewpager中 MainActivity.java类是用来展示ListView列表。布局layout中包含三个布局文件,分别为:list_item.xml , loadmore.xml , main_activity.xml 。下面分别贴下源码:

layout中的 list_item.xml源码:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <TextView
        android:id="@+id/newstitle"
        android:textColor="@android:color/holo_purple"
        android:textSize="20sp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

    <TextView
        android:layout_margin="3dp"
        android:textSize="20dp"
        android:id="@+id/newscontent"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

</LinearLayout>


layout中loadmore.xml源码:


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">
    <Button
        android:id="@+id/loadMoreButton"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="查看更多..." />

</LinearLayout>


layout中main_activity.xml源码:


<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.listviewpager.MainActivity">

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

</android.support.constraint.ConstraintLayout>


News.java类 源码:


package com.listviewpager;

/**
 * Created by Administrator on 2016-08-01.
 */

public class News {
    private String title;
    private String content;

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }
}


MainActivity.java类 源码:


package com.listviewpager;

import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

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

public class MainActivity extends AppCompatActivity implements AbsListView.OnScrollListener{

    private ListView listView;
    private int visibleLastIndex = 0;   //最后的可视项索引
    private int visibleItemCount;   // 当前窗口可见项总数
    private int datasize = 38;          //模拟数据集的条数
    private PaginationAdapter adapter;
    private View loadMoreView;
    private Button loadMoreButton;
    private Handler handler = new Handler();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        loadMoreView = getLayoutInflater().inflate(R.layout.loadmore,null);

        loadMoreButton = (Button) loadMoreView.findViewById(R.id.loadMoreButton);

        loadMoreButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                loadMoreButton.setText("正在加载中...");   //设置按钮文字
                handler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        loadMoreData();
                        adapter.notifyDataSetChanged();
                        loadMoreButton.setText("查看更多...");  //恢复按钮文字

                    }
                },2000);
            }

        });
        listView = (ListView) findViewById(R.id.lvNews);
        listView.addFooterView(loadMoreView);
        initializeAdapter();
        listView.setAdapter(adapter);
        listView.setOnScrollListener(this);


    }


    private void loadMoreData() {
        int count = adapter.getCount();
        if (count + 10 <= datasize) {
            for (int i = 1; i <= 10; i++) {
                News item = new News();
                item.setTitle("helloworld" + i);
                item.setContent("This is hello world" + i);
                adapter.addNewsItem(item);
            }
        }else {
            for (int i=count+1;i<=datasize;i++){
                News item = new News();
                item.setTitle("helloworld" + i);
                item.setContent("This is hello world" + i);
                adapter.addNewsItem(item);
            }
        }
    }

    @Override
    public void onScrollStateChanged(AbsListView absListView, int i) {
        int itemsLastIndex = adapter.getCount()-1;
        int lastIndex = itemsLastIndex+1;
        if(i == AbsListView.OnScrollListener.SCROLL_STATE_IDLE && visibleLastIndex==lastIndex){
            // 如果是自动加载,可以在这里放置异步加载数据的代码

        }
    }

    @Override
    public void onScroll(AbsListView absListView, int i, int i1, int i2) {
        this.visibleItemCount = i1;
        visibleLastIndex = i + i1 - 1;

        Log.e("========================= ","========================");
        Log.e("firstVisibleItem = ",i+"");
        Log.e("visibleItemCount = ",i1+"");
        Log.e("totalItemCount = ",i2+"");
        Log.e("========================= ","========================");

        //如果所有的记录选项等于数据集的条数,则移除列表底部视图
        if(i2 == datasize+1){
            listView.removeFooterView(loadMoreView);
            Toast.makeText(getApplicationContext(),"全部加载完毕。。。",Toast.LENGTH_SHORT).show();

        }

    }

    /**
     * 初始化ListView的适配器
     */
    public void initializeAdapter(){
        List<News> news = new ArrayList<News>();
        for(int i =1;i<=10;i++){
            News items = new News();
            items.setTitle("helloworld"+i);
            items.setContent("This is hello world" + i);
            news.add(items);
        }
        adapter = new PaginationAdapter(news);
    }

    private class PaginationAdapter extends BaseAdapter{
        List<News> newItems;

        public PaginationAdapter(List<News> newItems) {
            this.newItems = newItems;
        }

        @Override
        public int getCount() {
            return newItems.size();
        }

        @Override
        public Object getItem(int i) {
            return newItems.get(i);
        }

        @Override
        public long getItemId(int i) {
            return i;
        }

        @Override
        public View getView(int i, View view, ViewGroup viewGroup) {
            if(view==null){
                view = getLayoutInflater().inflate(R.layout.list_item, null);
            }
            //新闻标题
            TextView tv_title = (TextView) view.findViewById(R.id.newstitle);
            tv_title.setText(newItems.get(i).getTitle());
            //新闻内容
            TextView tv_content = (TextView) view.findViewById(R.id.newscontent);
            tv_content.setText(newItems.get(i).getContent());

            return view;
        }
        /**
         * 添加数据列表项
         * @param newsitem
         */
        public void addNewsItem(News newsitem){
            newItems.add(newsitem);
        }

    }
}


最后,运行程序的结果截图如下:



通过上面的截图,当我们点击"查看更多..."按钮时,就会加载下10条记录,当加载完所有的记录后,ListView的底部视图将会移除。