GridLayoutManager高度无法设置为WRAP_CONTENT(Vertical情况下)

本文探讨了在使用GridLayoutManager时遇到的高度无法设置为WRAP_CONTENT的问题,特别是在垂直布局下。作者指出,即使有多个子View,GridLayoutManager的高度始终为MATCH_PARENT。为了解决这个问题,提出了一个方法,即创建GridLayoutManager的子类并进行定制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

     RecyclerView相信大家都不会陌生,作为ListView的替代控件,为大家提供了很多方便,在使用的时候我们会发现一个setLayoutManager这样一个方法,他的参数可以是LinearLayoutManager,GridLayoutManager以及特别酷炫的StaggeredGridLayoutManager,至于区别呢,大家自己动手,今天主要记录一下GridLayoutManager这个类。

  GridLayoutManager主要是实现GridView这样的效果的,用着用着你会发现一个坑,那就是这个家伙高度无法设置为Wrap_content,就是说无论有几个子View高度都是一样的(Vertical情况下),都是MATCH_PARENT,效果如下:


   解决的方式是写个子类继承GridLayoutManager,如下:

class WrappableGridLayoutManager extends GridLayoutManager {
        public WrappableGridLayoutManager(Context context, int spanCount) {
            super(context, spanCount);
        }
        private int[] mMeasuredDimension = new int[2];

        @Override
        public boolean canScrollVertically() {
            return false;
        }

        @Override
        public void onMeasure(RecyclerView.Recycler recycler, RecyclerView.State state, int widthSpec, int heightSpec) {
            final int widthMode = View.MeasureSpec.getMode(widthSpec);
            final int heightMode = View.MeasureSpec.getMode(heightSpec);
            final int widthSize = View.MeasureSpec.getSize(widthSpec);
            final int heightSize = View.MeasureSpec.getSize(heightSpec);

            int spanWidth = 0;
            int spanHeight = 0;
            int viewWidth = 0;
            int viewHeight = 0;

            int spanCount = getSpanCount();

            for (int i = 0; i < getItemCount(); i++) {
                measureScrapChild(recycler, i, View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED), View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED), mMeasuredDimension);

                if(i%spanCount==0){
                    spanWidth=mMeasuredDimension[0];
                    spanHeight=mMeasuredDimension[1];
                }else{
                    if(getOrientation()==VERTICAL){
                        spanWidth+=mMeasuredDimension[0];
                        spanHeight=Math.max(spanHeight,mMeasuredDimension[1]);
                    }else{
                        spanWidth=Math.max(spanWidth,mMeasuredDimension[0]);
                        spanHeight+=mMeasuredDimension[1];
                    }
                }

                if(i%spanCount==spanCount-1||i==getItemCount()-1){
                    if(getOrientation()==VERTICAL){
                        viewWidth=Math.max(viewWidth,spanWidth);
                        viewHeight+=spanHeight;
                    }else{
                        viewWidth+=spanWidth;
                        viewHeight=Math.max(viewHeight,spanHeight);
                    }
                }
            }

            int finalHeight;
            int finalWidth;

            switch (widthMode){
                case View.MeasureSpec.EXACTLY:
                    finalWidth=widthSize;
                    break;
                case View.MeasureSpec.AT_MOST:
                    finalWidth=Math.min(widthSize,viewWidth);
                    break;
                case View.MeasureSpec.UNSPECIFIED:
                    finalWidth=viewWidth;
                    break;
                default:
                    finalWidth=widthSize;
                    break;
            }

            switch (heightMode){
                case View.MeasureSpec.EXACTLY:
                    finalHeight=heightSize;
                    break;
                case View.MeasureSpec.AT_MOST:
                    finalHeight=Math.min(heightSize,viewHeight);
                    break;
                case View.MeasureSpec.UNSPECIFIED:
                    finalHeight=viewHeight;
                    break;
                default:
                    finalHeight=heightSize;
                    break;
            }
            setMeasuredDimension(finalWidth,finalHeight);
        }

        private void measureScrapChild(RecyclerView.Recycler recycler, int position, int widthSpec, int heightSpec, int[] measuredDimension) {

            View view = recycler.getViewForPosition(position);

            if (view != null) {

                RecyclerView.LayoutParams p = (RecyclerView.LayoutParams) view.getLayoutParams();

                int childWidthSpec = ViewGroup.getChildMeasureSpec(widthSpec,
                        getPaddingLeft() + getPaddingRight(), p.width);
                int childHeightSpec = ViewGroup.getChildMeasureSpec(heightSpec,
                        getPaddingTop() + getPaddingBottom(), p.height);

                view.measure(childWidthSpec, childHeightSpec);

                measuredDimension[0] = view.getMeasuredWidth() + p.leftMargin + p.rightMargin;
                measuredDimension[1] = view.getMeasuredHeight() + p.bottomMargin + p.topMargin;

                Rect decoratorRect=new Rect();
                calculateItemDecorationsForChild(view,decoratorRect);
                measuredDimension[0]+=decoratorRect.left;
                measuredDimension[0]+=decoratorRect.right;
                measuredDimension[1]+=decoratorRect.top;
                measuredDimension[1]+=decoratorRect.bottom;

                recycler.recycleView(view);
            }
        }
    }

 使用上述的类之后呢,效果就是 
 

当然,我使用了addItemDecotation方法,这个就不多说了。打个广告http://stay4it.com/,大神带你飞,不喜勿喷。

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值