自定义下拉刷新和上拉加载的recycleview

自定义下拉刷新和上拉加载的recycleview

先看一下效果(因为模拟器的原因,看不到进度条,大家可以下载demo,进行查看)

demo地址

首先看我们自定义的HeadView

package yuan.kuo.yu.view;

import android.animation.ValueAnimator;
import android.content.Context;
import android.os.Handler;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.RotateAnimation;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

import yuan.kuo.yu.R;
import yuan.kuo.yu.load.CircleLoadingView;

/**
 * Created by yukuo on 2016/4/29.
 * 这是一个recycleview的刷新的头布局
 */
public class YRecycleviewRefreshHeadView extends LinearLayout {
    //刷新头布局
    LinearLayout mContentView;
    //这是一个旋转动画
    private RotateAnimation mRotateUpAnim;
    private RotateAnimation mRotateDownAnim;
    //旋转默认的动画时间
    private static final int ROTATE_ANIM_DURATION = 180;
    private int mMeasuredHeight;
    private int mStatus;
    //正在刷新的状态
    public final static int STATE_REFRESHING = 2;
    //刷新结束的状态
    public final static int STATE_DONE = 3;
    //没有任何的状态
    public final static int STATE_NORMAL = 0;
    //准备刷新的状态
    private final int STATE_RELEASE_TO_REFRESH = 1;
    private ImageView iv_y_recycleview_head_refresh_status;
    private CircleLoadingView pb_y_recycleview_head_refresh_progressbar;
    private TextView tv_y_recycleview_head_refresh_status;

    public YRecycleviewRefreshHeadView(Context context) {
        super(context);
        initView(context);
    }

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

    /**
     * 初始化
     */
    private void initView(Context context) {
        mContentView = (LinearLayout) View.inflate(context, R.layout.head_recycleview_refresh, null);
        //宽高
        LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
        //距离父布局的距离
        lp.setMargins(0, 0, 0, 0);
        //设置布局的宽高的属性
        this.setLayoutParams(lp);
        //设置内容距离布局的边界的尺寸
        this.setPadding(0, 0, 0, 0);
        //添加内容布局并且设置宽是屏幕的宽.高为0
        addView(mContentView, new LayoutParams(LayoutParams.MATCH_PARENT, 0));
        //设置内容位于布局的下方
        setGravity(Gravity.BOTTOM);
        //查找头布局控件
        //刷新状态字体
        tv_y_recycleview_head_refresh_status = (TextView) findViewById(R.id.tv_y_recycleview_head_refresh_status);
        //刷新状态的箭头
        iv_y_recycleview_head_refresh_status = (ImageView) findViewById(R.id.iv_y_recycleview_head_refresh_status);
        //正在刷新的进度条
        pb_y_recycleview_head_refresh_progressbar = (CircleLoadingView) findViewById(R.id.pb_y_recycleview_head_refresh_progressbar);
        //定义一个向上旋转动画
        mRotateUpAnim = new RotateAnimation(0.0f, -180.0f,
                Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
        mRotateUpAnim.setDuration(ROTATE_ANIM_DURATION);
        //设置旋转之后保持旋转后的状态
        mRotateUpAnim.setFillAfter(true);
        //定义一个向下旋转的动画
        mRotateDownAnim = new RotateAnimation(-180.0f, 0.0f,
                Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
        mRotateDownAnim.setDuration(ROTATE_ANIM_DURATION);
        mRotateDownAnim.setFillAfter(true);
        //测量
        measure(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        //获取高度
        mMeasuredHeight = getMeasuredHeight();
    }

    /**
     * 设置这个刷新状态的方法
     */
    public void setState(int status) {
        //如果状态一致就不要更改
        if (status == mStatus) {
            return;
        }
        /**
         * 设置当前布局格局状态隐藏和显示
         */
        //设置刷新状态
        if (status == STATE_REFRESHING) {
            //清除箭头的动画效果并且隐藏
            iv_y_recycleview_head_refresh_status.clearAnimation();
            iv_y_recycleview_head_refresh_status.setVisibility(View.INVISIBLE);
            //展示进度条
            pb_y_recycleview_head_refresh_progressbar.setVisibility(View.VISIBLE);
        } else if (status == STATE_DONE) {
            //刷新结束状态
            iv_y_recycleview_head_refresh_status.setVisibility(View.INVISIBLE);
            pb_y_recycleview_head_refresh_progressbar.setVisibility(View.INVISIBLE);
        } else {
            //正常状态隐藏进度条显示箭头
            iv_y_recycleview_head_refresh_status.setVisibility(View.VISIBLE);
            pb_y_recycleview_head_refresh_progressbar.setVisibility(View.INVISIBLE);
        }
        /**
         * 根据状态进行动画的调整
         */
        switch (status) {
            case STATE_NORMAL:
                //如果当前状态是准备做刷新就开始动画
                if (mStatus == STATE_RELEASE_TO_REFRESH) {
                    iv_y_recycleview_head_refresh_status.startAnimation(mRotateDownAnim);
                }
                //如果当前状态正在刷新,就停止动画
                if (mStatus == STATE_REFRESHING) {
                    iv_y_recycleview_head_refresh_status.clearAnimation();
                }
                tv_y_recycleview_head_refresh_status.setText("下拉刷新");
                break;

            case STATE_RELEASE_TO_REFRESH:
                //如果当前状态不是准备去刷新
                if (mStatus != STATE_RELEASE_TO_REFRESH) {
                    iv_y_recycleview_head_refresh_status.clearAnimation();
                    iv_y_recycleview_head_refresh_status.startAnimation(mRotateUpAnim);
                    tv_y_recycleview_head_refresh_status.setText("松开刷新");
                }
                break;
            case STATE_REFRESHING:
                tv_y_recycleview_head_refresh_status.setText("正在刷新");
                break;
            case STATE_DONE:
                tv_y_recycleview_head_refresh_status.setText("刷新完成");
                break;
            default:
        }
        mStatus = status;
    }

    /**
     * 返回当前的状态
     * @return
     */
    public int getStatus() {
        return mStatus;
    }

    /**
     * 释放意图
     *
     * @return
     */
    public boolean releaseAction() {
        //是否在刷新
        boolean isOnRefresh = false;
        //获取显示的高度
        int height = getVisibleHeight();
        if (height == 0) // not visible.
            isOnRefresh = false;//没有刷新
        if (getVisibleHeight() > mMeasuredHeight && mStatus < STATE_REFRESHING) {
            setState(STATE_REFRESHING);
            isOnRefresh = true;//正在刷新
        }
        // refreshing and header isn‘t shown fully. do nothing.
        if (mStatus == STATE_REFRESHING && height <= mMeasuredHeight) {
            //return;
        }
        int destHeight = 0; // default: scroll back to dismiss header.
        // is refreshing, just scroll back to show all the header.
        if (mStatus == STATE_REFRESHING) {
            destHeight = mMeasuredHeight;
        }
        smoothScrollTo(destHeight);

        return isOnRefresh;
    }

    /**
     * 移动距离
     *
     * @param delta
     */
    public void onMove(float delta) {
        if (getVisibleHeight() > 0 || delta > 0) {
            setVisibleHeight((int) delta + getVisibleHeight());
            if (mStatus <= STATE_RELEASE_TO_REFRESH) { // 未处于刷新状态,更新箭头
                if (getVisibleHeight() > mMeasuredHeight) {
                    setState(STATE_RELEASE_TO_REFRESH);
                } else {
                    setState(STATE_NORMAL);
                }
            }
        }
    }

    /**
     * 这是一个让布局高度改变的方法
     */
    public void smoothScrollTo(int Height) {
        ValueAnimator animator = ValueAnimator.ofInt(getVisibleHeight(), Height);
        animator.setDuration(300).start();
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                setVisibleHeight((int) animation.getAnimatedValue());
            }
        });
        animator.start();
    }

    /**
     * 设置布局高度为0,并设置状态为正常状态
     */
    public void reset() {
        smoothScrollTo(0);
        new Handler().postDelayed(new Runnable() {
            public void run() {
                setState(STATE_NORMAL);
            }
        }, 500);
    }

    /**
     * 刷新完成
     */
    public void refreshComplete() {
        setState(STATE_DONE);
        new Handler().postDelayed(new Runnable() {
            public void run() {
                reset();
            }
        }, 200);
    }

    /**
     * 获取显示的高度
     *
     * @return
     */
    public int getVisibleHeight() {
        LayoutParams lp = (LayoutParams) mContentView.getLayoutParams();
        return lp.height;
    }

    /**
     * 设置显示的高度
     *
     * @param height
     */
    public void setVisibleHeight(int height) {
        if (height < 0) height = 0;
        LayoutParams lp = (LayoutParams) mContentView.getLayoutParams();
        lp.height = height;
        mContentView.setLayoutParams(lp);
    }

}

然后看我们自定义的加载更多的footview

package yuan.kuo.yu.view;

import android.content.Context;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;

import yuan.kuo.yu.R;
import yuan.kuo.yu.load.CircleLoadingView;

/**
 * Created by yukuo on 2016/4/30.
 */
public class YRecycleviewRefreshFootView extends LinearLayout {

    private CircleLoadingView pb_y_recycleview_foot_loadmore_progressbar;
    private TextView tv_y_recycleview_foot_loadmore_status;
    /**
     * 加载中
     */
    public final static int STATE_LOADING = 0;
    /**
     * 加载完成
     */
    public final static int STATE_COMPLETE = 1;
    /**
     * 正常状态
     */
    public final static int STATE_NOMORE = 2;

    public YRecycleviewRefreshFootView(Context context) {
        super(context);
        initView(context);
    }

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

    /**
     * 初始化
     */
    private void initView(Context context) {
        //设置内部内容居中
        setGravity(Gravity.CENTER);
        //设置宽高
        setLayoutParams(new ViewGroup.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
        //底部布局
        View mContentView = View.inflate(context, R.layout.foot_recycleview_loadmore, null);
        pb_y_recycleview_foot_loadmore_progressbar = (CircleLoadingView) mContentView.findViewById(R.id.pb_y_recycleview_foot_loadmore_progressbar);
        tv_y_recycleview_foot_loadmore_status = (TextView) mContentView.findViewById(R.id.tv_y_recycleview_foot_loadmore_status);
        addView(mContentView);
    }

    /**
     * 设置当前状态
     *
     * @param state
     */
    public void setState(int state) {
        switch (state) {
            case STATE_LOADING:
                pb_y_recycleview_foot_loadmore_progressbar.setVisibility(View.VISIBLE);
                tv_y_recycleview_foot_loadmore_status.setText("加载中...");
                this.setVisibility(View.VISIBLE);
                break;
            case STATE_COMPLETE:
                tv_y_recycleview_foot_loadmore_status.setText("加载中...");
                this.setVisibility(View.GONE);
                break;
            case STATE_NOMORE:
                tv_y_recycleview_foot_loadmore_status.setText("没有更多了..");
                pb_y_recycleview_foot_loadmore_progressbar.setVisibility(View.GONE);
                this.setVisibility(View.VISIBLE);
                break;
        }

    }
}

然后就是我们最重要的自定义recycleview了

package yuan.kuo.yu.view;

import android.content.Context;
import android.support.annotation.Nullable;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.StaggeredGridLayoutManager;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;

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

/**
 * Created by yukuo on 2016/4/29.
 * 这是一个带下拉刷新和上拉加载的revycleview
 */
public class YRecycleview extends RecyclerView {
    /**
     * 是否可以刷新的常量
     */
    private boolean pullRefreshEnabled = true;
    /**
     * 是否可以加载更多的常量
     */
    private boolean loadMoreEnabled = true;
    /**
     * 头布局集合
     */
    private ArrayList<View> mHeaderViews = new ArrayList<>();
    /**
     * 脚布局集合
     */
    private ArrayList<View> mFootViews = new ArrayList<>();
    //当前的头布局
    private YRecycleviewRefreshHeadView mHeadView;
    //监听器
    private OnRefreshAndLoadMoreListener refreshAndLoadMoreListener;
    //加载数据中的状态
    private boolean isLoadingData = false;
    //adapter没有数据的时候显示,类似于listView的emptyView
    private View mEmptyView;
    //没有数据的状态
    private boolean isNoMore = false;
    //阻率
    private static final float DRAG_RATE = 2;
    /**
     * 数据观察者
     */
    private final RecyclerView.AdapterDataObserver mDataObserver = new DataObserver();
    /**
     * 最后的y坐标
     */
    private float mLastY = -1;
    private boolean onTop;
    private WrapAdapter mWrapAdapter;
    private static final int TYPE_REFRESH_HEADER = -5;
    private static final int TYPE_NORMAL = 0;
    private static final int TYPE_FOOTER = -3;
    private static List<Integer> sHeaderTypes = new ArrayList<>();
    private static final int HEADER_INIT_INDEX = 10000;

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

    public YRecycleview(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public YRecycleview(Context context, @Nullable AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init();
    }

    /**
     * 这是一个初始化的方法
     */
    private void init() {
        //可以进行刷新
        if (pullRefreshEnabled) {
            //获取头布局
            YRecycleviewRefreshHeadView refreshHeader = new YRecycleviewRefreshHeadView(getContext());
            //添加进去
            mHeaderViews.add(0, refreshHeader);
            mHeadView = refreshHeader;
        }
        YRecycleviewRefreshFootView footView = new YRecycleviewRefreshFootView(getContext());
        addFootView(footView);
        mFootViews.get(0).setVisibility(GONE);
    }

    /**
     * 当滚动状态改变的时候
     *
     * @param state
     */
    @Override
    public void onScrollStateChanged(int state) {
        super.onScrollStateChanged(state);

        if (state == RecyclerView.SCROLL_STATE_IDLE && refreshAndLoadMoreListener != null && !isLoadingData && loadMoreEnabled) {
            LayoutManager layoutManager = getLayoutManager();
            int lastVisibleItemPosition;
            if (layoutManager instanceof GridLayoutManager) {
                lastVisibleItemPosition = ((GridLayoutManager) layoutManager).findLastVisibleItemPosition();
            } else if (layoutManager instanceof StaggeredGridLayoutManager) {
                int[] into = new int[((StaggeredGridLayoutManager) layoutManager).getSpanCount()];
                ((StaggeredGridLayoutManager) layoutManager).findLastVisibleItemPositions(into);
                lastVisibleItemPosition = findMax(into);
            } else {
                lastVisibleItemPosition = ((LinearLayoutManager) layoutManager).findLastVisibleItemPosition();
            }
            if (layoutManager.getChildCount() > 0
                    && lastVisibleItemPosition >= layoutManager.getItemCount() - 1 && layoutManager.getItemCount() > layoutManager.getChildCount()
                    && !isNoMore && mHeadView.getStatus() < YRecycleviewRefreshHeadView.STATE_REFRESHING) {

                View footView = mFootViews.get(0);
                isLoadingData = true;
                if (footView instanceof YRecycleviewRefreshFootView) {
                    ((YRecycleviewRefreshFootView) footView).setState(YRecycleviewRefreshFootView.STATE_LOADING);
                } else {
                    footView.setVisibility(View.VISIBLE);
                }
                refreshAndLoadMoreListener.onLoadMore();
            }
        }
    }

    private int findMax(int[] into) {
        int max = into[0];
        for (int value : into) {
            if (value > max) {
                max = value;
            }
        }
        return max;
    }

    /**
     * 控件的触摸事件的监听
     *
     * @param e
     * @return
     */
    @Override
    public boolean onTouchEvent(MotionEvent e) {
        if (mLastY == -1) {
            mLastY = e.getRawY();
        }
        switch (e.getAction()) {
            case MotionEvent.ACTION_DOWN:
                mLastY = e.getRawY();
                break;
            case MotionEvent.ACTION_MOVE:
                final float deltaY = e.getRawY() - mLastY;
                mLastY = e.getRawY();
                if (isOnTop() && pullRefreshEnabled) {
                    mHeadView.onMove(deltaY / DRAG_RATE);
                    if (mHeadView.getVisibleHeight() > 0 && mHeadView.getStatus() < mHeadView.STATE_REFRESHING) {
                        return false;
                    }
                }
                break;
            default:
                //复位
                mLastY = -1; // reset
                if (isOnTop() && pullRefreshEnabled) {
                    if (mHeadView.releaseAction()) {
                        if (refreshAndLoadMoreListener != null) {
                            refreshAndLoadMoreListener.onRefresh();
                        }
                    }
                }
                break;
        }
        return super.onTouchEvent(e);
    }

    /**
     * 是否是顶部
     *
     * @return
     */
    public boolean isOnTop() {
        return !(mHeaderViews == null || mHeaderViews.isEmpty()) && mHeaderViews.get(0).getParent() != null;
    }

    @Override
    public void setAdapter(Adapter adapter) {
        mWrapAdapter = new WrapAdapter(adapter);
        super.setAdapter(mWrapAdapter);
        adapter.registerAdapterDataObserver(mDataObserver);
        mDataObserver.onChanged();
    }

    /**
     * 包装的适配器
     */
    private class WrapAdapter extends RecyclerView.Adapter<ViewHolder> {
        private RecyclerView.Adapter adapter;
        private int mCurrentPosition;
        private int headerPosition = 1;

        public WrapAdapter(Adapter adapter) {
            this.adapter = adapter;
        }

        @Override
        public int getItemViewType(int position) {
            if (isRefreshHeader(position)) {
                return TYPE_REFRESH_HEADER;
            }
            if (isHeader(position)) {
                position = position - 1;
                return sHeaderTypes.get(position);
            }
            if (isFooter(position)) {
                return TYPE_FOOTER;
            }
            int adjPosition = position - getHeadersCount();
            int adapterCount;
            if (adapter != null) {
                adapterCount = adapter.getItemCount();
                if (adjPosition < adapterCount) {
                    return adapter.getItemViewType(adjPosition);
                }
            }
            return TYPE_NORMAL;
        }

        @Override
        public void onAttachedToRecyclerView(RecyclerView recyclerView) {
            super.onAttachedToRecyclerView(recyclerView);
            RecyclerView.LayoutManager manager = recyclerView.getLayoutManager();
            if (manager instanceof GridLayoutManager) {
                final GridLayoutManager gridManager = ((GridLayoutManager) manager);
                gridManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
                    @Override
                    public int getSpanSize(int position) {
                        return (isHeader(position) || isFooter(position))
                                ? gridManager.getSpanCount() : 1;
                    }
                });
            }
        }

        public boolean isHeader(int position) {
            return position >= 0 && position < mHeaderViews.size();
        }

        public boolean isContentHeader(int position) {
            return position >= 1 && position < mHeaderViews.size();
        }

        public boolean isFooter(int position) {
            return position < getItemCount() && position >= getItemCount() - mFootViews.size();
        }

        public boolean isRefreshHeader(int position) {
            return position == 0;
        }

        public int getHeadersCount() {
            return mHeaderViews.size();
        }

        public int getFootersCount() {
            return mFootViews.size();
        }

        @Override
        public void onViewAttachedToWindow(ViewHolder holder) {
            super.onViewAttachedToWindow(holder);
            ViewGroup.LayoutParams lp = holder.itemView.getLayoutParams();
            if (lp != null
                    && lp instanceof StaggeredGridLayoutManager.LayoutParams
                    && (isHeader(holder.getLayoutPosition()) || isFooter(holder.getLayoutPosition()))) {
                StaggeredGridLayoutManager.LayoutParams p = (StaggeredGridLayoutManager.LayoutParams) lp;
                p.setFullSpan(true);
            }
        }

        @Override
        public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            if (viewType == TYPE_REFRESH_HEADER) {
                mCurrentPosition++;
                return new SimpleViewHolder(mHeaderViews.get(0));
            } else if (isContentHeader(mCurrentPosition)) {
                if (viewType == sHeaderTypes.get(mCurrentPosition - 1)) {
                    mCurrentPosition++;
                    return new SimpleViewHolder(mHeaderViews.get(headerPosition++));
                }
            } else if (viewType == TYPE_FOOTER) {
                return new SimpleViewHolder(mFootViews.get(0));
            }
            return adapter.onCreateViewHolder(parent, viewType);
        }

        @Override
        public void onBindViewHolder(ViewHolder holder, int position) {
            if (isHeader(position)) {
                return;
            }
            int adjPosition = position - getHeadersCount();
            int adapterCount;
            if (adapter != null) {
                adapterCount = adapter.getItemCount();
                if (adjPosition < adapterCount) {
                    adapter.onBindViewHolder(holder, adjPosition);
                    return;
                }
            }
        }

        @Override
        public int getItemCount() {
            if (adapter != null) {
                return getHeadersCount() + getFootersCount() + adapter.getItemCount();
            } else {
                return getHeadersCount() + getFootersCount();
            }
        }

        @Override
        public long getItemId(int position) {
            if (adapter != null && position >= getHeadersCount()) {
                int adjPosition = position - getHeadersCount();
                int adapterCount = adapter.getItemCount();
                if (adjPosition < adapterCount) {
                    return adapter.getItemId(adjPosition);
                }
            }
            return -1;
        }

        @Override
        public void registerAdapterDataObserver(AdapterDataObserver observer) {
            if (adapter != null) {
                adapter.registerAdapterDataObserver(observer);
            }
        }

        @Override
        public void unregisterAdapterDataObserver(AdapterDataObserver observer) {
            if (adapter != null) {
                adapter.unregisterAdapterDataObserver(observer);
            }
        }

        private class SimpleViewHolder extends RecyclerView.ViewHolder {
            public SimpleViewHolder(View itemView) {
                super(itemView);
            }
        }
    }

    /**
     * 这是一个数据观察者
     */
    private class DataObserver extends RecyclerView.AdapterDataObserver {
        @Override
        public void onChanged() {
            Adapter<?> adapter = getAdapter();
            if (adapter != null && mEmptyView != null) {
                int emptyCount = 0;
                if (pullRefreshEnabled) {
                    emptyCount++;
                }
                if (loadMoreEnabled) {
                    emptyCount++;
                }
                if (adapter.getItemCount() == emptyCount) {
                    mEmptyView.setVisibility(View.VISIBLE);
                    YRecycleview.this.setVisibility(View.GONE);
                } else {
                    mEmptyView.setVisibility(View.GONE);
                    YRecycleview.this.setVisibility(View.VISIBLE);
                }
            }
            if (mWrapAdapter != null) {
                mWrapAdapter.notifyDataSetChanged();
            }
        }

        @Override
        public void onItemRangeInserted(int positionStart, int itemCount) {
            mWrapAdapter.notifyItemRangeInserted(positionStart, itemCount);
        }

        @Override
        public void onItemRangeChanged(int positionStart, int itemCount) {
            mWrapAdapter.notifyItemRangeChanged(positionStart, itemCount);
        }

        @Override
        public void onItemRangeChanged(int positionStart, int itemCount, Object payload) {
            mWrapAdapter.notifyItemRangeChanged(positionStart, itemCount, payload);
        }

        @Override
        public void onItemRangeRemoved(int positionStart, int itemCount) {
            mWrapAdapter.notifyItemRangeRemoved(positionStart, itemCount);
        }

        @Override
        public void onItemRangeMoved(int fromPosition, int toPosition, int itemCount) {
            mWrapAdapter.notifyItemMoved(fromPosition, toPosition);
        }

    }

    /**
     * 设置没有更多数据了
     *
     * @param noMore
     */
    public void setNoMoreData(boolean noMore) {
        this.isNoMore = noMore;
        View footView = mFootViews.get(0);
        ((YRecycleviewRefreshFootView) footView).setState(isNoMore ? YRecycleviewRefreshFootView.STATE_NOMORE : YRecycleviewRefreshFootView.STATE_COMPLETE);
    }

    /**
     * 获取一个空布局
     *
     * @return
     */
    public View getmEmptyView() {
        return mEmptyView;
    }

    /**
     * 设置空布局
     */
    public void setEmptyView(View emptyView) {
        mEmptyView = emptyView;
        //数据改变
        mDataObserver.onChanged();
    }

    /**
     * 还原所有的状态
     */
    public void reSetStatus() {
        setloadMoreComplete();
        refreshComplete();
    }

    /**
     * 设置刷新完成
     */
    private void refreshComplete() {
        mHeadView.refreshComplete();
    }

    /**
     * 设置加载更多完成
     */
    public void setloadMoreComplete() {
        //设置加载数据为false
        isLoadingData = false;
        View footView = mFootViews.get(0);
        if (footView instanceof YRecycleviewRefreshFootView) {
            ((YRecycleviewRefreshFootView) footView).setState(YRecycleviewRefreshFootView.STATE_COMPLETE);
        } else {
            footView.setVisibility(View.GONE);
        }
    }

    /**
     * 设置刷新和加载更多的监听器
     *
     * @param refreshAndLoadMoreListener 监听器
     */
    public void setRefreshAndLoadMoreListener(OnRefreshAndLoadMoreListener refreshAndLoadMoreListener) {
        this.refreshAndLoadMoreListener = refreshAndLoadMoreListener;
    }

    /**
     * 刷新和加载更多的监听器
     */
    public interface OnRefreshAndLoadMoreListener {
        void onRefresh();

        void onLoadMore();
    }

    /**
     * 设置是否启用下拉刷新功能
     *
     * @param isEnabled
     */
    public void setReFreshEnabled(boolean isEnabled) {
        pullRefreshEnabled = isEnabled;
    }

    /**
     * 设置刷新完成
     */
    public void setReFreshComplete() {
        mHeadView.refreshComplete();
    }

    /**
     * 设置是否启用上拉加载功能
     *
     * @param isEnabled
     */
    public void setLoadMoreEnabled(boolean isEnabled) {
        loadMoreEnabled = isEnabled;
        //如果不启用加载更多功能,就隐藏脚布局
        if (!isEnabled && mFootViews.size() > 0) {
            mFootViews.get(0).setVisibility(GONE);
        }
    }

    /**
     * 设置是否刷新ing状态
     *
     * @param refreshing
     */
    public void setRefreshing(boolean refreshing) {
        if (refreshing && pullRefreshEnabled && refreshAndLoadMoreListener != null) {
            mHeadView.setState(YRecycleviewRefreshHeadView.STATE_REFRESHING);
            mHeadView.onMove(mHeadView.getMeasuredHeight());
            refreshAndLoadMoreListener.onRefresh();
        }
    }

    /**
     * 添加头布局
     *
     * @param headView 刷新头布局
     */
    public void addHeadView(View headView) {
        if (pullRefreshEnabled && !(mHeaderViews.get(0) instanceof YRecycleviewRefreshHeadView)) {
            YRecycleviewRefreshHeadView refreshHeader = new YRecycleviewRefreshHeadView(getContext());
            mHeaderViews.add(0, refreshHeader);
            mHeadView = refreshHeader;
        }
        mHeaderViews.add(headView);
        sHeaderTypes.add(HEADER_INIT_INDEX + mHeaderViews.size());
    }

    /**
     * 添加底部布局
     *
     * @param footView
     */
    private void addFootView(YRecycleviewRefreshFootView footView) {
        mFootViews.clear();
        mFootViews.add(footView);
    }

}

这个自定义recycleview参考的是xlistview的实现方式!!

使用方式很简单,直接布局引用就可以了,其他的适配器等 与原生的一样,没有任何改变

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <yuan.kuo.yu.view.YRecycleview
        android:id="@+id/ycl"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</RelativeLayout>

Demo地址:github

欢迎fork和star,谢谢

时间: 2024-10-12 10:07:05

自定义下拉刷新和上拉加载的recycleview的相关文章

支持下拉刷新和上划加载更多的自定义RecyclerView(仿XListView效果)

首先看效果 下拉刷新:        上划加载        在项目更新的过程中,遇到了一个将XListView换成recyclerView的需求,而且更换完之后大体效果不能变,但是对于下拉刷新这样的效果,谷歌给出的解决方案是把RecyclerView放在一个SwipeRefreshLayout中,但是这样其实是拉下一个小圆形控件实现的,和XListView的header效果不同.在网上找了很多的别人代码,都没有实现我想要的效果,于是自己动手写了一个. 具体实现的效果有以下几条 下拉刷新功能:

最新Android ListView 下拉刷新 上滑加载

开发项目过程中基本都会用到listView的下拉刷新和上滑加载更多,之前大家最常用的应该是pull to refresh或它的变种版吧,google官方在最新的android.support.v4包中增加了一个新类SwipeRefreshLayout,地址 这个类的作用就是提供官方的下拉刷新,并且效果相当不错,而上拉加载更多则用我们自定义的listview,也是相当简单. 下拉刷新 简单的介绍下: 首先它是一个viewgroup,但是它只允许有一个子控件,子控件能是任何view,使用的时候,所在

vue2.0 自定义 下拉刷新和上拉加载更多(Scroller) 组件

1.下拉刷新和上拉加载更多组件 Scroller.vue <!-- 下拉刷新 上拉加载更多 组件 --> <template> <div :style="marginTop" class="yo-scroll" :class="{'down':(state===0),'up':(state==1),refresh:(state===2),touch:touching}" @touchstart="touch

iOS学习之路--下拉刷新和上拉加载更多

iOS学习之路--下拉刷新和上拉加载更多 简介 本文中笔者将和大家分享应用app中常用到的表单内容的下拉刷新和上拉加载更多的功能实现的方法. 内容 1.有哪些实现方法与各方法的优劣 使用过美团,大众点评的朋友们应该有注意到,当你向上滑动表单的时候会有更多的店铺加载进你的表单中,而当你下滑表单顶的时候,则会刷新表单的内容并从网络上获取最新的信息.通过下拉刷新和上拉加载更多的功能,使app可以获取更多用户想要的信息和获取最新的信息.那么这种功能如何实现呢,还请跟着笔者继续往下看. 目前来说,主要的实

【好程序员笔记分享】——下拉刷新和上拉加载更多

-iOS培训,iOS学习-------型技术博客.期待与您交流!------------ iOS学习之路--下拉刷新和上拉加载更多 简介 本文中笔者将和大家分享应用app中常用到的表单内容的下拉刷新和上拉加载更多的功能实现的方法. 内容 1.有哪些实现方法与各方法的优劣 使用过美团,大众点评的朋友们应该有注意到,当你向上滑动表单的时候会有更多的店铺加载进你的表单中,而当你下滑表单顶的时候,则会刷新表单的内容 并从网络上获取最新的信息.通过下拉刷新和上拉加载更多的功能,使app可以获取更多用户想要

RecyclerView 下拉刷新和上拉加载

RecyclerView 下拉刷新和上拉加载 RecyclerView已经出来很久了,许许多多的项目都开始从ListView转战RecyclerView,那么,上拉加载和下拉刷新是一件很有必要的事情. 在ListView上,我们可以通过自己添加addHeadView和addFootView去添加头布局和底部局实现自定义的上拉和下拉,或者使用一些第三方库来简单的集成,例如android-pulltorefresh或者android-Ultra-Pull-to-Refresh,后者的自定义更强,但需

使用PullToRefresh实现下拉刷新和上拉加载

使用PullToRefresh实现下拉刷新和上拉加载 分类: Android2013-12-20 15:51 78158人阅读 评论(91) 收藏 举报 Android下拉刷新上拉加载PullToRefresh PullToRefresh是一套实现非常好的下拉刷新库,它支持: 1.ListView 2.ExpandableListView 3.GridView 4.WebView 等多种常用的需要刷新的View类型,而且使用起来也十分方便. (下载地址:https://github.com/ch

IOS 开发下拉刷新和上拉加载更多

IOS 开发下拉刷新和上拉加载更多 简介 1.常用的下拉刷新的实现方式 (1)UIRefreshControl (2)EGOTTableViewrefresh (3)AH3DPullRefresh (4)MJRefresh (5)自己实现 2.AH3DPullRefresh实现下拉刷新和上拉下载的步骤 添加UIScrollView+AH3DPullRefresh.h 和UIScrollView+AH3DPullRefresh.m两个文件,由此可知,它是基于UIScrollView的方法. 在bu

Android 使用PullToRefresh实现下拉刷新和上拉加载(ExpandableListView)

PullToRefresh是一套实现非常好的下拉刷新库,它支持: 1.ListView 2.ExpandableListView 3.GridView 4.WebView 等多种常用的需要刷新的View类型,而且使用起来也十分方便. (下载地址:https://github.com/chrisbanes/Android-PullToRefresh) 下载完成,将它导入到eclipse中,作为一个library导入到你的工程中就好了. 一.废话少说,下拉刷新Go. 1.在你的布局文件中加上你想用的