I have a ScrollView
and a Button
side by side in a vertical orientation(both children of ConstraintLayout
's weighted chain with weight 1 and 0 respectively for ScrollView
and the Button
. BTW, you can optionally assume them to be children of a LinearLayout
instead of a ConstraintLayout
because a weighted ConstraintLayout
chain works almost the same as a LinearLayout
).
This is one of those typical use cases where you create the ScrollView
with a list of certain items(children) and at the bottom have a big Button that searches your database based on the values filled in the ScollView
children. Something like below:
The red-color encircled portion is where the Button is supposed to be(it is there but not visible).
Now the problem.
I want the button to be visible at all times irrespective of the ScrollView
(if that implies shrinking of ScrollView
's height, so be it because it is scrollable after all) but since the contents of ScrollView
take enough space to hide the Button
, by default it gets hidden. The solution(I think) would entail having to shrink the ScrollView
's height just the amount that the Button
is visible in the remaining space below.
Note that, I don't want the arrangement to end up like having the Button
overlay the ScrollView
's area. This is the case where no shrinkage of height would be required to ScrollView
but rather the Button
is made to float above it at the bottom, hiding some of its area. I want to force the ScrollView
to adjust to the Button
. Also, having weights of 1 and 0 respectively didn't help.
EDIT: Code for layout. (The Button
is with id search_button)
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="8dp"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
>
<ScrollView
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
android:id="@+id/scrollView2"
app:layout_constraintTop_toTopOf="parent"
tools:layout_constraintRight_creator="1"
tools:layout_constraintLeft_creator="1"
app:layout_constraintVertical_weight="1"
app:layout_constraintBottom_toTopOf="@+id/search_button"
app:layout_constraintVertical_chainStyle="spread_inside">
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginEnd="4dp"
android:layout_marginLeft="4dp"
android:layout_marginRight="4dp"
android:layout_marginStart="4dp"
android:layout_marginTop="8dp"
android:background="@android:drawable/dialog_holo_light_frame"
android:paddingEnd="8dp"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:paddingStart="8dp"
android:paddingTop="8dp">
<LinearLayout
android:layout_height="wrap_content"
android:layout_width="0dp"
app:layout_constraintTop_toTopOf="parent"
android:layout_marginTop="8dp"
android:layout_marginLeft="8dp"
android:layout_marginStart="8dp"
app:layout_constraintLeft_toLeftOf="parent"
android:layout_marginRight="8dp"
android:layout_marginEnd="8dp"
android:orientation="vertical"
app:layout_constraintRight_toRightOf="parent"
android:id="@+id/frameLayout">
<include layout="@layout/layout_subject_search" />
</LinearLayout>
<View
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="?android:attr/listDivider"
android:layout_marginLeft="8dp"
app:layout_constraintLeft_toLeftOf="parent"
android:layout_marginRight="8dp"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/frameLayout"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:layout_marginTop="8dp"
android:id="@+id/view" />
<LinearLayout
android:layout_height="wrap_content"
android:layout_width="0dp"
android:layout_marginTop="8dp"
android:layout_marginLeft="8dp"
android:layout_marginStart="8dp"
app:layout_constraintLeft_toLeftOf="parent"
android:layout_marginRight="8dp"
android:layout_marginEnd="8dp"
android:orientation="vertical"
app:layout_constraintRight_toRightOf="parent"
android:id="@+id/frameLayout1"
app:layout_constraintTop_toBottomOf="@+id/view">
<include layout="@layout/layout_qualification_search" />
</LinearLayout>
<View
android:layout_width="0dp"
android:layout_height="2dp"
android:background="?android:attr/listDivider"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:layout_marginTop="8dp"
app:layout_constraintTop_toBottomOf="@+id/frameLayout1"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:id="@+id/view2" />
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/search_by_location_label"
android:textSize="15sp"
android:textStyle="bold"
android:layout_marginLeft="8dp"
app:layout_constraintLeft_toLeftOf="parent"
android:layout_marginTop="8dp"
app:layout_constraintTop_toBottomOf="@+id/view2"
android:layout_marginStart="8dp" />
<Switch
android:id="@+id/location_toggle_switch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:text=""
android:layout_marginTop="16dp"
app:layout_constraintTop_toBottomOf="@+id/view2"
android:layout_marginRight="16dp"
app:layout_constraintRight_toRightOf="parent"
android:layout_marginEnd="16dp" />
<FrameLayout
android:id="@+id/map_search_fragment"
android:layout_width="0dp"
android:layout_height="240dp"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_below="@+id/textView"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:background="@android:drawable/dialog_holo_light_frame"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/location_toggle_switch"
app:layout_constraintVertical_bias="0.0">
</FrameLayout>
</android.support.constraint.ConstraintLayout>
</ScrollView>
<Button
android:id="@+id/search_button"
android:layout_width="0dp"
android:layout_height="0dp"
android:text="@string/search_tutors_string"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_marginBottom="4dp"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintVertical_weight="0"
app:layout_constraintTop_toBottomOf="@+id/scrollView2" />
<ProgressBar
android:id="@+id/search_tutors_progress_bar"
style="?android:attr/progressBarStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:visibility="gone"/>
</android.support.constraint.ConstraintLayout>
EDIT 2: As asked by @marshmallow 's,
// include layout="@layout/layout_subject_search"
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/search_by_subject_label"
android:textStyle="bold"
android:textSize="15sp"/>
<com.learncity.learner.search.SubjectMultiAutoCompleteTextView
android:id="@+id/subject_multi_auto_complete_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:completionThreshold="1"
android:ems="10"/>
</merge>
// include layout="@layout/layout_qualification_search"
<merge xmlns:android="http://schemas.android.com/apk/res/android" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/search_by_qualification_label"
android:textStyle="bold"
android:textSize="15sp"/>
<com.learncity.learner.search.QualificationMultiAutoCompleteTextView
android:id="@+id/qualification_multi_auto_complete_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:completionThreshold="1"
android:ems="10"/>
</merge>
First of all, thanks to @marshmallow for suggesting the wrap_content
strategy as well as repeatedly testing and replying with updated solutions.
The solution is bit of a twist on his suggestion:
layout_height
for Button
to be wrap_content
. Why? We want to declare button's height as a reference for ScrollView
to adjust its size and the true height of the button is obtained by using wrap_content
.ScrollView
to adjust its size as per button. To do this, we use layout_height
as 0dp
which translates to, "Use available constraints to adjust your size rather than asserting any fixed size of your own". For the same reason, Button
's height is not 0dp.ScrollView
and 0 for Button
(it doesn't effectively work for Button because width is not 0dp/match constraints; so just a pointer to ScrollView
to take up space remaining other than Button
)With this, the final solution becomes:(The solution tested for both portrait and landscape modes)
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="8dp"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
>
<ScrollView
android:id="@+id/scrollView2"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginBottom="4dp"
app:layout_constraintBottom_toTopOf="@+id/search_button"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0"
app:layout_constraintVertical_chainStyle="spread_inside"
app:layout_constraintVertical_weight="1"
tools:layout_constraintLeft_creator="1"
tools:layout_constraintRight_creator="1">
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginEnd="4dp"
android:layout_marginLeft="4dp"
android:layout_marginRight="4dp"
android:layout_marginStart="4dp"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
android:background="@android:drawable/dialog_holo_light_frame"
android:paddingEnd="8dp"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:paddingStart="8dp"
android:paddingTop="8dp">
<LinearLayout
android:id="@+id/frameLayout"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:orientation="vertical"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent">
<include layout="@layout/layout_subject_search" />
</LinearLayout>
<View
android:id="@+id/view"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:background="?android:attr/listDivider"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/frameLayout" />
<LinearLayout
android:id="@+id/frameLayout1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:orientation="vertical"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/view">
<include layout="@layout/layout_qualification_search" />
</LinearLayout>
<View
android:id="@+id/view2"
android:layout_width="0dp"
android:layout_height="2dp"
android:layout_marginEnd="8dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:background="?android:attr/listDivider"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/frameLayout1" />
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:text="@string/search_by_location_label"
android:textSize="15sp"
android:textStyle="bold"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@+id/view2" />
<Switch
android:id="@+id/location_toggle_switch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_marginEnd="16dp"
android:layout_marginRight="16dp"
android:layout_marginTop="16dp"
android:text=""
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/view2" />
<FrameLayout
android:id="@+id/map_search_fragment"
android:layout_width="0dp"
android:layout_height="240dp"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_below="@+id/textView"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:background="@android:drawable/dialog_holo_light_frame"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/location_toggle_switch"
app:layout_constraintVertical_bias="0.0">
</FrameLayout>
</android.support.constraint.ConstraintLayout>
</ScrollView>
<Button
android:id="@+id/search_button"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginBottom="4dp"
android:layout_marginTop="4dp"
android:text="@string/search_tutors_string"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/scrollView2"
app:layout_constraintVertical_weight="0" />
<ProgressBar
android:id="@+id/search_tutors_progress_bar"
style="?android:attr/progressBarStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:visibility="gone"/>
</android.support.constraint.ConstraintLayout>