ListView的下拉刷新和上拉加载(一)

今天说一说ListView的下拉刷新和上拉加载的初步实现,感觉自己写的东西基本上就是拾人牙慧,几乎没什么创新,就是把别人的东西东拼西凑来实现自己的需求。但是还是能学到点东西的,至少以后自己再遇到同样的请求可以看自己的总结就行了。

下拉刷新参考网址:android-Ultra-Pull-To-Refresh

上拉加载参考网址: ListView上拉加载更多的UI需求

先看一看效果

这里写图片描述

下拉刷新就不说了,下面说一说上拉加载实现的原理。

  1. ListView 实现上拉加载更多,就是在ListView在滚动的时候,并且竖直方向上向上滚动的距离大于0,当最后一个 item 可见的时候触发加载更多的操作。请注意滚动距离大于0 这两个条件,因为如果ListView 初始化的时候只有很少几项数据,这时候,最后item是可见的。这时候,ListView的滚动距离为0,所以不应该触发加载更多操作。

  2. 在加载更多的过程中,动态给ListView添加一个FootView,Footview有两种状态,正在加载,和没有更多数据。

  3. 在加载完成后,如果得到的数据不为空,就通知adapter notifyDataSetChanged() ,然后把FootView隐藏或者remove。如果得到的数据为空,FootView 就应该显示 no more data 类似的提示。

  4. 实现的步骤最主要的是给ListView添加一个滚动的监听事件,当ListView滚动的时候,判断是否满足加载更多的条件,如果满足,就加载更多。接下来看看自定义LsitView源码并不难理解

package com.example.listviewpulldownrefreshpulluploadmore;

import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.widget.AbsListView;
import android.widget.ListView;

/**
 * Created by dumingwei on 2016/8/20.
 */
public class MyListView extends ListView {

    private boolean isPullUpLoading = false;//是否正在加载更多
    private boolean noMoreItem = false;//是否还有更多数据
    private LoadMoreListener loadMoreListener;//加载更多的回调接口

    public void setNoMoreItem(boolean noMoreItem) {
        this.noMoreItem = noMoreItem;
    }


    private PullUpLoadListViewFooter mFooterView;

    public void setPullUpLoading(boolean pullUpLoading) {
        isPullUpLoading = pullUpLoading;
    }

    public void setLoadMoreListener(LoadMoreListener loadMoreListener) {
        this.loadMoreListener = loadMoreListener;
    }

    public MyListView(Context context) {
        this(context, null);
    }

    public MyListView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

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

    private void init() {
        isPullUpLoading = false;
        mFooterView = new PullUpLoadListViewFooter(getContext());
        setOnScrollListener(new MyOnScrollerListener());
    }

    private class MyOnScrollerListener implements OnScrollListener {

        @Override
        public void onScrollStateChanged(AbsListView view, int scrollState) {
            //do nothing here
        }

        /**
         * Callback method to be invoked when the list or grid has been scrolled. This will be
         * called after the scroll has completed
         *
         * @param view The view whose scroll state is being reported
         * @param firstVisibleItem the index of the first visible cell (ignore if
         *         visibleItemCount == 0)
         * @param visibleItemCount the number of visible cells
         * @param totalItemCount the number of items in the list adaptor
         */
        @Override
        public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
            /**
             * 判断条件表示的意思
             * !isPullUpLoading 不是处于正在加载更多的状态中
             * !noMoreItem 还有更多数据
             * (firstVisibleItem + visibleItemCount) == totalItemCount ,ListView的最后一个item可见
             *  getScrollDistance() > 0 ,ListView 向上滑动的距离大于0(如果不加这个条件,当ListView最初只有几项数据,以至于,前两个条件满足,会触发加载更多操作)
             */
            if (!isPullUpLoading && !noMoreItem && (firstVisibleItem + visibleItemCount) == totalItemCount
                    && getScrollDistance() > 0) {
                showFootView();
                if (loadMoreListener != null) {
                    loadMoreListener.loadMore();
                }
            }
        }
    }

    /**
     * 的到ListView 在竖直方向上的滑动距离
     *
     * @return
     */
    public int getScrollDistance() {
        View c = getChildAt(0);
        if (c == null) {
            return 0;
        }
        int firstVisiblePosition = getFirstVisiblePosition();
        int top = c.getTop();
        return -top + firstVisiblePosition * c.getHeight();
    }

    /**
     * 加载更多的回调接口
     */
    public interface LoadMoreListener {

        void loadMore();
    }

    /**
     * 显示footView
     */
    public void showFootView() {
        if (getFooterViewsCount() < 1) {
            addFooterView(mFooterView);
        }
        mFooterView.setVisibility(View.VISIBLE);
        mFooterView.updateView(PullUpLoadListViewFooter.State.LOADING);//显示Loading
    }

    /**
     * 隐藏掉footView
     */
    public void removeFootView() {
        setPullUpLoading(false);
        // removeFooterView(mFooterView);
        mFooterView.setVisibility(View.GONE);
    }

    /**
     * 数据已经完全加载完毕,footView 显示 no  more
     */
    public void haveLoadAll() {
        setNoMoreItem(true);//没有更多数据
        if (mFooterView != null) {
            mFooterView.setVisibility(View.VISIBLE);
            mFooterView.updateView(PullUpLoadListViewFooter.State.NOT_LOADING);//显示no more data
        }

    }
}

该说的都在注释里面了,使用的demo下载,请移步:ListViewPullDownRefreshPullUpLoadMore

2024.04.09 回顾,现在基本不用ListView了吧,都用RecyclerView了。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值