实现带header和footer功能的RecyclerView——完善篇

在上一篇文章中我们实现了实现带header和footer功能的RecyclerView,见  实现带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的功能很简单,大家看一下源码就明白了。至于更多的功能,我们以后再慢慢补充。

下一章我们会在WrapRecyclerView的基础上实现PullToRefresh,即下拉刷新和上拉加载,敬请期待!

 源码

完整源码请关注公众号:BennuCTech,发送“WrapRecyclerView”获取。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

BennuCTech

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值