I had this issue. I needed to build a UI page that contained a RecyclerView
with an unknown number of elements that should scroll. The page had the the following layout:
LinearLayout
ConstraintLayout
TextView
RecyclerView
TextView
and I wanted heights to be determined procedurally for everything using match_parent
and wrap_content
.
I wanted the RecyclerView
to use all the space available between the two TextViews
.
The key was to give the RecyclerView
an "impossible" constraint, by doing this:
app:layout_constraintTop_toBottomOf="@+id/topTextView"
app:layout_constraintBottom_toTopOf="@+id/bottomTextView"
and adding this:
app:layout_constrainedHeight="true"
If you need to add margin between the top TextView
and RecyclerView
(and/or the bottom TextView
and RecyclerView
) put the margin on the RecyclerView
, not the TextViews
.
Code Examples
Below is the actual code I'm using (with some text styling removed for readability)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#1A1A1C">
<TextView
android:id="@+id/selectcampus_es"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_marginEnd="32dp"
android:layout_marginTop="48dp"
android:text="Pick a campus."
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_marginTop="24dp"
android:layout_marginBottom="24dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constrainedHeight="true"
app:layout_constraintTop_toBottomOf="@+id/selectcampus_es"
app:layout_constraintBottom_toTopOf="@+id/comingsoon_es" />
<TextView
android:id="@+id/comingsoon_es"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_marginEnd="32dp"
android:layout_marginBottom="48dp"
android:text="More campuses coming soon."
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toBottomOf="parent" />
</android.support.constraint.ConstraintLayout>
</LinearLayout>
As a final note, the HolderView
also uses only wrap_content
. Here's that code as well:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<android.support.v7.widget.AppCompatTextView
android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:layout_marginLeft="20dp"
android:layout_marginTop="15dp"
android:text="Avondale"
android:alpha="1"/>
</android.support.constraint.ConstraintLayout>