title: How do I make WRAP_CONTENT work on a RecyclerView
body: <p>I have a <code>DialogFragment</code> that contains a <code>RecyclerView</code> (a list of cards).</p>
  <p>Within this <code>RecyclerView</code> are one or more <code>CardViews</code> that can have any height.</p>
  <p>I want to give this <code>DialogFragment</code> the correct height based on the <code>CardViews</code> that are contained within.</p>
  <p>Normally this would be simple, I would set <code>wrap_content</code> on the <code>RecyclerView</code> like this.</p>
  <pre><code>&lt;android.support.v7.widget.RecyclerView ...
      xmlns:tools=&quot;http://schemas.android.com/tools&quot;
      android:id=&quot;@+id/recycler_view&quot;
      android:layout_width=&quot;match_parent&quot;
      android:layout_height=&quot;wrap_content&quot;   
      android:clickable=&quot;true&quot;   
      android:scrollbars=&quot;vertical&quot; &gt;
  
  &lt;/android.support.v7.widget.RecyclerView&gt;
  </code></pre>
  <p>Because I am using a <code>RecyclerView</code> this does not work:</p>
  <p><a href="https://issuetracker.google.com/issues/37001674" rel="noreferrer">https://issuetracker.google.com/issues/37001674</a></p>
  <p>and</p>
  <p><a href="https://stackoverflow.com/questions/26649406/nested-recycler-view-height-doesnt-wrap-its-content">Nested Recycler view height doesn&#39;t wrap its content</a></p>
  <p>On both of these pages people suggest to extend <code>LinearLayoutManager</code> and to override <code>onMeasure()</code></p>
  <p>I first used the <strong>LayoutManager</strong> that someone provided in the first link:</p>
  <pre><code>public static class WrappingLayoutManager extends LinearLayoutManager {
  
          public WrappingLayoutManager(Context context) {
              super(context);
          }
  
          private int[] mMeasuredDimension = 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);
  
              measureScrapChild(recycler, 0,
                      View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
                      View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
                      mMeasuredDimension);
  
              int width = mMeasuredDimension[0];
              int height = mMeasuredDimension[1];
  
              switch (widthMode) {
                  case View.MeasureSpec.EXACTLY:
                  case View.MeasureSpec.AT_MOST:
                      width = widthSize;
                      break;
                  case View.MeasureSpec.UNSPECIFIED:
              }
  
              switch (heightMode) {
                  case View.MeasureSpec.EXACTLY:
                  case View.MeasureSpec.AT_MOST:
                      height = heightSize;
                      break;
                  case View.MeasureSpec.UNSPECIFIED:
              }
  
              setMeasuredDimension(width, height);
          }
  
          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();
                  measuredDimension[1] = view.getMeasuredHeight();
                  recycler.recycleView(view);
              }
          }
      }
  </code></pre>
  <p>However <strong>this did not work</strong> because</p>
  <p><code>heightSize = View.MeasureSpec.getSize(heightSpec);</code></p>
  <p>returns a very large value that appear to be related to <code>match_parent</code>.</p>
  <p>By commenting  <code>height = heightSize;</code> (in the second switch case) I managed to make the height work but only if a <code>TextView</code> child inside the <code>CardView</code> does not wrap its own text (a long sentence).</p>
  <p>As soon as that <code>TextView</code> wraps it's own text the height SHOULD increase but it doesn't. It calculated the height for that long sentence as a single line, not a wrapped line (2 or more).</p>
  <p>Any advice on how I should improve this <code>LayoutManager</code> so my <code>RecyclerView</code> works with <code>WRAP_CONTENT</code>?</p>
  <p><strong>Edit: This layout manager might work for most people, but it still has problems with scrolling and calculating heights of wrapping textviews</strong></p>
  <pre><code>public class MyLinearLayoutManager extends LinearLayoutManager {
  
  public MyLinearLayoutManager(Context context, int orientation, boolean reverseLayout)    {
      super(context, orientation, reverseLayout);
  }
  
  private int[] mMeasuredDimension = 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 width = 0;
      int height = 0;
      for (int i = 0; i &lt; getItemCount(); i++) {
          measureScrapChild(recycler, i,
                  View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED),
                  View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED),
                  mMeasuredDimension);
  
          if (getOrientation() == HORIZONTAL) {
              width = width + mMeasuredDimension[0];
              if (i == 0) {
                  height = mMeasuredDimension[1];
              }
          } else {
              height = height + mMeasuredDimension[1];
              if (i == 0) {
                  width = mMeasuredDimension[0];
              }
          }
      }
      switch (widthMode) {
          case View.MeasureSpec.EXACTLY:
              width = widthSize;
          case View.MeasureSpec.AT_MOST:
          case View.MeasureSpec.UNSPECIFIED:
      }
  
      switch (heightMode) {
          case View.MeasureSpec.EXACTLY:
              height = heightSize;
          case View.MeasureSpec.AT_MOST:
          case View.MeasureSpec.UNSPECIFIED:
      }
  
      setMeasuredDimension(width, height);
  }
  
      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;
              recycler.recycleView(view);
          }
      }
  }
  </code></pre>