RecyclerView的layoutmanager为GridLayoutManager时如何使头布局不被单元格约束而能占据整个屏幕的宽度作为一个单独的viewtype

版权声明:请尊重原创,侵权必究 如果想转载或者讨论问题,可以添加微信号 WJ1118825 进行授权获取或者共同交流学习 ,转载请注明原文链接并设置超链接跳转功能,本文链接: https://blog.csdn.net/wjj1996825/article/details/83187653

       之前用RecyclerView的时候一般都是用LinearLayoutManager,这样添加头布局会非常方便,如果是九宫格的话选用LayoutManager就必须用GridLayoutManager了,之前一直以为选用了GridLayoutManager后就只能按照定好的单元格数出itemview,如果突然像LinearLayoutManager一样添加一个占据整个屏幕宽度的HeaderView的话肯定实现不了,所以每次都是把需要做的布局单独家在外面,如果要求和RecyclerView一起滑动的话首先想到的就是外面用NestedScrollView

包裹,但是这样会影响性能和内存损耗,但之前一直以为除了这样做没有别的办法。

       偶然的机会项目中又遇到了这样的需求,需求是这样的,在RecyclerView中每个itemview 是绘制圆角视频特效的GlSurfaceView,但如果使它背景透明绘制出圆角效果就必须得覆盖别的view当滑出屏幕的时候,产品经理为了圆角效果的特效,直接把之前的设计改掉,让整个RecyclerView覆盖整个屏幕,然后让顶部的标题和返回按钮部分作为RecyclerView的一个itemview,我当时感觉可以实现,但真正做的时候发现很坑,我先添加了头布局的方式,然后运行出来发现第一个头布局竟然被限制在了一个单元格的方框中,猛然想起来这样不行,现在用的是GridLayoutManager,然后当时就想改变思路,于是在外面嵌套NestedScrollView,但由于我用的RecyclerView的外面还包裹了一个SwipeToLoadLayout的三方库控件做上拉加载下拉刷新的操作,所以无论怎么解决滑动冲突都不行,而且用NestedScrollView包裹后对里面的滑动的view要求必须是绘制出固定的高度才能滑动,而出现了滑动冲突后刷新加载的事件都无效了,实在悲催,不得不放弃这个自以为唯一可行的解决方案。

         就在实在无助的时候,脑子里面在想,难道一个RecyclerView的每个itemview就不能拥有不同的布局管理器LayoutManager吗?于是Google搜索我的问题,翻 了好几篇博客都不是我想要的答案,就在最后快要绝望放弃的时候,终于找到一篇能解决我的问题的博客(https://blog.csdn.net/FZW_Faith/article/details/51217252),天助我也,太及时了,差点死在这个需求上,为了解决这个需求晚饭都没有吃。哈哈,不发牢骚了,说正题,看下面的解决方案:

我们创建GridLayoutManager布局管理器时会制定一行的单元格数

var layoutManager = GridLayoutManager(this,3)
        recyclerview.layoutManager = layoutManager as RecyclerView.LayoutManager?

其实谷歌都为我们考虑到了,当设置了GridLayoutManager的单元格数,后面的itemview都会遵从这个规律,如果有添加Headview或者Footview的需求,肯定不能局限在其中一个小的单元格中,那么,有没有办法让headerview或者footerview这个itemview占据3个单元格的宽度,单独霸占一行呢?答案是肯定的,我们可以通过setSpanSizeLookup抽象类中的getSpanSize()方法的返回的postion来获取对应的viewtype从而判断是否是headerview来设定每个itemview占据多少个单元格 。

代码如下,在recyclerview的adaper里面:

 // 控制每个itemview所占据的单元格数量,这里实现headerview占据3格,占据一整行
    override fun onAttachedToRecyclerView(recyclerView: RecyclerView) {
        super.onAttachedToRecyclerView(recyclerView)
        var layoutManager:RecyclerView.LayoutManager = recyclerView.layoutManager!!
        if (layoutManager is GridLayoutManager){
            layoutManager.spanSizeLookup = object :GridLayoutManager.SpanSizeLookup(){
                override fun getSpanSize(position: Int): Int {
                    return if(getItemViewType(position) == TYPE_HEAD){
                        layoutManager.spanCount  // headerveiw时返回三个的单元格,从而占据整个一行的宽度
                    }else{
                        1          // 正常情况下返回一个单元格
                    }
                }
            }
        }
    }

这样就可以了,不被坑就不能有经验,今天差点被坑死,但不幸中的万幸,爬出了坑,也积累了对应的经验,写下这篇博客作为纪念与总结!果然是阳光总在风雨后啊,哈哈

猜你喜欢

转载自blog.csdn.net/wjj1996825/article/details/83187653