Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RecyclerView doesn't respect height=wrap_content?

I have a chat screen which contains two views : a recycler view for displaying previous chat and a custom view which encapsulates an edit text, a send button, and another recycler view to let user select other things to send like photos, etc. This custom view is called "Panel".

So, my chat activity has the following layout:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    xmlns:android="http://schemas.android.com/apk/res/android">

    <chat.example.app.widget.Panel
        style="@style/PanelStyle"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|center"
        android:id="@+id/panel" />

    <android.support.v7.widget.RecyclerView
        android:background="@android:color/holo_red_dark"
        android:layout_margin="@dimen/activity_horizontal_margin"
        android:scrollbars="vertical"
        android:id="@+id/previous_chat"
        android:layout_above="@id/panel"
        android:layout_alignParentTop="true"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

</RelativeLayout>

and my "Panel" view has the following layout:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@android:color/white">
    <RelativeLayout
        android:id="@+id/staging_area_root"
        android:layout_gravity="center"
        android:gravity="center"
        android:paddingLeft="5dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <!-- Chat box and send -->
    </RelativeLayout>
    <!-- THIS GUY IS PROBLEMATIC -->
    <android.support.v7.widget.RecyclerView
        android:id="@+id/card_set"
        android:layout_margin="15dp"
        android:layout_below="@id/staging_area_root"
        android:background="@android:color/holo_blue_bright"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
</RelativeLayout>  

The problem is that the recycler view from Panel gobbles up entire screen space. So all I see is Mr. problematic recycler view from Panel class.

Both these recycler views have LinearLayoutManagers assigned to them. No adapters yet.

I have the latest support library in my build.gradle:

compile 'com.android.support:recyclerview-v7:23.2.0'  

and going over the latest android developers blog post:

This release brings an exciting new feature to the LayoutManager API: auto-measurement! This allows a RecyclerView to size itself based on the size of its contents. This means that previously unavailable scenarios, such as using WRAP_CONTENT for a dimension of the RecyclerView, are now possible. You’ll find all built in LayoutManagers now support auto-measurement.

Have I missed something ?

Update 1:

I added an adapter to Mr. problematic recycler view with 0 items in it. Still no solution.

Update2:
Screenshot:

enter image description here

like image 350
An SO User Avatar asked Mar 01 '16 15:03

An SO User


1 Answers

Code snippet taken from the 23.2 RecyclerView onMeasure() call:

if (mLayout.mAutoMeasure) {
        final int widthMode = MeasureSpec.getMode(widthSpec);
        final int heightMode = MeasureSpec.getMode(heightSpec);
        final boolean skipMeasure = widthMode == MeasureSpec.EXACTLY
                && heightMode == MeasureSpec.EXACTLY;
        mLayout.onMeasure(mRecycler, mState, widthSpec, heightSpec);
        if (skipMeasure || mAdapter == null) {
            return;
        }
        if (mState.mLayoutStep == State.STEP_START) {
            dispatchLayoutStep1();
        }
        // set dimensions in 2nd step. Pre-layout should happen with old dimensions for
        // consistency
        mLayout.setMeasureSpecs(widthSpec, heightSpec);
        mState.mIsMeasuring = true;
        dispatchLayoutStep2();

        // now we can get the width and height from the children.
        mLayout.setMeasuredDimensionFromChildren(widthSpec, heightSpec);

        // if RecyclerView has non-exact width and height and if there is at least one child
        // which also has non-exact width & height, we have to re-measure.
        if (mLayout.shouldMeasureTwice()) {
            mLayout.setMeasureSpecs(
                    MeasureSpec.makeMeasureSpec(getMeasuredWidth(), MeasureSpec.EXACTLY),
                    MeasureSpec.makeMeasureSpec(getMeasuredHeight(), MeasureSpec.EXACTLY));
            mState.mIsMeasuring = true;
            dispatchLayoutStep2();
            // now we can get the width and height from the children.
            mLayout.setMeasuredDimensionFromChildren(widthSpec, heightSpec);
        }
    }

The mLayout.setMeasuredDimensionFromChildren() call will do the auto-measuring based off of the size of the children of the RecyclerView. Meaning, a valid RecyclerView.Adapter with 1 or more children is needed for the auto-measurement to trigger.

like image 102
Alex Townsend Avatar answered Sep 29 '22 19:09

Alex Townsend