1. 程式人生 > >GridLayoutManager高度無法設定為WRAP_CONTENT(Vertical情況下)

GridLayoutManager高度無法設定為WRAP_CONTENT(Vertical情況下)

     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/,大神帶你飛,不喜勿噴。