实现带header和footer功能的RecyclerView——完善篇
2017-08-07 16:48
507 查看
在上一篇文章中我们实现了实现带header和footer功能的RecyclerView,见
实现带header和footer功能的RecyclerView
但是由于加入了header,item的position有了变化,导致了RecyclerView中的一些与position有关方法或使用出现问题。本章着重解决一些常用的方法和使用,至于其他的解决方法类似。
首先,重写几个比较常用的方法,如下:
总之涉及到item的position的方法和使用都要格外注意,在需要的时候对position进行相应处理。
比如getChildAdapterPosition,我们想知道item的position。但是由于RecyclerView中实际上使用的是WrapAdapter,所以获取的position是包括header的,所以要减去header的数量。
同理,在findViewHolderForAdapterPostion中,我们想通过外部adapter中item的postion获取该item的ViewHolder。实际上我们是要在WrapAdapter中去取,这时考虑到header需要为这个position加上header的数量才能取到正确的ViewHolder。
上面都是比较简单的,复杂一点比如divider。
在列表中我们经常会用到divider,RecyclerView并不像ListView那样可以很简单的添加divider,需要用户自定义一个ItemDecoration。
当我们定义ItemDecoration时就需要注意与position相关的计算,因为一般情况下divider只是给正常的item来使用,header和footer不需要使用(在其布局中已经包含了)。
由于我们一般用比较简单divider就可以了,所以这里实现了一个很简单的默认divider,如果需要自定义参考即可,代码如下:
关于ItemDecoration的实现网上有太多的文章了,这里就不细说了。主要说说position相关需要注意的地方。
重点关注getItemOffsets这个方法,通过getViewLayoutPosistion获取的position是item在WrapAdapter中的position。
首先判断是否是header或footer,如果是不添加。
普通的item,由于需要判断是否是一行的最后一个(isEnd,在GridLayoutManager或StaggeredGridLayoutManager中),所以要排除掉header对item位置的影响,这里减去header的数量。
通过上面的处理,header和footer的功能基本完善了,如果遇到其他问题,可以参照上面两种情况进行处理。
这样关于WrapRecyclerView的功能就告一段落了,有关onClickListener的功能很简单,大家看一下源码就明白了。至于更多的功能,我们以后再慢慢补充。
本项目的github地址是https://github.com/chzphoenix/PullToRefreshRecyclerView
下一章我们会在WrapRecyclerView的基础上实现PullToRefresh,即下拉刷新和上拉加载,敬请期待!
实现带header和footer功能的RecyclerView
但是由于加入了header,item的position有了变化,导致了RecyclerView中的一些与position有关方法或使用出现问题。本章着重解决一些常用的方法和使用,至于其他的解决方法类似。
首先,重写几个比较常用的方法,如下:
@Override public int getChildAdapterPosition(View child) { return super.getChildAdapterPosition(child) - mWrapAdapter.getHeaderCount(); } @Override public void swapAdapter(Adapter adapter, boolean removeAndRecycleExistingViews) { mWrapAdapter.setAdapter(adapter); super.swapAdapter(mWrapAdapter, removeAndRecycleExistingViews); } @Override public ViewHolder findViewHolderForAdapterPosition(int position) { return super.findViewHolderForAdapterPosition(position + mWrapAdapter.getHeaderCount()); }
总之涉及到item的position的方法和使用都要格外注意,在需要的时候对position进行相应处理。
比如getChildAdapterPosition,我们想知道item的position。但是由于RecyclerView中实际上使用的是WrapAdapter,所以获取的position是包括header的,所以要减去header的数量。
同理,在findViewHolderForAdapterPostion中,我们想通过外部adapter中item的postion获取该item的ViewHolder。实际上我们是要在WrapAdapter中去取,这时考虑到header需要为这个position加上header的数量才能取到正确的ViewHolder。
上面都是比较简单的,复杂一点比如divider。
在列表中我们经常会用到divider,RecyclerView并不像ListView那样可以很简单的添加divider,需要用户自定义一个ItemDecoration。
当我们定义ItemDecoration时就需要注意与position相关的计算,因为一般情况下divider只是给正常的item来使用,header和footer不需要使用(在其布局中已经包含了)。
由于我们一般用比较简单divider就可以了,所以这里实现了一个很简单的默认divider,如果需要自定义参考即可,代码如下:
public void setTransparentDivider(final int sizePx){ addItemDecoration(new ItemDecoration() { @Override public void onDraw(Canvas c, RecyclerView parent, State state) { super.onDraw(c, parent, state); } @Override public void onDrawOver(Canvas c, RecyclerView parent, State state) { super.onDrawOver(c, parent, state); } @Override public void getItemOffsets(Rect outRect, View view, RecyclerView parent, State state) { int position = ((LayoutParams) view.getLayoutParams()).getViewLayoutPosition(); if(mWrapAdapter.isHeader(position) || mWrapAdapter.isFooter(position)){ super.getItemOffsets(outRect, view, parent, state); return; } int index = position - mWrapAdapter.getHeaderCount(); if(isEnd(parent, index)){ if(isVertical(parent)){ outRect.set(0, 0, 0, sizePx); } else{ outRect.set(0, 0, sizePx, 0); } } else{ outRect.set(0, 0, sizePx, sizePx); } } private boolean isVertical(RecyclerView parent){ LayoutManager layout = parent.getLayoutManager(); if(layout instanceof StaggeredGridLayoutManager){ return ((StaggeredGridLayoutManager) layout).getOrientation() == StaggeredGridLayoutManager.VERTICAL; } else if(layout instanceof LinearLayoutManager){ return ((LinearLayoutManager) layout).getOrientation() == LinearLayoutManager.VERTICAL; } return true; } private int getSpanCount(RecyclerView parent){ LayoutManager layout = parent.getLayoutManager(); if(layout instanceof GridLayoutManager){ return ((GridLayoutManager) layout).getSpanCount(); } if(layout instanceof StaggeredGridLayoutManager){ return ((StaggeredGridLayoutManager) layout).getSpanCount(); } return 1; } private boolean isEnd(RecyclerView parent, int index){ int spanCount = getSpanCount(parent); return (index + 1) % spanCount == 0; } }); }
关于ItemDecoration的实现网上有太多的文章了,这里就不细说了。主要说说position相关需要注意的地方。
重点关注getItemOffsets这个方法,通过getViewLayoutPosistion获取的position是item在WrapAdapter中的position。
首先判断是否是header或footer,如果是不添加。
普通的item,由于需要判断是否是一行的最后一个(isEnd,在GridLayoutManager或StaggeredGridLayoutManager中),所以要排除掉header对item位置的影响,这里减去header的数量。
通过上面的处理,header和footer的功能基本完善了,如果遇到其他问题,可以参照上面两种情况进行处理。
这样关于WrapRecyclerView的功能就告一段落了,有关onClickListener的功能很简单,大家看一下源码就明白了。至于更多的功能,我们以后再慢慢补充。
本项目的github地址是https://github.com/chzphoenix/PullToRefreshRecyclerView
下一章我们会在WrapRecyclerView的基础上实现PullToRefresh,即下拉刷新和上拉加载,敬请期待!
相关文章推荐
- 实现带header和footer功能的RecyclerView
- Android中Recyclerview使用13----实现瀑布流遇到的各种问题(item移动,加载更多图片闪烁,以及定制各种类型Header和Footer)
- 封装RecyclerView Adapter 实现可添加多个header和footer,可设置loadingView,低耦合的多种布局。
- RecyclerView中实现addHeaderView,addFooterView功能
- RecyclerView中实现headerView,footerView功能
- XRecyclerView:实现下拉刷新、滚动到底部加载更多以及添加header功能的RecyclerView
- 使用RecyclerView实现带Header和Footer的GridView
- RecyclerView之ViewHolder封装实现点击、长按、headerView和多选功能
- 详解自主实现RecyclerView下拉刷新、上拉加载、Header、Footer以及swiperefreshlayout的部分讲解
- 基于RecyclerView的封装,仿qq侧拉删除效果,实现下拉刷新,上拉加载更多,添加header,添加footer
- RecyclerView实现瀑布流遇到的各种问题(item移动,加载更多图片闪烁,以及定制各种类型Header和Footer)
- Android RecyclerView通用适配器,支持Header、Footer、LoadMore、EmptyView等功能
- RecyclerView之ViewHolder封装实现点击、长按、headerView和多选功能
- 一个精简的实现RecyclerView可添加header和footer的Demo
- RecyclerView:带header&footer&加载更多
- indexablerecyclerview 的使用体验(实现选择城市,选择联系人等需要索引的功能)
- RecyclerView加载不同item并实现其item点击事件,实现添加常用应用的功能
- Android RecyclerView瀑布流布局添加Footer实现上拉加载
- RecyclerView五大开源项目-解决上拉加载、下拉刷新和添加Header、Footer等问题
- RecyclerView中使用CheckBox勾选混乱问题解决以及单选功能的实现