RecyclerView上拉刷新,下拉加载更多

来源:互联网 发布:淘宝衣服质量好的店铺 编辑:程序博客网 时间:2024/05/22 15:25

RecyclerView上拉刷新,下拉加载更多

经常在写项目的时候都会碰到RecyclerView上拉刷新,下拉加载更多的功能,今天自己来捋一捋。

效果图

这里写图片描述

下拉刷新(SwipeRefreshLayout)

这是Google自己出的下拉刷新控件,其实还挺好看的,这里我们只要知道其中几个方法就可以了。
1. setColorSchemeResources
2. setOnRefreshListener
第一个是设置刷新时小圆圈的颜色,可以设置4中颜色切换。
第二个方法是设置刷新监听。这个接口里面有个onRefresh方法,刷新任务就在这里面执行。
所以总而言之下拉刷新才用官方的还是so easy.
在刷新任务完成后,你就可以把新数注入到adapter里面,刷新下就可以完成下拉刷新。

上拉加载更多

首先需要判断是否滑动到底部了,所以写个抽象类,继承RecyclerView的OnScrollListener

public abstract class RecyclerOnScrollListener extends RecyclerView.OnScrollListener {    private int mPreviousTotal = 0;    private boolean mLoading = true;    int mFirstVisibleItem, mVisibleItemCount, mTotalItemCount;//第一个item,显示的item总数,整个item总数    private int currentPage = 1;    private LinearLayoutManager mLinearLayoutManager;    public RecyclerOnScrollListener(            LinearLayoutManager linearLayoutManager) {        this.mLinearLayoutManager = linearLayoutManager;    }    @Override    public void onScrolled(RecyclerView recyclerView, int dx, int dy) {        super.onScrolled(recyclerView, dx, dy);        mVisibleItemCount = recyclerView.getChildCount();        mTotalItemCount = mLinearLayoutManager.getItemCount();        mFirstVisibleItem = mLinearLayoutManager.findFirstVisibleItemPosition();        if (mLoading) {            if (mTotalItemCount > mPreviousTotal) {                mLoading = false;                mPreviousTotal = mTotalItemCount;            }        }        if (!mLoading                && (mTotalItemCount - mVisibleItemCount) <= mFirstVisibleItem) {            currentPage++;            onLoadMore(currentPage);            mLoading = true;        }    }    public abstract void onLoadMore(int currentPage);}

这个类主要是判断是否滚动到了底部,滚动到了底部就去执行加载更多方法

添加底部加载更多布局

因为加载更多是属于耗时操作,为了提高用户体验,所以很有必要加个进度条提示。
进度条可以当做为一个item,在滑动到最后的时候就让他显示出来。
这里我采用了牛人的一个类,来辅助我们实现这个效果。站在巨人的肩膀上就可以看得更远。
到时直接把自己的适配器传递进去就行了。先贴上大神的代码

public class HeaderViewRecyclerAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {    private static final int HEADERS_START = Integer.MIN_VALUE;    private static final int FOOTERS_START = Integer.MIN_VALUE + 10;    private static final int ITEMS_START = Integer.MIN_VALUE + 20;    private static final int ADAPTER_MAX_TYPES = 100;    private RecyclerView.Adapter mWrappedAdapter;    private List<View> mHeaderViews, mFooterViews;    private Map<Class, Integer> mItemTypesOffset;    /**     * Construct a new header view recycler adapter     * @param adapter The underlying adapter to wrap     */    public HeaderViewRecyclerAdapter(RecyclerView.Adapter adapter) {        mHeaderViews = new ArrayList<View>();        mFooterViews = new ArrayList<View>();        mItemTypesOffset = new HashMap<Class, Integer>();        setWrappedAdapter(adapter);    }    /**     * Replaces the underlying adapter, notifying RecyclerView of changes     * @param adapter The new adapter to wrap     */    public void setAdapter(RecyclerView.Adapter adapter) {        if(mWrappedAdapter != null && mWrappedAdapter.getItemCount() > 0) {            notifyItemRangeRemoved(getHeaderCount(), mWrappedAdapter.getItemCount());        }        setWrappedAdapter(adapter);        notifyItemRangeInserted(getHeaderCount(), mWrappedAdapter.getItemCount());    }    @Override    public int getItemViewType(int position) {        int hCount = getHeaderCount();        if (position < hCount) return HEADERS_START + position;        else {            int itemCount = mWrappedAdapter.getItemCount();            if (position < hCount + itemCount) {                return getAdapterTypeOffset() + mWrappedAdapter.getItemViewType(position - hCount);            }            else return FOOTERS_START  + position - hCount - itemCount;        }    }    @Override    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {        if (viewType < HEADERS_START + getHeaderCount())            return new StaticViewHolder(mHeaderViews.get(viewType - HEADERS_START));        else if (viewType < FOOTERS_START + getFooterCount())            return new StaticViewHolder(mFooterViews.get(viewType - FOOTERS_START));        else {            return mWrappedAdapter.onCreateViewHolder(viewGroup, viewType - getAdapterTypeOffset());        }    }    @Override    public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) {        int hCount = getHeaderCount();        if (position >= hCount && position < hCount + mWrappedAdapter.getItemCount())            mWrappedAdapter.onBindViewHolder(viewHolder, position - hCount);    }    /**     * Add a static view to appear at the start of the RecyclerView. Headers are displayed in the     * order they were added.     * @param view The header view to add     */    public void addHeaderView(View view) {        mHeaderViews.add(view);    }    /**     * Add a static view to appear at the end of the RecyclerView. Footers are displayed in the     * order they were added.     * @param view The footer view to add     */    public void addFooterView(View view) {        mFooterViews.add(view);    }    @Override    public int getItemCount() {        return getHeaderCount() + getFooterCount() + getWrappedItemCount();    }    /**     * @return The item count in the underlying adapter     */    public int getWrappedItemCount() {        return mWrappedAdapter.getItemCount();    }    /**     * @return The number of header views added     */    public int getHeaderCount() {        return mHeaderViews.size();    }    /**     * @return The number of footer views added     */    public int getFooterCount() {        return mFooterViews.size();    }    private void setWrappedAdapter(RecyclerView.Adapter adapter) {        if (mWrappedAdapter != null) mWrappedAdapter.unregisterAdapterDataObserver(mDataObserver);        mWrappedAdapter = adapter;        Class adapterClass = mWrappedAdapter.getClass();        if(!mItemTypesOffset.containsKey(adapterClass)) putAdapterTypeOffset(adapterClass);        mWrappedAdapter.registerAdapterDataObserver(mDataObserver);    }    private void putAdapterTypeOffset(Class adapterClass) {        mItemTypesOffset.put(adapterClass, ITEMS_START + mItemTypesOffset.size() * ADAPTER_MAX_TYPES);    }    private int getAdapterTypeOffset() {        return mItemTypesOffset.get(mWrappedAdapter.getClass());    }    private RecyclerView.AdapterDataObserver mDataObserver = new RecyclerView.AdapterDataObserver() {        @Override        public void onChanged() {            super.onChanged();            notifyDataSetChanged();        }        @Override        public void onItemRangeChanged(int positionStart, int itemCount) {            super.onItemRangeChanged(positionStart, itemCount);            notifyItemRangeChanged(positionStart + getHeaderCount(), itemCount);        }        @Override        public void onItemRangeInserted(int positionStart, int itemCount) {            super.onItemRangeInserted(positionStart, itemCount);            notifyItemRangeInserted(positionStart + getHeaderCount(), itemCount);        }        @Override        public void onItemRangeRemoved(int positionStart, int itemCount) {            super.onItemRangeRemoved(positionStart, itemCount);            notifyItemRangeRemoved(positionStart + getHeaderCount(), itemCount);        }        @Override        public void onItemRangeMoved(int fromPosition, int toPosition, int itemCount) {            super.onItemRangeMoved(fromPosition, toPosition, itemCount);            int hCount = getHeaderCount();            // TODO: No notifyItemRangeMoved method?            notifyItemRangeChanged(fromPosition + hCount, toPosition + hCount + itemCount);        }    };    private static class StaticViewHolder extends RecyclerView.ViewHolder {        public StaticViewHolder(View itemView) {            super(itemView);        }    }}

这个类很好用,可以随意添加头和尾。它的主要原理也就是先获取源数据的item数,然后根据你添加的布局类型(头或者尾)去动态的添加到recyclerview里面。
最后贴上activity源代码吧,看看如何使用

public class MainActivity extends AppCompatActivity implements SwipeRefreshLayout.OnRefreshListener {    private SwipeRefreshLayout mRefreshLayout;    private RecyclerView mRecyclerView;    private MyAdapter mAdapter;    private List<String> mLists;    private HeaderViewRecyclerAdapter mHeaderAdapter;    private List<String> list=new ArrayList<>();    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        mRefreshLayout= (SwipeRefreshLayout) findViewById(R.id.refreshlayout);        mRecyclerView= (RecyclerView) findViewById(R.id.recyclerview);        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);        //如果可以确定每个item的高度是固定的,设置这个选项可以提高性能        mRecyclerView.setHasFixedSize(true);        mRecyclerView.setLayoutManager(linearLayoutManager);        mRefreshLayout.setColorSchemeResources(                R.color.colorAccent,                R.color.colorPrimary,                R.color.read,                R.color.blue        );        mRefreshLayout.setOnRefreshListener(this);        initdata();        mAdapter=new MyAdapter(MainActivity.this,mLists);        mHeaderAdapter=new HeaderViewRecyclerAdapter(mAdapter);        mRecyclerView.setAdapter(mHeaderAdapter);        initFootView();        mRecyclerView.addOnScrollListener(new RecyclerOnScrollListener(linearLayoutManager) {            @Override            public void onLoadMore(int currentPage) {                loadMoreData();            }        });    }    private void initFootView() {        View loadMoreView = LayoutInflater                .from(MainActivity.this)                .inflate(R.layout.item_foot_layout, mRecyclerView, false);        mHeaderAdapter.addFooterView(loadMoreView);    }    private void initdata() {        mLists=new ArrayList<>();        for (int i=0;i<15;i++){            mLists.add(""+i+" itme");        }    }    /**     * 测试数据,延迟两秒执行     */    private void loadMoreData(){        Handler handler=new Handler();        handler.postDelayed(new Runnable() {            @Override            public void run() {                loadData();            }        },2000);    }    private void loadData(){        list.clear();        for (int i=0;i<5;i++){            list.add("上拉加载出来的数据");        }        mLists.addAll(list);        mHeaderAdapter.notifyDataSetChanged();    }    @Override    public void onRefresh() {        Handler handler=new Handler();        handler.postDelayed(new Runnable() {            @Override            public void run() {                mRefreshLayout.setRefreshing(false);                Toast.makeText(MainActivity.this,"数据刷新了",Toast.LENGTH_SHORT).show();            }        },2000);    }}

这里数据都是测试数据,实际上可以根据自己需求去获取的,获取完后添加到原数据里面,然后刷新一下就OK了(这里先不用考虑局部刷新……)。

0 0
原创粉丝点击