GridLayoutManager高度無法設定為WRAP_CONTENT(Vertical情況下)
阿新 • • 發佈:2019-02-02
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/,大神帶你飛,不喜勿噴。