Android - how to make a scrollable constraintlayout?
I want to make a layout that lets me scroll down using constraint layout, but I don't know how to go about it. Should the ScrollView
be the parent of the ConstraintLayout
like this?
<?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">
<android.support.constraint.ConstraintLayout
android:id="@+id/Constraint"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
Or the other way around? Maybe someone can point me to a good tutorial on this or give an example, I can't seem to find one.
Also, I don't know if this is a bug or some configuration that I don't have set up but I've seen images like this one :
where there are some components outside the blueprint "blue rectangle" yet they are visible, while on my side if I place a component on the "white space" I can't see it or move it anywhere, and it appears on the component tree.
UPDATE :
I found a way to make the constraint layout scrollable in the design tool, using a horizontal guideline to push down the constraint layout border and extend it beyond the device, after that, you can use the guideline as the new bottom of the constraint layout to anchor the components.
It seems that it is working, I don't know what dependency you were working with but in this one
compile 'com.android.support.constraint:constraint-layout:1.0.2'
Is working, this is what I did
<?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"
tools:context=".MainActivity">
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.design.widget.TextInputLayout
android:id="@+id/til_input"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:hint="Escriba el contenido del archivo"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@+id/btn_save"
app:layout_constraintTop_toTopOf="@id/btn_save"
app:layout_constraintVertical_chainStyle="spread">
<EditText
android:layout_width="match_parent"
android:layout_height="match_parent" />
</android.support.design.widget.TextInputLayout>
<Button
android:id="@+id/btn_save"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="onClickButtonSave"
android:text="Guardar"
app:layout_constraintLeft_toRightOf="@+id/til_input"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/txt_content"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="0dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/til_input"
app:layout_constraintVertical_chainStyle="spread"
app:layout_constraintVertical_weight="1" />
<Button
android:id="@+id/btn_delete"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:onClick="onClickButtonDelete"
android:text="Eliminar"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/txt_content"
app:layout_constraintVertical_chainStyle="spread" />
</android.support.constraint.ConstraintLayout>
</ScrollView>
Scroll Top
Scroll Bottom
There is a type of constraint which breaks the scroll function:
Just make sure you are not using this constraint on any view when wanting your ConstraintLayout
to be scrollable with ScrollView
:
app:layout_constraintBottom_toBottomOf=“parent”
If you remove these your scroll should work.
Explanation:
Setting the height of the child to match that of a ScrollView
parent is contradictory to what the component is meant to do. What we want most of the time is for some dynamic sized content to be scrollable when it is larger than a screen/frame; matching the height with the parent ScrollView
would force all the content to be displayed into a fixed frame (the height of the parent) hence invalidating any scrolling functionality.
This also happens when regular direct child components are set to layout_height="match_parent"
.
If you want the child of the ScrollView
to match the height of the parent when there is not enough content, simply set android:fillViewport
to true for the ScrollView
.
Use NestedScrollView with viewport true is working good for me
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true">
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="700dp">
</android.support.constraint.ConstraintLayout>
</android.support.v4.widget.NestedScrollView>
for android x use this
<androidx.core.widget.NestedScrollView
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="match_parent">
.....other views....
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>
To summarize, you basically wrap your android.support.constraint.ConstraintLayout
view in a ScrollView
within the text of the *.xml
file associated with your layout.
Example activity_sign_in.xml
<?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"
tools:context=".SignInActivity"> <!-- usually the name of the Java file associated with this activity -->
<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="match_parent"
android:layout_height="match_parent"
android:background="@drawable/gradient"
tools:context="app.android.SignInActivity">
<!-- all the layout details of your page -->
</android.support.constraint.ConstraintLayout>
</ScrollView>
Note 1: The scroll bars only appear if a wrap is needed in any way, including the keyboard popping up.
Note 2: It also wouldn't be a bad idea to make sure your ConstraintLayout is big enough to the reach the bottom and sides of any given screen, especially if you have a background, as this will ensure that there isn't odd whitespace. You can do this with spaces if nothing else.