recyclerview gridlayoutmanager 怎么设置列数

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了recyclerview gridlayoutmanager 怎么设置列数相关的知识,希望对你有一定的参考价值。

直接用addView(child, width, height).size()来设置就可以了。因为GridLayout里面的组件是在变化的,所有需要动态设置子组件的Size和它们之间的间距。还可以这么做:在父类容器中把子类容器的参数通过修改子类容器构造函数的方式传给子类容器,这样就可以在父类容器中直接修改子类容器的属性了。 参考技术A GridLayoutManager gridLayoutManager = new GridLayoutManager(this, 2);
new的时候就可以把列数传进去

Android RecyclerView源码学习

RecyclerView 的三驾马车

LayoutManager

掌管RecyclerView的布局,你可以通过它实现一个listview、gridview、瀑布流等效果。LayoutManager主要作用与RecyclerView的measure和layout过程中。LayoutManager是RecyclerView中的一个内部抽象类,具体实现类有GridLayoutManager,LinearLayoutManager,StaggerLayoutManager等。每一个LayoutManager只能和一个RecyclerView绑定,调用setLayoutManager后,当一个LayoutManager被绑定到RecyclerView的时候,会回调LayoutManager的onAttachedToWindow接口。

measure

视图测绘的过程中,ViewRootImpl会执行perforMeasure方法,然后View的measure方法会被调用,同时注意measure方法是final不可重写,同时在measure中调用了相应View的onMeasure,所以我们只要查看onMeasure即可。我们可以实现LayoutManager中的onMeasure方法完成整个recyclerView的测量,来标定其大小,否则RecyclerView会直接调用其默认measure方法,也就是我们通常设置在LayoutParams中的大小,完成对RececylerView整个大小的measure。当通过adapter向RecyclerView中添加child view后,在进行addView的时候又会根据子View的LayoutParams进行child view的布局。

layout

layout则由onLayout中实现,调用 dispatchLayout() ,其中调用 onLayoutChildren,即可以调用到LayoutManager具体实现的onLayoutChildren。

在RecyclerView 进行 onMeasure的时候,调用了如下代码:

        if (mLayout == null) 
            defaultOnMeasure(widthSpec, heightSpec);
         else 
            mLayout.onMeasure(mRecycler, mState, widthSpec, heightSpec);
        

如果我们设置了LayoutManager,那么则由LayoutManager的onMeasure来完成测绘。然后去看实现类,以LinearLayoutManager为例,我们会发现其中并没有onMeasure的实现,这是因为

Adapter

LayoutManager负责布局,而adapter就是负责数据,以及每一个child view的提供。

ViewHolder

adapter中getCount,getItem等方法有点类似ListView,ViewHolder有点类似ListView中我们自定义用来回收利用convertView 的holder。只不过这里进一步的封装,并有recyclerview去调度管理。

ViewHolder构造代码如下:

        public ViewHolder(View itemView) 
            if (itemView == null) 
                throw new IllegalArgumentException("itemView may not be null");
            
            this.itemView = itemView;
        

其中将我们定义的View绑定在了ViewHolder中。通过自定义adapter,主要重写的方法是onCreateViewHolder和onBindViewHolder。我们的onCreateViewHolder会在Adapter中的 createViewHolder调用,代码如下:

        public final VH createViewHolder(ViewGroup parent, int viewType) 
            TraceCompat.beginSection(TRACE_CREATE_VIEW_TAG);
            final VH holder = onCreateViewHolder(parent, viewType);
            holder.mItemViewType = viewType;
            TraceCompat.endSection();
            return holder;
    

而createViewHolder又会在getViewForPosition方法中被调用,其中会经历检查无用的ViewHolder,可以回收的ViewHolder一系列过程,最后如果没有会调用adapter的createViewHolder,在其中还会调用bindViewHolder,也就是我们实现的方法完成视图和数组的绑定。

ViewHolder中的ItemView

ItemDecoration

ItemDecoration负责每一个ItemView的padding修整,背景以及蒙层绘制。

在说明ItemDecoration之前首先要看一下view中draw事件的传递:

View的绘制过程通过dispatchView实现,会调用所有子view的draw方法,draw事件被一层一层传递下去。在View的默认实现draw中,遵循以下流程:
1. 绘制背景 drawBackground
2. 绘制视图内容,即调用自身的 onDraw
3. 绘制child view

使用ItemDecoration,主要通过覆写以下方法:

getItemOffsets

可以通过对outRect.set的设置,设置list中每个item的padding值。在RecyclerView 对子view,也就是每个item进行测绘的时候,measureChild中有以下代码:

onDraw

RecyclerView 被父布局调用draw方法,draw方法中关键代码:

    public void draw(Canvas c) 
        super.draw(c);
        final int count = mItemDecorations.size();
        for (int i = 0; i < count; i++) 
            mItemDecorations.get(i).onDrawOver(c, this, mState);
        
        ...
    

其中super.draw 调用了view的默认实现,那么会调用自身的onDraw方法,Recyclerview的onDraw中有:

    public void onDraw(Canvas c) 
        super.onDraw(c);
        final int count = mItemDecorations.size();
        for (int i = 0; i < count; i++) 
            mItemDecorations.get(i).onDraw(c, this, mState);
        
    

也就是说,recyclerview进行绘制的时候,首先绘制背景,然后调用了ItemDecoration 的onDraw方法,之后对child进行绘制,然后最后调用了onDrawOver方法。因为Canvas是每一层都绘制在原始的层面之上的,所以我们可以认为ItemDecoration中,onDraw是绘制每个item的背景,onDrawOver是最后再在最上面绘制一层。所以我们可以利用这两个方法绘制背景或者绘制蒙层。而getViewForPosition这个方法,则是由LayoutManager在onLayoutChildren布局的时候,最终调用到的方法:

        View next(RecyclerView.Recycler recycler) 
            if (mScrapList != null) 
                return nextViewFromScrapList();
            
            final View view = recycler.getViewForPosition(mCurrentPosition);
            mCurrentPosition += mItemDirection;
            return view;
        

measureChild 时候有 getItemDecorInsetsForChild,其中调用了getItemOffsets,然后依据此计算了 child 中外层layout的params,实现child的测绘,

以上是关于recyclerview gridlayoutmanager 怎么设置列数的主要内容,如果未能解决你的问题,请参考以下文章

关于RecyclerView

recyclerview 内的 RecyclerView 只显示父 recyclerview 的最后一项

RecyclerView详解

RecyclerView

RecyclerView嵌套RecyclerView问题

RecyclerView小结