教你简单的实现ListView上拉加载

作者: RaphetS | 来源:发表于2016-10-14 20:27 被阅读4764次

    ![4RN]VE7H(4D}(1@~~IYNUZT.png](https://img.haomeiwen.com/i2964446/4ac85e11f7edd190.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

    最近的一个项目,由于改了一些需求,需要给列表加上上拉加载功能。之前列表用的是ListView,改成RecyclerView改的地方还挺多,于是就想着自己写一个简单的支持加载更多的ListView。

    上拉加载.gif

    思路

    ————>ListView可以添加FootView,那么可以考虑用FootView作为加载布局。

    ————>那么什么情况下显示加载布局呢?当然是滑到底部就显示加载布局了。

    ————>但是怎么判断ListView是否滑到底部了呢?因为之前实现RecyclerView的上拉加载的时候,通过调用RecyclerView的addOnScrollListener()方法,判断是否加载到底部。所以可以看看ListView有没有类似的方法。通过查看ListView的API,果然,发现了setOnScrollListener()方法。

    好了,这些条件都具备了,那么就可以开始实现了。

    实现

    <br />

    一、首先,新建一个类继承自ListView,重写他的三个构造函数。
    public class LoadMoreListView extends ListView implements AbsListView.OnScrollListener {
    
        public LoadMoreListView(Context context) {
            super(context);
        }
    
        public LoadMoreListView(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
        }
    
        public LoadMoreListView(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
    }
    
    二、然后,在构造函数里对ListView进行初始化:添加FootView,设置setOnScrollListener()方法,实现OnScrollListener 接口,重写他的onScrollStateChanged()和onScroll()方法
    public class LoadMoreListView extends ListView implements AbsListView.OnScrollListener {
       private View mFootView;
        private int mTotalItemCount;//item总数
        private OnLoadMoreListener mLoadMoreListener;
        private boolean mIsLoading=false;//是否正在加载
    
        public LoadMoreListView(Context context) {
            super(context);
            init(context);
        }
    
        public LoadMoreListView(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            init(context);
        }
    
        public LoadMoreListView(Context context, AttributeSet attrs) {
            super(context, attrs);
            init(context);
        }
    
     private void init(Context context){
            mFootView= LayoutInflater.from(context).inflate(R.layout.foot_view,null);
            setOnScrollListener(this);
        }
    }
    

    下面是foot_view布局:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="horizontal" android:layout_width="match_parent"
        android:gravity="center"
        android:layout_height="match_parent">
        <ProgressBar
            style="@android:style/Widget.ProgressBar.Small"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
        <TextView
            android:layout_marginLeft="10dp"
            android:text="正在加载..."
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
    </LinearLayout>
    
    三、再然后,重写onScrollStateChanged()和onScroll()方法,判断是否到达底部
      @Override
        public void onScrollStateChanged(AbsListView listView, int scrollState) {
            // 滑到底部后,判断listview已经停止滚动并且最后可视的条目等于adapter的条目
            int lastVisibleIndex=listView.getLastVisiblePosition();
            if (!mIsLoading&&scrollState == OnScrollListener.SCROLL_STATE_IDLE//停止滚动
                    && lastVisibleIndex ==mTotalItemCount-1) {//滑动到最后一项
                mIsLoading=true;
                addFooterView(mFootView);
                if (mLoadMoreListener!=null) {
                    mLoadMoreListener.onloadMore();
                }
            }
        }
    
        @Override
        public void onScroll(AbsListView absListView, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
            mTotalItemCount=totalItemCount;
        }
    

    其中scrollState == OnScrollListener.SCROLL_STATE_IDLE表示,listView停止滑动。
    lastVisibleIndex ==mTotalItemCount-1表示滑动到最后一行了。

    四、然后,写一个方法,设置加载完毕,控制加载布局消失。
    public void setLoadCompleted(){
            mIsLoading=false;
           removeFooterView(mFootView);
        }
    
    五、最后新建一个接口OnLoadMoreListener以及一个setOnLoadMoreListener()方法,供外部调用加载更多的事件
    public void setONLoadMoreListener(OnLoadMoreListener listener){
            mLoadMoreListener=listener;
        }
    
        public interface OnLoadMoreListener{
            void onloadMore();
        }
    

    如何使用

    使用方法和ListView一样。
    首先布局文件:

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/activity_main"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
     <org.raphets.demoloadmorelistview.LoadMoreListView
         android:id="@+id/listview"
         android:layout_width="match_parent"
         android:layout_height="match_parent">
     </org.raphets.demoloadmorelistview.LoadMoreListView>
    </RelativeLayout>
    

    然后在Activity中:

    mListView.setOnLoadMoreListener(new LoadMoreListView.OnLoadMoreListener() {
                @Override
                public void onloadMore() {
                    loadMore();
                }
            });
    

    loadmore()方法中,处理加载更多数据的逻辑:

    private void loadMore() {
            new Thread(){
                @Override
                public void run() {
                    super.run();
                    try {
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    mData.add("atate");
                    mData.add("546646");
                    mData.add("546646");
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            adapter.notifyDataSetChanged();
                            mListView.setLoadCompleted();
                        }
                    });
                }
            }.start();
        }
    

    注意架加载完成之后,要调用setLoadCompleted()方法,控制加载布局消失

    完整代码

    package org.raphets.demoloadmorelistview;
    
    import android.content.Context;
    import android.util.AttributeSet;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.widget.AbsListView;
    import android.widget.ListView;
    
    /**
     * Created by RaphetS on 2016/10/14.
     */
    
    public class LoadMoreListView extends ListView implements AbsListView.OnScrollListener {
        private Context mContext;
        private View mFootView;
        private int mTotalItemCount;
        private OnLoadMoreListener mLoadMoreListener;
        private boolean mIsLoading=false;
    
        public LoadMoreListView(Context context) {
            super(context);
            init(context);
        }
    
        public LoadMoreListView(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            init(context);
        }
    
        public LoadMoreListView(Context context, AttributeSet attrs) {
            super(context, attrs);
            init(context);
        }
    
        private void init(Context context){
            this.mContext=context;
            mFootView= LayoutInflater.from(context).inflate(R.layout.foot_view,null);
            setOnScrollListener(this);
        }
    
    
        @Override
        public void onScrollStateChanged(AbsListView listView, int scrollState) {
            // 滑到底部后自动加载,判断listview已经停止滚动并且最后可视的条目等于adapter的条目
            int lastVisibleIndex=listView.getLastVisiblePosition();
            if (!mIsLoading&&scrollState == OnScrollListener.SCROLL_STATE_IDLE
                    && lastVisibleIndex ==mTotalItemCount-1) {
                mIsLoading=true;
                addFooterView(mFootView);
                if (mLoadMoreListener!=null) {
                    mLoadMoreListener.onloadMore();
                }
            }
        }
    
        @Override
        public void onScroll(AbsListView absListView, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
            mTotalItemCount=totalItemCount;
        }
    
        public void setOnLoadMoreListener(OnLoadMoreListener listener){
            mLoadMoreListener=listener;
        }
    
        public interface OnLoadMoreListener{
            void onloadMore();
        }
        public void setLoadCompleted(){
            mIsLoading=false;
           removeFooterView(mFootView);
        }
    }
    

    footView布局:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="horizontal" android:layout_width="match_parent"
        android:gravity="center"
        android:padding="15dp"
        android:layout_height="match_parent">
        <ProgressBar
            style="@android:style/Widget.ProgressBar.Small"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
        <TextView
            android:layout_marginLeft="10dp"
            android:text="正在加载..."
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
    </LinearLayout>
    

    Demo地址

    https://github.com/RaphetS/LoadMoreListView

    最后

    以上代码若是有什么问题,希望大家多多指教。希望能和大家互相学习,共同进步。谢谢。

    相关文章

      网友评论

      本文标题:教你简单的实现ListView上拉加载

      本文链接:https://www.haomeiwen.com/subject/zdcnyttx.html