2015-07-28 4 views
7

я пытаюсь решить следующий:RecyclerView с GridLayoutManager пытается решить wrap_content

  • использования RecyclerView
  • с GridLayoutManager
  • с неподвижной сотовой шириной
  • recyclerview изменение размер только на необходимую высоту (wrap_content)

Я стараюсь использовать следующий код, проблема в том, что он не работает, и я hav не обнаружил, что какой-либо рабочий пример не упоминается для правильной перерисовки при изменении ориентации.

public class AutofitRecyclerView extends RecyclerView { 
    private MyGridLayoutManager manager; 
    private int columnWidth = -1; 

    public AutofitRecyclerView(Context context) { 
     super(context); 
     init(context, null); 
    } 

    public AutofitRecyclerView(Context context, AttributeSet attrs) { 
     super(context, attrs); 
     init(context, attrs); 
    } 

    public AutofitRecyclerView(Context context, AttributeSet attrs, int defStyle) { 
     super(context, attrs, defStyle); 
     init(context, attrs); 
    } 

    private void init(Context context, AttributeSet attrs) { 
     if (attrs != null) { 
      int[] attrsArray = { 
        android.R.attr.columnWidth 
      }; 
      TypedArray array = context.obtainStyledAttributes(attrs, attrsArray); 
      columnWidth = array.getDimensionPixelSize(0, -1); 
      array.recycle(); 
     } 

     manager = new MyGridLayoutManager(getContext(), 1); 
     setLayoutManager(manager); 
    } 

    @Override 
    protected void onMeasure(int widthSpec, int heightSpec) { 
     super.onMeasure(widthSpec, heightSpec); 
     if (columnWidth > 0) { 

      int mw = getMeasuredWidth(); 

      int spanCount = Math.max(1, mw/columnWidth); 
      manager.setSpanCount(spanCount); 
     } 

     int numOfFullRows = manager.getItemCount()/manager.getSpanCount(); 

     if(manager.getItemCount() % manager.getSpanCount() > 0) 
     { 
      numOfFullRows++; 
     } 

     if(getChildCount() > 0) { 
      int h = 0; 
      try { 
       h = manager.getChildAt(0).getMeasuredHeight(); 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 

      if(h != 0) { 
       getLayoutParams().height = numOfFullRows * h; 
      } 
     } 
    } 
} 

ответ

-1

Если вы установите ниже свойства, то все ячейки будут иметь фиксированный размер: recyclerView.setHasFixedSize (истина);

8

Основываясь на коде, опубликованном в этом выпуске, я придумал следующее решение, которое поддерживает разные размеры строк и столбцов (хотя я, по общему признанию, не тестировал это), учитывает размеры украшений предметов и обрабатывает их различные режимы измерения.

Вот код:

import android.content.Context; 
import android.graphics.Rect; 
import android.support.v7.widget.GridLayoutManager; 
import android.support.v7.widget.RecyclerView; 
import android.view.View; 
import android.view.ViewGroup; 

public class WrappableGridLayoutManager extends GridLayoutManager { 

    public WrappableGridLayoutManager(Context context, int spanCount) { 
     super(context, spanCount); 
    } 

    private int[] measuredSize = new int[2]; 

    @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), measuredSize); 

      if (i % spanCount == 0) { 
       spanWidth = measuredSize[0]; 
       spanHeight = measuredSize[1]; 
      } else { 
       if (getOrientation() == VERTICAL) { 
        spanWidth += measuredSize[0]; 
        spanHeight = Math.max(spanHeight, measuredSize[1]); 
       } else { 
        spanWidth = Math.max(spanWidth, measuredSize[0]); 
        spanHeight += measuredSize[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 finalWidth; 
     int finalHeight; 

     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 = null; 
     try { 
      view = recycler.getViewForPosition(position); 
     } catch (Exception ex) { 
      // try - catch is needed since support library version 24 
     } 


     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); 
     } 
    } 
} 
+0

Почему это downvoted? Это улучшенная версия кода соединителя и копируется из кода, который я написал для рабочего, опубликованного приложения, поэтому я знаю, что он работает. – Nantoka

+0

Сдвиги были, вероятно, от лиц, которые могут иметь только один предмет и, например, 2 столбца - в этом случае ваш менеджер задает высоту просмотра recycler равным 0 (6.0 Nexus 7). ссылка на git в другом ответе выше работает отлично (я не использую декорирование) – snachmsm

+1

Спасибо, что сообщили мне. Я рассмотрю это, как только найду какое-то время. – Nantoka

Смежные вопросы