欢迎访问宙启技术站
智能推送

Android ListView 实现上拉加载的示例代码

发布时间:2023-05-15 15:51:50

在开发中,常用到的列表控件是ListView,但在处理大量数据时,仅使用ListView可能无法满足需求,因为初始状态下列表只会显示一定数量的数据,需要滑动到底部才会加载更多数据。于是,很多开发者会尝试实现上拉加载功能。下面,我将为大家介绍一种实现上拉加载的示例代码,希望对大家有所帮助。

先看一下实现效果:

![示例图](https://img-blog.csdnimg.cn/20220607155824163.gif?#pic_center)

下拉刷新的代码不再详细讲述,主要介绍如何实现上拉加载。

1、在布局文件中添加LoadMoreView

<?xml version="1.0" encoding="utf-8"?>
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/srl_refresh"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

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

    <include
        android:id="@+id/loadMoreView"
        layout="@layout/load_more_view" />
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>

其中,layout="@layout/load_more_view"即为加载更多的布局文件。

2、编写LoadMoreView

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/ll_load_more"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:gravity="center"
    android:orientation="vertical"
    android:padding="10dp"
    android:visibility="gone">

    <ProgressBar
        android:id="@+id/pb_loading"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:indeterminate="true" />

    <TextView
        android:id="@+id/tv_load_hint"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:text="正在加载中..."
        android:textColor="#999999"
        android:textSize="14sp" />
</LinearLayout>

其中,ProgressBar和TextView用于显示正在加载中的提示信息。

3、编写LoadMoreAdapter

/**
 * 上拉加载的适配器
 */
public abstract class LoadMoreAdapter extends BaseAdapter {
    /**
     * ListView 对象
     */
    private ListView mListView;

    /**
     * LoadMoreView 布局
     */
    private View mLoadMoreView;

    /**
     * ProgressBar
     */
    private ProgressBar mLoadingView;

    /**
     * TextView
     */
    private TextView mLoadText;

    /**
     * 加载状态
     */
    private int mLoadState = STATE_NONE;

    /**
     * 数据加载状态
     */
    public static final int STATE_NONE = 0;      // 隐藏
    public static final int STATE_LOADING = 1;   // 正在加载
    public static final int STATE_FAILED = 2;    // 加载失败
    public static final int STATE_NO_MORE = 3;   // 没有更多数据了

    public LoadMoreAdapter(ListView listView) {
        mListView = listView;
        mLoadMoreView = LayoutInflater.from(listView.getContext()).inflate(R.layout.load_more_view, null);
        mLoadingView = mLoadMoreView.findViewById(R.id.pb_loading);
        mLoadText = mLoadMoreView.findViewById(R.id.tv_load_hint);
        mLoadMoreView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (mLoadState == STATE_FAILED) {
                    mLoadState = STATE_LOADING;
                    updateLoadState();
                    onLoadMore();
                }
            }
        });
        updateLoadState();
        mListView.addFooterView(mLoadMoreView);
    }

    /**
     * 更新加载状态
     */
    public void updateLoadState() {
        switch (mLoadState) {
            case STATE_NONE:
                mLoadMoreView.setVisibility(View.GONE);
                break;

            case STATE_LOADING:
                mLoadingView.setVisibility(View.VISIBLE);
                mLoadText.setText(R.string.loading);
                mLoadMoreView.setVisibility(View.VISIBLE);
                break;

            case STATE_FAILED:
                mLoadingView.setVisibility(View.GONE);
                mLoadText.setText(R.string.load_failed);
                mLoadMoreView.setVisibility(View.VISIBLE);
                break;

            case STATE_NO_MORE:
                mLoadingView.setVisibility(View.GONE);
                mLoadText.setText(R.string.no_more_data);
                mLoadMoreView.setVisibility(View.VISIBLE);
                break;
        }
    }

    /**
     * 设置加载状态
     * @param loadState 加载状态
     */
    public void setLoadState(int loadState) {
        mLoadState = loadState;
        updateLoadState();
    }

    /**
     * 获取加载状态
     * @return 加载状态
     */
    public int getLoadState() {
        return mLoadState;
    }

    /**
     * 加载更多数据
     */
    public abstract void onLoadMore();
}

其中,主要实现了updateLoadState()方法,用于更新加载状态;setLoadState()方法,用于设置加载状态;getLoadState()方法,用于获取加载状态;onLoadMore()方法,用于加载更多数据。

4、编写LoadMoreListView

public class LoadMoreListView extends ListView {
    /**
     * 加载状态
     */
    private int mLoadState = STATE_NONE;

    /**
     * 数据加载状态
     */
    public static final int STATE_NONE = 0;      // 隐藏
    public static final int STATE_LOADING = 1;   // 正在加载
    public static final int STATE_FAILED = 2;    // 加载失败
    public static final int STATE_NO_MORE = 3;   // 没有更多数据了

    /**
     * 适配器
     */
    private LoadMoreAdapter mAdapter;

    /**
     * 是否正在加载中
     */
    private boolean mIsLoading = false;

    public LoadMoreListView(Context context) {
        super(context);
    }

    public LoadMoreListView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public LoadMoreListView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    /**
     * 设置适配器
     * @param adapter 适配器对象
     * @param listener 加载完成监听器
     */
    public void setLoadMoreAdapter(final LoadMoreAdapter adapter, final OnLoadMoreListener listener) {
        mAdapter = adapter;
        super.setAdapter(adapter);

        // 添加滚动事件监听
        super.setOnScrollListener(new OnScrollListener() {
            @Override
            public void onScrollStateChanged(AbsListView view, int scrollState) {
                // 滚动停止时的监听事件
                if (scrollState == SCROLL_STATE_IDLE) {
                    if (getLastVisiblePosition() == getAdapter().getCount() - 1) {   // 已经滑到底部了
                        if (mAdapter.getLoadState() == LoadMoreAdapter.STATE_NONE && !mIsLoading) {   // 如果当前不在加载中,开始加载更多数据
                            mIsLoading = true;
                            mAdapter.setLoadState(LoadMoreAdapter.STATE_LOADING);
                            listener.onLoadMore();
                        }
                    }
                }
            }

            @Override
            public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {

            }
        });
    }

    /**
     * 加载数据完成
     */
    public void onLoadMoreCompleted() {
        mIsLoading = false;
    }
}

其中,onLoadMoreCompleted()方法,用于通知上拉加载完成。

5、编写OnLoadMoreListener

/**
 * 加载更多监听器
 */
public interface OnLoadMoreListener {
    /**
     * 加载更多数据
     */
    void onLoadMore();
}

6、在Activity中使用

`

public class MainActivity extends AppCompatActivity {

/**

* 数据列表

*/

private List<String> mDataList;

/**

* 数据适配器

*/

private ArrayAdapter<String> mAdapter;

/**

* ListView 对象

*/

private LoadMoreListView mListView;

/**

* 下拉刷新控件

*/

private SwipeRefreshLayout mRefreshLayout;

/**

* 加载完成监听器

*/

private LoadMoreListView.OnLoadMoreListener mLoadMoreListener = new LoadMoreListView.OnLoadMoreListener() {

@Override

public void onLoadMore() {

// 模拟网络请求

new Handler().postDelayed(new Runnable() {

@Override

public void run()