RecyclerView 上拉加载更多以及下拉刷新

RecyclerView 已经出来很久了,但是在项目中之前都使用的是ListView,最近新的项目上了都大量的使用了RecycleView.尤其是瀑布流的下拉刷新,网上吧啦吧啦没有合适的自己总结了一哈。
先贴图上来看看:
这里写图片描述
这里写图片描述

使用RecyclerView实现上拉加载更多和下拉刷新的功能我自己有两种方式:
1.使用系统自带的Android.support.v4.widget.SwipeRefreshLayout这个控价来实现。
2.自定义的里面带有RecyleView的控件。
使用RecycleView很不好添加头部,之前在使用listview当中自己可以添加header和bootm,但是RecycleView好像不是那么的好操作。对于第一种使用系统自带的Android.support.v4.widget.SwipeRefreshLayout来实现的,也很好用,但是产品一般不要这种下拉刷新,为了让自己显得牛逼,他一般会搞一个自己的带有动画,这就比较扯淡了。。。所以就只能用方法2了。
大致说一哈方法2的实现方式,父布局为ViewGroup,里面添加View第一个为控件为header第二个控件为RecycleView,至于最底部的下拉加载更多试图,通过RecycleViw的Adapter来添加。
有了思路就搞起来:

package com.krain.srecyclerview.fruitview;

import android.content.Context;
import android.graphics.drawable.AnimationDrawable;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.ImageView;
import com.krain.srecyclerview.R;
/**
 * Created by dafuShao on 2016/9/9 0009.
 *
 */
public class ElizabethView extends FrameLayout {
    private ImageView imageView;
    private  AnimationDrawable animationDrawable;
    public ElizabethView(Context context) {
        super(context);
        initview(context);
    }
    public ElizabethView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initview(context);
    }
    public ElizabethView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initview(context);
    }
    private void initview(Context context){
        View view= LayoutInflater.from(context).inflate(R.layout.elizabeth_item,null);
        imageView=(ImageView) view.findViewById(R.id.elizabeth_im);
        animationDrawable= (AnimationDrawable) imageView.getBackground();
        addView(view);
    }
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }
    //开始动画
    public  void startAnim(){
        animationDrawable.start();
    }
    //停止动画
    public   void  stopAnim(){
        animationDrawable.stop();
    }
}

这是头部控价很简单里面有一个小的臭蛋眼睛左右挤一哈的效果就不贴图了。
下面是自定义的包含RecyclerView的控件代码如下:

package com.krain.srecyclerview.srecyclerview;

import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.support.v4.view.MotionEventCompat;
import android.support.v7.widget.DefaultItemAnimator;
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.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.Scroller;
import android.widget.TextView;

import com.krain.srecyclerview.R;
import com.krain.srecyclerview.fruitview.ElizabethView;
public class SRecyclerView extends ViewGroup {
    Context context;
    RecyclerView mRecyclerView;
    ElizabethView mHeaderView;
    TextView mFootViewTips;//footview的文字显示
    AdapterWrapper mAdapter;
    boolean mIsTop = true;//是否滑动到了最顶部
    RecyclerView.LayoutManager mLayoutManager;
    int mLastVisibleItem;
    int mFirstVisibleItem;
    OnRecyclerStatusChangeListener mRecyclerChangeListener;
    int mStatus;//当前状态
    int mHeadviewHeight;//headview的高度
    Scroller mScroller;
    int mFristScollerY;//最开始的getscrolly
    boolean mHasFooter;//是否有上拉加载的功能
    boolean mShowFootVisible;//是否显示FOOTERview在mHasFooter为true的时候生效
    boolean mHasRefresh = true;//是否支持下拉刷新
    private final int DEFAULT_MIN_PAGEINDEX = 1;//默认最小的页数
    int mMaxPage = DEFAULT_MIN_PAGEINDEX;//分页的总页数
    int mCurrentPage = DEFAULT_MIN_PAGEINDEX;//当前的页数,从1开始
    private final int STATUS_NORMAL = 0, STATUS_REFRESH = 1, STATUS_LOAD = 2;
    private final int MSG_LOAD_COMPLETE = 1, MSG_REFRESH_COMPLETE = 0;//handle的常量
    private final int DELAY_LOAD_COMPLETE = 1000, DELAY_REFRESH_COMPLETE = 1000;//加载完成延时回收的时间

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

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

    /**
     * 设置最大页数
     *
     * @param maxPage
     */
    public void setMaxPage(int maxPage) {
        this.mMaxPage = maxPage;
    }

    /**
     * 是否支持上拉加载
     *
     * @param hasLoadmore
     */
    public void setLoadmore(boolean hasLoadmore) {
        mHasFooter = hasLoadmore;
    }


    public void  setRecyclerViewLayoutManage(RecyclerView.LayoutManager mLayoutManage){
        this.mLayoutManager=mLayoutManage;
    }
    /**
     * 关闭下拉刷新功能
     */
    public void disableRefresh() {
        mHasRefresh = false;
    }

    public void setAdapter(BaseRecyclerViewAdapter adapter) {
        int height = 0;
        if (mMaxPage == DEFAULT_MIN_PAGEINDEX) {
            mHasFooter = false;
        }
        mAdapter = new AdapterWrapper(context, adapter);
        mRecyclerView.setAdapter(mAdapter);
    }

    private int getViewHeight(View view) {
        int measure = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
        view.measure(measure, measure);
        return view.getMeasuredHeight();
    }

    /**
     * 获取viewgroup里面的recyclerview
     *
     * @return
     */
    public RecyclerView getRecyclerView() {
        return mRecyclerView;
    }

    public void setOnRecyclerChangeListener(OnRecyclerStatusChangeListener listener) {
        mRecyclerChangeListener = listener;
    }

    /**
     * 设置RecyclerView添加、删除Item的动画
     *
     * @param animator
     */
    public void setItemAnimator(RecyclerView.ItemAnimator animator) {
        mRecyclerView.setItemAnimator(animator);
    }

    public void notifyDataSetChanged() {
        mStatus = STATUS_NORMAL;//重新set数据代表loadmore结束了,此时恢复成普通状态
        mAdapter.notifyDataSetChanged();

    }

    public void notifyDataInsert(int positionStart, int itemCount) {
        mStatus = STATUS_NORMAL;//重新set数据代表loadmore结束了,此时恢复成普通状态
        mAdapter.notifyItemRangeInserted(positionStart, itemCount);
    }

    public void notifyDataRemove(int position) {
        mStatus = STATUS_NORMAL;//重新set数据代表loadmore结束了,此时恢复成普通状态
        mAdapter.notifyItemRemoved(position);
    }

    /**
     * 初始化操作
     *
     * @param context
     */
    void init(Context context) {
        this.context = context;
        mScroller = new Scroller(context);
//        if (mLayoutManager!=null){
//            addChildView(context,mLayoutManager);
//        }else{
//            addChildView(context, new LinearLayoutManager(context));
//        }
        addChildView(context);
    }
    @Override
    public void computeScroll() {
        if (mScroller.computeScrollOffset()) {
            scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
            postInvalidate();
        }
    }

    /**
     * 增加子View
     *
     * @param context
     */
    void addChildView(Context context, RecyclerView.LayoutManager mLayoutManager) {
        ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
        mHeaderView = new ElizabethView(context);
        mRecyclerView = new RecyclerView(context);
        addView(mHeaderView);
        addView(mRecyclerView);
        //mLayoutManager = new LinearLayoutManager(context);
       // mLayoutManager = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL);
        mRecyclerView.setLayoutManager(mLayoutManager);
        // 设置Item增加、移除默认动画
        mRecyclerView.setItemAnimator(new DefaultItemAnimator());
        mRecyclerView.addOnScrollListener(onScrollListener);
        mRecyclerView.setHasFixedSize(true);
        mRecyclerView.setLayoutParams(params);
    }
    void addChildView(Context contex) {
        ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
        mHeaderView = new ElizabethView(context);
        mRecyclerView = new RecyclerView(context);
        addView(mHeaderView);
        addView(mRecyclerView);
        //mLayoutManager = new LinearLayoutManager(context);
        mLayoutManager = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL);
        mRecyclerView.setLayoutManager(mLayoutManager);
        // 设置Item增加、移除默认动画
        mRecyclerView.setItemAnimator(new DefaultItemAnimator());
        mRecyclerView.addOnScrollListener(onScrollListener);
        mRecyclerView.setHasFixedSize(true);
        mRecyclerView.setLayoutParams(params);
    }
    /**
     * 屏蔽Recyclerview的触摸事件(下拉刷新的时候)
     */
    float lastY;

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        final int action = MotionEventCompat.getActionMasked(ev);
        switch (action) {
            case MotionEvent.ACTION_DOWN:
                lastY = ev.getRawY();
                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                return false;
            case MotionEvent.ACTION_MOVE:
                if (mHasRefresh && mIsTop && ev.getRawY() > lastY)
                    return true;
                break;

        }
        return false;
    }


    float offsetY = 0;

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_MOVE:
                offsetY = Math.abs(event.getRawY() - lastY); //Y差值绝对值
                if (offsetY > 0)
                    scrollToOffset(offsetY);
                else {
                    mIsTop = false;
                }
                break;
            case MotionEvent.ACTION_UP:
                if (getScrollY() <= 0) {
                    doRefresh();
                    mHeaderView.stopAnim();
                    mHeaderView.startAnim();
                } else complete();
                break;
        }
        return super.onTouchEvent(event);
    }


    /**
     * 滚动这个view到手滑动的位置
     *
     * @param offsetY Y轴偏移量
     */
    void scrollToOffset(float offsetY) {
        //假如正在刷新并且现在的scrolly和初始值一样的时候,代表准备下拉开始刷新,并执行一次only
        if (getScrollY() == mFristScollerY && mRecyclerChangeListener != null)
            mRecyclerChangeListener.startRefresh();
        int value = Math.round(offsetY / 2.0F);
        value = mFristScollerY - value;
        scrollTo(0, value);
    }

    /**
     * 执行刷新操作,移动到header刚出来的位置
     */
    void doRefresh() {


        mStatus = STATUS_REFRESH;
        int currentY = getScrollY();
        mScroller.startScroll(0, currentY, 0, (mFristScollerY - mHeadviewHeight) - currentY);
        invalidate();
        if (mRecyclerChangeListener != null) mRecyclerChangeListener.onRefresh();
        handler.sendEmptyMessageDelayed(MSG_REFRESH_COMPLETE, DELAY_REFRESH_COMPLETE);

    }

    Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            if (msg.what == MSG_LOAD_COMPLETE) {
                View footview = mAdapter.getFootView();
                if (footview != null)
                    mRecyclerView.smoothScrollBy(0, -footview.getMeasuredHeight());
            } else if (msg.what == MSG_REFRESH_COMPLETE)
                complete();
        }
    };


    /**
     * header返回原处完全隐藏
     */
    public void complete() {
        mCurrentPage = DEFAULT_MIN_PAGEINDEX;//完成之后当前的page恢复默认值
        if (mFootViewTips != null)
            mFootViewTips.setText(context.getString(R.string.loading));//更改foot提示为正在加载中
        if (mRecyclerChangeListener != null) mRecyclerChangeListener.refreshComplete();
        mStatus = STATUS_NORMAL;
        int currentY = getScrollY();
        mScroller.startScroll(0, currentY, 0, mFristScollerY - currentY);
        mHeaderView.stopAnim();
        invalidate();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int width = MeasureSpec.getSize(widthMeasureSpec);
        int height = 0;
        for (int i = 0; i < getChildCount(); i++) {
            View child = getChildAt(i);
            measureChild(child, widthMeasureSpec, heightMeasureSpec);
            height += child.getMeasuredHeight();
        }
        setMeasuredDimension(width, height);
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        int left = getPaddingLeft();
        int top = getPaddingTop();
        for (int i = 0; i < getChildCount(); i++) {
            View child = getChildAt(i);
            if (i == 0) {//当是header的时候居中显示
                int headerLeft = getMeasuredWidth() / 2 - child.getMeasuredWidth() / 2;
                child.layout(headerLeft, top, headerLeft + child.getMeasuredWidth(), top + child.getMeasuredHeight());
            } else
                child.layout(left, top, left + child.getMeasuredWidth(), top + child.getMeasuredHeight());
            top += child.getMeasuredHeight();
        }
        mHeadviewHeight = getPaddingTop() + mHeaderView.getMeasuredHeight();
        scrollTo(0, mHeadviewHeight);//移动到header下方以显示recyleview
        mFristScollerY = getScrollY();
    }


    /**
     * RecyclerView的滑动监听事件
     */
    RecyclerView.OnScrollListener onScrollListener = new RecyclerView.OnScrollListener() {
        @Override
        public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
            super.onScrollStateChanged(recyclerView, newState);

            if (newState == RecyclerView.SCROLL_STATE_IDLE) {
                //滑动到了顶部
                if (mFirstVisibleItem == 0) {
                    mIsTop = true;
                } else {
                    mIsTop = false;
                    if (mStatus != STATUS_LOAD && mShowFootVisible && mLastVisibleItem + 1 == mAdapter.getItemCount()) {
                        if (mCurrentPage == mMaxPage) {
                            //当前页面是最后一页的时候
                            mFootViewTips = (TextView) mAdapter.getFootView().findViewById(R.id.footer_tips);
                            mFootViewTips.setText(context.getString(R.string.last_page_tips));
                            handler.sendEmptyMessageDelayed(MSG_LOAD_COMPLETE, DELAY_LOAD_COMPLETE);
                        } else {
                            mStatus = STATUS_LOAD;
                            if (mRecyclerChangeListener != null) {
                                mRecyclerChangeListener.onLoadMore();
                                mCurrentPage++;
                            }
                        }

                    }
                }


            }
        }

        @Override
        public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
            super.onScrolled(recyclerView, dx, dy);
            if (mLayoutManager instanceof LinearLayoutManager) {
                mLastVisibleItem = ((LinearLayoutManager) mLayoutManager).findLastVisibleItemPosition();
                mFirstVisibleItem = ((LinearLayoutManager) mLayoutManager).findFirstCompletelyVisibleItemPosition();
                setFootviewVisible();
            } else if (mLayoutManager instanceof GridLayoutManager) {
                mLastVisibleItem = ((GridLayoutManager) mLayoutManager).findLastVisibleItemPosition();
                mFirstVisibleItem = ((GridLayoutManager) mLayoutManager).findFirstCompletelyVisibleItemPosition();
                setFootviewVisible();
            } else if (mLayoutManager instanceof StaggeredGridLayoutManager) {
                //因为StaggeredGridLayoutManager的特殊性可能导致最后显示的item存在多个,所以这里取到的是一个数组
                //得到这个数组后再取到数组中position值最大的那个就是最后显示的position值了
                int[] lastPositions = new int[((StaggeredGridLayoutManager) mLayoutManager).getSpanCount()];
                ((StaggeredGridLayoutManager) mLayoutManager).findLastVisibleItemPositions(lastPositions);
                mLastVisibleItem = findMax(lastPositions);
                mFirstVisibleItem = ((StaggeredGridLayoutManager) mLayoutManager).findFirstVisibleItemPositions(lastPositions)[0];
                setFootviewVisible();
            }
        }
    };
    void setFootviewVisible() {
        //当设置了拥有上拉加载功能但是第一页的条目不足以盛满Recyclerview的时候隐藏footer
        if (mHasFooter && mFirstVisibleItem == 0) {
            /**
             *  这里加上一个mShowFootVisible在上拉加载功能启用的情况下生效,从来控制item数量不足铺满
             *  recyclerview高度的时刻隐藏footview,在item数量超过view高度的情况下显示
             */
            if (mLastVisibleItem + 1 == mAdapter.getItemCount()) {
                mShowFootVisible = false;
            } else mShowFootVisible = true;
            notifyDataSetChanged();
        }
    }
    private int findMax(int[] positions) {
        int max = positions[0];
        for (int value : positions) {
            if (value > max) {
                max = value;
            }
        }
        return max;
    }
    private class AdapterWrapper extends RecyclerView.Adapter {
        private static final int TYPE_ITEM = 0;
        private static final int TYPE_FOOTER = 1;
        private RecyclerView.Adapter mAdapter;
        private Context mContext;
        View footer;
        public AdapterWrapper(Context context, RecyclerView.Adapter wrappedAdapter) {
            this.mContext = context;
            this.mAdapter = wrappedAdapter;
        }
        @Override
        public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            RecyclerView.ViewHolder holder = null;
            switch (viewType) {
                case TYPE_ITEM:
                    holder = mAdapter.onCreateViewHolder(parent, viewType);
                    break;
                case TYPE_FOOTER:
                    footer = LayoutInflater.from(mContext).inflate(R.layout.lib_recyle_footview, null);
                     LinearLayout linearLayout= (LinearLayout) footer.findViewById(R.id.loading_layout);
                    StaggeredGridLayoutManager.LayoutParams layoutParams =
                            new StaggeredGridLayoutManager.LayoutParams(
                                  ViewGroup.LayoutParams.MATCH_PARENT,
                                   ViewGroup.LayoutParams.WRAP_CONTENT);
                    layoutParams.setFullSpan(true);
                    linearLayout.setLayoutParams(layoutParams);
                    holder = new FooterViewHolder(footer);
                    break;
            }
            return holder;
        }

        public View getFootView() {
            return footer;
        }
        @Override
        public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
            if (!mHasFooter || position + 1 != getItemCount()) {
                mAdapter.onBindViewHolder(holder, position);
            }
        }
        @Override
        public int getItemCount() {
            return mShowFootVisible ? mAdapter.getItemCount() + 1 : mAdapter.getItemCount();
        }


        @Override
        public int getItemViewType(int position) {
            if (mShowFootVisible && position + 1 == getItemCount()) {
                return TYPE_FOOTER;
            } else {
                return TYPE_ITEM;
            }
        }
        private class FooterViewHolder extends RecyclerView.ViewHolder {
            public ProgressBar progressBar;
            public TextView tvLoading;
            public LinearLayout llyLoading;
            public FooterViewHolder(View itemView) {
                super(itemView);
                progressBar = (ProgressBar) itemView.findViewById(R.id.progress_loading);
                tvLoading = (TextView) itemView.findViewById(R.id.footer_tips);
                llyLoading = (LinearLayout) itemView.findViewById(R.id.loading_layout);
            }
        }
    }
}

最后还有一个就是Adapter的代码:

package com.krain.srecyclerview.srecyclerview;

import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.view.ViewGroup;


public abstract class BaseRecyclerViewAdapter<VH extends RecyclerView.ViewHolder> extends RecyclerView.Adapter<VH> {

    private OnItemClickLisener mItemListener;

    @Override
    public VH onCreateViewHolder(ViewGroup parent, int viewType) {

        View view = getItemView(viewType, parent);
        VH vh = getViewHolder(view);
        view.setOnClickListener(new OnRecyclerAdapterclickListener(vh, viewType));
        view.setOnLongClickListener(new OnRecyclerAdapterclickListener(vh, viewType));
        return vh;
    }

    public abstract VH getViewHolder(View itemView);

    /**
     * 返回item的view
     *
     * @return
     */
    public abstract View getItemView(int viewType, ViewGroup parent);

    /**
     * 返回Adapter每个itemn的数据 可选
     */
    public Object getItem(int position) {
        return null;
    }
    /**
     * item点击事件接口
     *
     * @param mItemListener
     */
    public void setOnItemListener(OnItemClickLisener mItemListener) {
        this.mItemListener = mItemListener;

    }
    @Override
    public abstract void onBindViewHolder(VH holder, int position);

    @Override
    public abstract int getItemCount();


    class OnRecyclerAdapterclickListener implements View.OnClickListener, View.OnLongClickListener {
        VH viewholder;
        int viewType;

        public OnRecyclerAdapterclickListener(VH viewholder, int viewType) {
            this.viewholder = viewholder;
            this.viewType = viewType;
        }

        @Override
        public void onClick(View v) {
            if (mItemListener != null && viewholder.getAdapterPosition() != RecyclerView.NO_POSITION) {
                mItemListener.onItemClick(viewholder.getAdapterPosition(), viewType, viewholder, v);
            }
        }
        @Override
        public boolean onLongClick(View v) {
            if (mItemListener != null && viewholder.getAdapterPosition() != RecyclerView.NO_POSITION) {
                mItemListener.onItemLongClick(viewholder.getAdapterPosition(), viewType, viewholder, v);
            }
            return false;
        }
    }
}

需要注意一哈:
如果想改变Reciview的布局方式在这个修改

    void addChildView(Context contex) {
        ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
        mHeaderView = new ElizabethView(context);
        mRecyclerView = new RecyclerView(context);
        addView(mHeaderView);
        addView(mRecyclerView);
        //mLayoutManager = new LinearLayoutManager(context);
        mLayoutManager = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL);
        mRecyclerView.setLayoutManager(mLayoutManager);
        // 设置Item增加、移除默认动画
        mRecyclerView.setItemAnimator(new DefaultItemAnimator());
        mRecyclerView.addOnScrollListener(onScrollListener);
        mRecyclerView.setHasFixedSize(true);
        mRecyclerView.setLayoutParams(params);
    }
mLayoutManager = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL);这一行就是了改成对应的就可以了,这儿没有封装过几天封装一个出来。
还需要注意一哈就是在滑动判断是不是最后一行,如果是瀑布流就要注意哈判断的方式和其他的不一样,
 if (mLayoutManager instanceof StaggeredGridLayoutManager) {
                //因为StaggeredGridLayoutManager的特殊性可能导致最后显示的item存在多个,所以这里取到的是一个数组
                //得到这个数组后再取到数组中position值最大的那个就是最后显示的position值了
                int[] lastPositions = new int[((StaggeredGridLayoutManager) mLayoutManager).getSpanCount()];
                ((StaggeredGridLayoutManager) mLayoutManager).findLastVisibleItemPositions(lastPositions);
                mLastVisibleItem = findMax(lastPositions);
                mFirstVisibleItem = ((StaggeredGridLayoutManager) mLayoutManager).findFirstVisibleItemPositions(lastPositions)[0];
                setFootviewVisible();
            }

因为StaggeredGridLayoutManager的特殊性可能导致最后显示的item存在多个,所以这里取到的是一个数组,得到这个数组后再取到数组中position值最大的那个就是最后显示的position值了
再去设置最后一行加载更多的显示。
代码稍后放出来,我再精简一哈。
补充一哈,我在后面应为项目要使用到列表和瀑布流这两种的 下拉刷新和上拉加载所以自定义了一个属性来设置这两种方式。以下是代码。传送门

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,下面是一个简单的示例代码: 首先,在XML布局文件中添加一个RecyclerView和SwipeRefreshLayout控件: ```xml <androidx.swiperefreshlayout.widget.SwipeRefreshLayout android:id="@+id/swipe_refresh_layout" android:layout_width="match_parent" android:layout_height="match_parent"> <androidx.recyclerview.widget.RecyclerView android:id="@+id/recycler_view" android:layout_width="match_parent" android:layout_height="match_parent" /> </androidx.swiperefreshlayout.widget.SwipeRefreshLayout> ``` 然后,在Activity或Fragment中初始化RecyclerView和SwipeRefreshLayout,并设置相应的监听器: ```java // 初始化RecyclerView和SwipeRefreshLayout mRecyclerView = findViewById(R.id.recycler_view); mSwipeRefreshLayout = findViewById(R.id.swipe_refresh_layout); // 设置布局管理器和适配器 mLayoutManager = new LinearLayoutManager(this); mAdapter = new MyAdapter(mDataList); mRecyclerView.setLayoutManager(mLayoutManager); mRecyclerView.setAdapter(mAdapter); // 设置下拉刷新监听器 mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { @Override public void onRefresh() { // 进行下拉刷新操作 refreshData(); } }); // 设置上拉加载更多监听器 mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) { super.onScrollStateChanged(recyclerView, newState); if (newState == RecyclerView.SCROLL_STATE_IDLE && isSlideToBottom(recyclerView)) { // 滑动到底部,触发加载更多操作 loadMoreData(); } } }); // 判断RecyclerView是否滑动到底部 private boolean isSlideToBottom(RecyclerView recyclerView) { LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager(); int lastVisibleItemPosition = layoutManager.findLastVisibleItemPosition(); int itemCount = layoutManager.getItemCount(); return lastVisibleItemPosition == (itemCount - 1); } // 进行下拉刷新操作 private void refreshData() { // 在这里进行刷新数据的操作 // 刷新完成后调用mSwipeRefreshLayout.setRefreshing(false)停止刷新动画 } // 进行上拉加载更多操作 private void loadMoreData() { // 在这里进行加载更多数据的操作 // 加载完成后调用mAdapter.notifyDataSetChanged()更新列表 } ``` 需要注意的是,上述代码中的MyAdapter是自定义的RecyclerView适配器,需要根据实际情况进行修改。另外,刷新加载更多操作需要在子线程中进行,可以使用AsyncTask等方式进行异步处理。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值