I have a view constrained to bottom of the parent. I also have text fields on top. how ever when the keyboard shows up, it will push bottom views up which will cover my text fields.
I have everything inside a scroll view, keyboard should cover the bottom view and I should be able to scroll to bottom to reach the bottom view.
Here is a simple example. I manually increased the height to reproduce the problem easier. I actually have more views, this is just for demonstration.
note that fillViewPort is also enabled.
<?xml version="1.0" encoding="utf-8"?>
<ScrollView 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:fillViewport="true">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:id="#+id/edit_text_1"
android:layout_width="0dp"
android:layout_height="180dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<EditText
android:id="#+id/edit_text_2"
android:layout_width="0dp"
android:layout_height="180dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/edit_text_1" />
<View
android:id="#+id/bottom_view"
android:layout_width="0dp"
android:layout_height="160dp"
android:background="#color/grey_500"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>
You just simply need to put the ScrollView inside a ConstraintLayout
like this:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:layout_width="0dp"
android:layout_height="180dp"
android:inputType="textPersonName"
android:ems="10"
android:id="#+id/edit_text_1"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<EditText
android:layout_width="0dp"
android:layout_height="180dp"
android:inputType="textPersonName"
android:ems="10"
android:id="#+id/edit_text_2"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="#+id/edit_text_1"/>
<View
android:layout_width="0dp"
android:layout_height="160dp"
android:id="#+id/bottom_view"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="#+id/edit_text_2"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>
</androidx.constraintlayout.widget.ConstraintLayout>
Related
I have a layout where the main content is scrollable. At the same time the confirm button is always visible at the bottom so no matter where you are scrolling you can always confirm and see the button.
Whenever I touch a EditText the ScrollView scrolls up so the keyboard does not hide the EditText. This is done using android:windowSoftInputMode="adjustResize".
The problem is, that the button always also scrolls up when I touch the EditText. I do not want this behaviour. I want the button to stay hidden behind the keyboard.
Here is the layout I use:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context=".SecondFragment">
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="0dp"
android:fillViewport="true"
app:layout_constraintBottom_toTopOf="#+id/button_second"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<EditText
android:layout_width="200dp"
android:layout_height="wrap_content"
android:layout_marginTop="300dp"
android:hint="TYPE..."
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>
<Button
android:id="#+id/button_second"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="20dp"
android:text="#string/previous"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
And here are two pictures demonstrating:
On the second picture, the Button also scrolls up. But I only want the keyboard below the EditText the button shall stay hidden at the bottom behind the keyboard (Like it would without adjustResize
EDIT:
As suggested with FrameLayout it works when I have no content that needs to scroll. But once I add another EditText like below it stops working again (I am also unfamiliar with FrameLayout, I always only use ConstraintLayout, So I assume somehow the ScrollView has to stay on top of the button anyway)
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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"
tools:context=".SecondFragment">
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="top|center"
app:layout_constraintBottom_toTopOf="#+id/button_second"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<EditText
android:id="#+id/editText"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:layout_marginTop="300dp"
android:hint="TYPE..."
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<EditText
android:layout_width="200dp"
android:layout_height="wrap_content"
android:hint="TYPE..."
android:layout_marginTop="400dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.502"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/editText" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>
<Button
android:id="#+id/button_second"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="20dp"
android:layout_gravity="bottom|center"
android:text="#string/previous"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</FrameLayout>
Is this what you expected?
activity_main.xml
<FrameLayout 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"
tools:context=".MainActivity">
<include
layout="#layout/layout_item"
/>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="#+id/floatingActionButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:src="#android:drawable/ic_menu_add"
android:layout_gravity="bottom|right"
android:layout_marginBottom="16dp"
android:clickable="true" />
</FrameLayout>
layout_item.xml
<FrameLayout 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"
>
<EditText
android:layout_width="200dp"
android:layout_height="wrap_content"
android:layout_gravity="bottom|center"
android:layout_marginBottom="200dp"
android:hint="TYPE..." />
<Button
android:id="#+id/button_second"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|center"
android:layout_marginBottom="20dp"
android:text="previous"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</FrameLayout>
Hey I used windowSoftInputMode in my android manifest. It working fine in single line text in EditText. I want to do same thing in my multiline text in my EditText.
<activity android:name="XYZActivity"
android:windowSoftInputMode="adjustPan"/>
Chat.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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="match_parent"
android:layout_height="match_parent"
android:background="#color/white">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="0dp"
android:paddingStart="10dp"
android:paddingEnd="10dp"
android:paddingBottom="10dp"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintBottom_toTopOf="#+id/guideline"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<androidx.constraintlayout.widget.Guideline
android:id="#+id/guideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.90" />
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/inputContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/grey"
android:paddingTop="10dp"
android:paddingBottom="10dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/guideline"
app:layout_constraintVertical_bias="1">
<EditText
android:id="#+id/editTextContainer"
android:layout_width="200dp"
android:layout_height="match_parent"
android:fadeScrollbars="false"
android:inputType="textMultiLine"
android:scrollbars="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
Working in single line text
But it's not working in multiline text
Expected output
You should change the bottom constraint of your recyclerview to
app:layout_constraintBottom_toTopOf="#+id/inputContainer"
The position of the guideline won't change when the inputContainer changes size. It will stay at 90%.
I'm trying to put a ConstraintLayout inside a NestedScrollView, but there is a line that separates the ConstraintLayout. I can't place anything underneath that invisible line. I have been trying for hours and can't find the issue.
<?xml version="1.0" encoding="utf-8"?>
<layout 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">
<androidx.core.widget.NestedScrollView
android:id="#+id/premium_layout_id"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#BFFFFFFF"
android:focusableInTouchMode="true"
android:tag="layout/fragment_premium"
app:layout_constraintTop_toTopOf="parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".PremiumFragment">
<ImageView
android:id="#+id/launcher_id"
android:layout_width="185dp"
android:layout_height="185dp"
android:layout_marginTop="25dp"
android:layout_marginBottom="20dp"
android:contentDescription="TODO"
app:layout_constraintBottom_toTopOf="#+id/premium_text_id"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="#drawable/launch_premium" />
<TextView
android:id="#+id/premium_text_id"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="220dp"
android:text="#string/launch_to_premium"
android:textSize="24sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyclerView2"
android:layout_width="383dp"
android:layout_height="196dp"
android:layout_marginTop="24dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/premium_text_id" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>
</layout>
With a little bit of messing around I was able to get what you are looking for. The key is to use android:fillViewport="true" in the NestedScrollView
<?xml version="1.0" encoding="utf-8"?>
<layout 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">
<androidx.core.widget.NestedScrollView
android:id="#+id/premium_layout_id"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#BFFFFFFF"
android:focusableInTouchMode="true"
android:fillViewport="true"
android:tag="layout/fragment_premium">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ImageView
android:id="#+id/launcher_id"
android:layout_width="180dp"
android:layout_height="180dp"
android:layout_marginTop="25dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="#drawable/launch_premium" />
<TextView
android:id="#+id/premium_text_id"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/launch_to_premium"
android:textSize="24sp"
android:layout_marginTop="20dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/launcher_id" />
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyclerView2"
android:layout_width="383dp"
android:layout_height="196dp"
android:layout_marginTop="24dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/premium_text_id" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>
</layout>
You need to add a attribute android:fillViewport="true" in your NestedScrollView
<androidx.core.widget.NestedScrollView
android:id="#+id/premium_layout_id"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#BFFFFFFF"
android:focusableInTouchMode="true"
android:fillViewport="true" <-- add this
android:tag="layout/fragment_premium">
why?
fillViewport allows NestedScrollView to extend its height equals to the full height of the device screen height in the cases when the child of scroll view has less height.
this blog Will explain more about it.
what I want to achive
A scrollView which expends the free vertical space only if needed and a button which is appended on bottom of that scrollView but not hidden by the footer when the amount of the items in the scroll view increases.
whats the problem
scrollView android:layout_height = wrap content:
the button stays at the bottom of the scrollView. But then, if the ScrollView extends, the button is hidden behind the footer.
scrollView android:layout_height = 0dp:
the button stays visible while the scrollView extends the screen height. But then the button position is fixed because the scrollView is not resizing according to the amount of items.
But I didn't find a way to meet both criterias.
question
how do I set the constraints of this Layout to get the expected behaviour (see first image below)?
design to achive
current XML Layout
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:theme="#style/Theme.AppCompat.Light">
<TextView
android:id="#+id/header"
android:layout_width="match_parent"
android:layout_height="100dp"
android:background="#color/shadeOfGrey2"
android:gravity="center"
android:text="header"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.core.widget.NestedScrollView
android:id="#+id/nestedScrollView"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toTopOf="#id/addItem"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/header"
app:layout_constraintVertical_bias="0"
app:layout_constraintVertical_chainStyle="packed">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</androidx.core.widget.NestedScrollView>
<Button
android:id="#+id/addItem"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="button 01"
app:layout_constraintBottom_toTopOf="#id/footer"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/nestedScrollView" />
<TextView
android:id="#+id/footer"
android:layout_width="match_parent"
android:layout_height="100dp"
android:background="#color/shadeOfGrey2"
android:gravity="center"
android:text="footer"
app:layout_constraintBottom_toBottomOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
current Android layout
I think I got it down to what you're expecting now. Could you verify?
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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="match_parent"
android:layout_height="match_parent"
android:theme="#style/Theme.AppCompat.Light">
<TextView
android:id="#+id/header"
android:layout_width="match_parent"
android:layout_height="100dp"
android:background="#color/shadeOfGrey2"
android:gravity="center"
android:text="header"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.core.widget.NestedScrollView
android:id="#+id/nestedScrollView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constrainedHeight="true"
app:layout_constraintBottom_toTopOf="#+id/addItem"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/header"
app:layout_constraintVertical_bias="0"
app:layout_constraintVertical_chainStyle="packed">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:itemCount="8"
tools:listitem="#android:layout/simple_list_item_2" />
</androidx.core.widget.NestedScrollView>
<Button
android:id="#+id/addItem"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="button 01"
app:layout_constraintBottom_toTopOf="#+id/footer"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/nestedScrollView"
app:layout_constraintVertical_bias="0" />
<TextView
android:id="#+id/footer"
android:layout_width="match_parent"
android:layout_height="100dp"
android:background="#color/shadeOfGrey2"
android:gravity="center"
android:text="footer"
app:layout_constraintBottom_toBottomOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Just keep in mind that your approach above won't be recycling any views in the RecyclerView adapter, so if the data is big then performance might become a concern.
Screenshots from Android Studio:
I am trying to make a Dialog that looks like this
Here, the elements in orange rectangles are fixed header and footer sections of the Dialog. The elements inside blue rectangle are placed dynamically depending on what content is to be shown.
Here it the XML for this.
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="#+id/header_section"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<!-- some views -->
</LinearLayout>
<LinearLayout
android:id="#+id/body_section"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintTop_toBottomOf="#id/header_section"
app:layout_constraintBottom_toTopOf="#id/footer_section"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent">
</LinearLayout>
<LinearLayout
android:id="#+id/footer_section"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent">
<!-- some views -->
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
It works fine when I place other views inside the blue area, but when a RecyclerView is placed inside it and items are dynamically added to it, it grows in size and overlaps the text in header section and pushes the footer section to bottom. How can I make the RecyclerView cover only the blue area?
Use height 0dp in body section so it will fit between header and footer
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="#+id/header_section"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<!-- some views -->
</LinearLayout>
<LinearLayout
android:id="#+id/body_section"
android:layout_width="match_parent"
android:layout_height="0dp"
android:orientation="vertical"
app:layout_constraintTop_toBottomOf="#id/header_section"
app:layout_constraintBottom_toTopOf="#id/footer_section"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent">
</LinearLayout>
<LinearLayout
android:id="#+id/footer_section"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent">
<!-- some views -->
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
I use ScrollView to tackle this,
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ScrollView
android:id="#+id/scrollView"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintHeight_min="100dp"
app:layout_constraintHeight_max="250dp"
app:layout_constrainedHeight="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
>
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recycler"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:paddingHorizontal="8dp"
android:paddingVertical="8dp"
/>
</ScrollView>
</androidx.constraintlayout.widget.ConstraintLayout>
The main attributes are these 3
app:layout_constraintHeight_min="100dp"
app:layout_constraintHeight_max="250dp"
app:layout_constrainedHeight="true"