RecyclerView 轻松实现下拉刷新,上拉加载更多,添加HeaderView

    xiaoxiao2021-03-25  146

    一,下拉加载更多

    用SwipeRefreshLayout 包裹RecyclerView

    如下布局文件代码所示:

    <android.support.v4.widget.SwipeRefreshLayout android:id="@+id/refresh_layout" android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.v7.widget.RecyclerView android:id="@+id/recylerview" android:layout_width="match_parent" android:layout_height="match_parent"/> </android.support.v4.widget.SwipeRefreshLayout>

    Java代码如下所示:

    mRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.refresh_layout); mRefreshLayout.setColorSchemeColors(Color.BLUE, Color.GREEN, Color.RED, Color.YELLOW); mRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { @Override public void onRefresh() { Log.d(TAG, "refreshing-------------->"); Handler handler = new Handler(); handler.postDelayed(new Runnable() { @Override public void run() { mList.add(0, "新的"); mMyAdapter.notifyDataSetChanged(); mRefreshLayout.setRefreshing(false); } }, 2000); } });

    为RecyclerView添加下拉刷新监听mRefreshLayout.setOnRefreshListener(mOnRefreshListener); 利用以上代码便可简单实现下拉刷新。

    二、上拉加载更多,添加HeaderView

    上拉加载更多、添加HeaderView稍微复杂些,按照下面几个步骤便可实现。 HeaderView:显示头部View NormalView:显示正常条目的View FooterView:显示加载更多的View

    1、重写RecyclerView.Adapter的getItemCount()方法

    因为添加了HeaderView和FooterView,在重写getItemCount()方法的时候要注意加上HeaderView和FooterView2个View的个数,在编程的时候可以根据是否添加了HeaderView和FooterView来动态的设置个数,如:

    @Override public int getItemCount() { return list == null ? totalAddationalItems() : list.size() + totalAddationalItems(); } private int totalAddationalItems() { int offset = 0; if (mIsLoadmore) offset++; if (mIsHeader) offset++; Log.d(TAG,"offset:"+offset); return offset; }

    2、重写RecyclerView.Adapter的getItemViewType()

    利用getItemViewType返回的类型判断是加载HeaderView、NormalView还是FooterView.如:

    private static final int HEADER_TYPE = 0; private static final int NORMAL_TYPE = 1; private static final int FOOTER_TYPE = 2; @Override public int getItemViewType(int position) { int last_item = getItemCount() - 1;//最后一个 Log.d(TAG,"getItemViewType position:"+(position-1)+" last_item:"+last_item); if (position == 0 && mIsHeader) { return HEADER_TYPE; } else if (position == last_item && mIsLoadmore) { return FOOTER_TYPE; }else { return NORMAL_TYPE; } }

    3、重写RecyclerView.Adapter的onCreateViewHolder() 方法

    重写该方法,实现根据不同的类型加载不同的View

    @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { if (viewType == NORMAL_TYPE) { View view = LayoutInflater.from(parent.getContext()) .inflate(R.layout.recycler_item, parent, false); return new MyViewHolder(view); } else if (viewType == FOOTER_TYPE) { mFooterView = LayoutInflater.from(parent.getContext()) .inflate(R.layout.footer_layout, parent, false); mFooterHolder = new MyFooterHolder(mFooterView); return mFooterHolder; } else if (viewType == HEADER_TYPE) { View view = LayoutInflater.from(parent.getContext()) .inflate(R.layout.header_view_layout, parent, false); return new MyHeaderView(view); } else { return null; } }

    4、重新RecyclerView.Adapter的onBindViewHolder()方法

    重写该方法的时候要注意position和数据源List的索引的区别,需要将position-1才和List的索引对称。

    @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { if (NORMAL_TYPE == getItemViewType(position)) { if (list != null && list.size() > position - 1 && position - 1 >= 0) { Log.d(TAG, "onBindViewHolder position:" + (position - 1)); MyViewHolder myViewHolder = (MyViewHolder) holder; myViewHolder.tv.setText(list.get(position - 1)); } } }

    5、处理FooterView 显示加载更多的View

    这一步是处理FooterView的显示和隐藏,当还有数据要加载的时候显示FooterView并请求数据, FooterViewHolder:

    public static class MyFooterHolder extends RecyclerView.ViewHolder { private View mLoadingView; private View mEndView; public MyFooterHolder(View itemView) { super(itemView); mLoadingView = itemView.findViewById(R.id.loading_vs); mEndView = itemView.findViewById(R.id.end_viewstub); } public void setData(ITEM_STATUS status) { switch (status) { case NORMAL: setAllGone(); break; case LOADING: setAllGone(); mLoadingView.setVisibility(View.VISIBLE); Log.d("ad", "ddddd"); break; case END: setAllGone(); break; } } private void setAllGone() { mLoadingView.setVisibility(View.GONE); mEndView.setVisibility(View.GONE); } }

    6、实现RecyclerView.OnScrollListener

    这一步非常重要,用于判断RecyclerView是否滑动到底部。主要是找到mLastVisibleItemPosition的值,根据不同的layoutManager做不同的处理,为RecyclerView添加滚动监听mRecyclerView.addOnScrollListener(mOnScrollListener);

    public void setFooterStatus(MyAdapter.ITEM_STATUS footerStatus) { this.mFooterStatus = footerStatus; changeFooterViewState(); } private void changeFooterViewState(){ if (mMyAdapter != null && mMyAdapter.getFooterHolder() != null){ Log.d(TAG, "changeFooterViewState-------------->"); mMyAdapter.getFooterHolder().setData(this.mFooterStatus); } } SwipeRefreshLayout.OnRefreshListener mOnRefreshListener = new SwipeRefreshLayout.OnRefreshListener() { @Override public void onRefresh() { Log.d(TAG, "refreshing-------------->"); Handler handler = new Handler(); handler.postDelayed(new Runnable() { @Override public void run() { mList.add(0, "新的"); mMyAdapter.notifyDataSetChanged(); mRefreshLayout.setRefreshing(false); } }, 2000); } }; private abstract class CustomOnScrollListener extends RecyclerView.OnScrollListener { private LayoutManagerType mLayoutManagerType; private int mLastVisibleItemPosition; private int[] mLastVisibleItemPositionStaggered; private int mCurrentScrollState; @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager(); if (mLayoutManagerType == null) { if (layoutManager instanceof GridLayoutManager) { mLayoutManagerType = LayoutManagerType.GRID; } else if (layoutManager instanceof LinearLayoutManager) { mLayoutManagerType = LayoutManagerType.LINEAR; } else if (layoutManager instanceof StaggeredGridLayoutManager) { mLayoutManagerType = LayoutManagerType.STAGGERED_GRID; } else { throw new RuntimeException("not support"); } } switch (mLayoutManagerType) { case LINEAR: mLastVisibleItemPosition = ((LinearLayoutManager) layoutManager).findLastVisibleItemPosition(); break; case GRID: mLastVisibleItemPosition = ((GridLayoutManager) layoutManager).findLastVisibleItemPosition(); break; case STAGGERED_GRID: StaggeredGridLayoutManager sg = (StaggeredGridLayoutManager) layoutManager; if (mLastVisibleItemPositionStaggered == null) { mLastVisibleItemPositionStaggered = new int[sg.getSpanCount()]; } sg.findLastVisibleItemPositions(mLastVisibleItemPositionStaggered); mLastVisibleItemPosition = findMax(mLastVisibleItemPositionStaggered); break; } } @Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) { super.onScrollStateChanged(recyclerView, newState); mCurrentScrollState = newState; int visiableItemCount = recyclerView.getLayoutManager().getChildCount(); int totalItemCount = recyclerView.getLayoutManager().getItemCount(); if (visiableItemCount > 0 && mCurrentScrollState == RecyclerView.SCROLL_STATE_IDLE && mLastVisibleItemPosition >= totalItemCount - 1) { onLoadMore(recyclerView); } } public abstract void onLoadMore(RecyclerView recyclerView); } private enum LayoutManagerType { LINEAR, GRID, STAGGERED_GRID, } private RecyclerView.OnScrollListener mOnScrollListener = new CustomOnScrollListener() { @Override public void onLoadMore(RecyclerView recyclerView) { if (mFooterStatus == MyAdapter.ITEM_STATUS.LOADING){ return; } Log.d(TAG, "onLoadMore----->"); if (mList.size() < 30){ requestData(); }else { mMyAdapter.enableLoadmore(false); //mMyAdapter.enableHeader(false); setFooterStatus(MyAdapter.ITEM_STATUS.END); mMyAdapter.notifyDataSetChanged(); } } }; private void requestData() { setFooterStatus(MyAdapter.ITEM_STATUS.LOADING); new Handler().postDelayed(new Runnable() { @Override public void run() { int start = mMyAdapter.getItemCount()-1; mList.add("str"+(mList.size()+1)); mList.add("str"+(mList.size()+1)); mList.add("str"+(mList.size()+1)); if (mList.size() >= 30){ mMyAdapter.enableLoadmore(false); //mMyAdapter.enableHeader(false); setFooterStatus(MyAdapter.ITEM_STATUS.END); }else { setFooterStatus(MyAdapter.ITEM_STATUS.NORMAL); } mMyAdapter.notifyDataSetChanged(); } }, 1500); } private int findMax(int[] lastPositions) { int max = Integer.MIN_VALUE; for (int value : lastPositions) { Log.d(TAG, "value:" + value + " max:" + max); if (value > max) max = value; } return max; }
    转载请注明原文地址: https://ju.6miu.com/read-5257.html

    最新回复(0)