实现带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”获取。

### PyCharm 打开文件显示全的解决方案 当遇到PyCharm打开文件显示全的情况时,可以尝试以下几种方法来解决问题。 #### 方法一:清理缓存并重启IDE 有时IDE内部缓存可能导致文件加载异常。通过清除缓存再启动程序能够有效改善此状况。具体操作路径为`File -> Invalidate Caches / Restart...`,之后按照提示完成相应动作即可[^1]。 #### 方法二:调整编辑器字体设置 如果是因为字体原因造成的内容显示问题,则可以通过修改编辑区内的文字样式来进行修复。进入`Settings/Preferences | Editor | Font`选项卡内更改合适的字号大小以及启用抗锯齿功能等参数配置[^2]。 #### 方法三:检查项目结构配置 对于某些特定场景下的源码视图缺失现象,可能是由于当前工作空间未能正确识别全部模块所引起。此时应该核查Project Structure的Content Roots设定项是否涵盖了整个工程根目录;必要时可手动添加遗漏部分,并保存变更生效[^3]。 ```python # 示例代码用于展示如何获取当前项目的根路径,在实际应用中可根据需求调用该函数辅助排查问题 import os def get_project_root(): current_file = os.path.abspath(__file__) project_dir = os.path.dirname(current_file) while not os.path.exists(os.path.join(project_dir, '.idea')): parent_dir = os.path.dirname(project_dir) if parent_dir == project_dir: break project_dir = parent_dir return project_dir print(f"Current Project Root Directory is {get_project_root()}") ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

BennuCTech

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

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

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

打赏作者

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

抵扣说明:

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

余额充值