ConstraintLayout - how to wrap over RecyclerView - android

I have a ConstraintLayout with an appBar (containing a toolbar), two fragments (containing a RecyclerView each) and a button at the bottom.
What I am trying to do is to wrap the height of the layout over the size of the RecyclerViews. As you can see on the picture below, every Recyclerview is taking an equal height regardless of the size of the list.
And this is my 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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/template_grey_light"
tools:context=".presentation.ui.activity.MainActivity">
<include
android:id="#+id/AppBar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="#+id/fragmentTop"
app:layout_constraintVertical_chainStyle="packed"
layout="#layout/app_bar" />
<androidx.fragment.app.FragmentContainerView
android:id="#+id/fragmentTop"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintTop_toBottomOf="#+id/AppBar"
app:layout_constraintBottom_toTopOf="#+id/fragmentBottom"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"/>
<androidx.fragment.app.FragmentContainerView
android:id="#+id/fragmentBottom"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintTop_toBottomOf="#+id/fragmentTop"
app:layout_constraintBottom_toTopOf="#+id/shuffleButton"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"/>
<Button
android:id="#+id/shuffleButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#color/white"
android:background="#color/template_love_red"
android:text="Go!"
android:layout_marginBottom="20dp"
app:layout_constraintTop_toBottomOf="#+id/fragmentBottom"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
I understand I am having 0dp on the height attributes and that makes it equal in height, but then if I don't, everything will overlap at the top. Any idea on how to make it work?

Use android:layout_height="wrap_content" in your FragmentContainerView tag

Related

Recyclerview crop last and first items shadow

Recyclerview crop first and last items shadows and i cant't fix it with any attributes.
I have a such xml screen:
<?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"
tools:context=".screens.view.CreateRequestFragment">
<ScrollView
android:id="#+id/createRequestScrollView"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toTopOf="#+id/sendRequestButton"
app:layout_constraintEnd_toEndOf="parent"
android:background="#color/transparent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<!-- ... some elements inside scrollview -->
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/usersRecyclerView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="#dimen/margin_m"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/selectUsersTitle" />
</androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>
<Button
android:id="#+id/sendRequestButton"
style="#style/OnDutyButtonStart"
android:text="Send Request"
android:layout_margin="#dimen/margin_m"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
tools:text="Send Request" />
</androidx.constraintlayout.widget.ConstraintLayout>
In this case i get cropped last and first items shadows:
but i need it like this:
If i add margin or padding - i get the same with blank white space and always cropped shadows.

Fluid height RecyclerView when full or empty

I have a dynamic recycler view. Which expands the height of its parent when full and looks really nice however when there are no entries added to it yet or there are few entries in it it just looks ugly.
However if I set the width to say 200dp than it looks a bit better.
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout 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/shading"
tools:context=".MainActivity">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="?android:attr/actionBarSize"
android:background="#color/shading">
<ImageView
android:id="#+id/logo"
android:layout_width="120dp"
android:layout_height="60dp"
android:src="#drawable/ic_logo"
app:layout_constraintBottom_toTopOf="#+id/list_projects"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/list_projects"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_margin="20dp"
android:background="#drawable/shape_list_item_projects"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/logo" />
</androidx.constraintlayout.widget.ConstraintLayout>
<com.google.android.material.bottomappbar.BottomAppBar
android:id="#+id/bottomAppBar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
app:backgroundTint="#color/white"
app:fabCradleRoundedCornerRadius="25dp"
app:fabCradleMargin="5dp"
app:hideOnScroll="false"
app:menu="#menu/menu_main_activity" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/ic_outline_add_circle_outline_24"
app:backgroundTint="#color/white"
app:layout_anchor="#id/bottomAppBar"
app:maxImageSize="40dp" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
The desired outcome is to have it wrap the content until it reaches the bounds of BottomAppBar.
You can do that by:
Bias the RecyclerView to the top using ConstraintLayout vertical chain:
app:layout_constraintVertical_bias="0"
app:layout_constraintVertical_chainStyle="packed"
This makes the RecyclerView directly under the top image, and pack both to the top of the layout.
Force the RecyclerView default height dimension to wrap_content:
app:layout_constraintHeight_default="wrap"
This makes the RecyclerView to wrap its content when having 0 or few items until it reaches the bounds of BottomAppBar; then the RV will be strict to the constraint.
Remove app:layout_constraintBottom_toTopOf="#+id/list_projects" from the top image to make the top image and RecyclerView aligned to the top (not centered vertically).

How to keep progressbar always below a recyclerView and not to be squeezed out of screen if there are too many items?

I am making a layout for showing scanned bluetooth device. Here is the 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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".fragments.ScannedListFragment">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recycler_view_scan_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="#id/progressBar_scan_list"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
tools:itemCount="12"
tools:listitem="#layout/list_item_scanned_list" />
<ProgressBar
android:id="#+id/progressBar_scan_list"
style="?android:attr/progressBarStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="#id/recycler_view_scan_list"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
But when there are too many list items, the progressbar will be squeezed out of the screen. Just like this:
demonstration1
I want to keep the progressbar stick to the bottom of the recyclerView when the screen has enough space to show all content and the progressbar can be completely shown above the bottom of the screen without scrolling even if there are too many items in the recyclerView.
I tried vertically chaining two views and packed chain with bias but no luck. Also, I found that adding app:layout_constraintHeight_max="" for the recyclerView can achieve similar effect. But it seems not a general solution for different screen sizes.
Create a vertical chain by constraining the bottom of the ProgressBar to the parent, then set the chain style to packed so that both views stick together and then set the vertical bias to 0 to align them to the top of the parent. To prevent the RecyclerView from pushing the ProgressBar out of the screen set the app:layout_constrainedHeight="true" attribute for the RecyclerView - it enforces constraints when the height is set to wrap_content.
<?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"
tools:context=".fragments.ScannedListFragment">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recycler_view_scan_list"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintVertical_chainStyle="packed"
app:layout_constraintVertical_bias="0"
app:layout_constrainedHeight="true"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="#id/progressBar_scan_list"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
tools:itemCount="12"
tools:listitem="#layout/list_item_scanned_list" />
<ProgressBar
android:id="#+id/progressBar_scan_list"
style="?android:attr/progressBarStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="#id/recycler_view_scan_list"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<?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"
tools:context=".fragments.ScannedListFragment">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recycler_view_scan_list"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="#id/progressBar_scan_list"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
tools:itemCount="12"
tools:listitem="#layout/list_item_scanned_list" />
<ProgressBar
android:id="#+id/progressBar_scan_list"
style="?android:attr/progressBarStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
This way it will be always visible. Make the progress bar bottom constraint to parent and recycler view height 0dp

Android: How to use constraint_height_percent inside a layout that will be included in a parent layout

Currently, I am trying to make my heights and widths of my views relative to the available space, so my ui will be more responsible. The problem I encounter is that whenever I try to include this layouts inside a parent layout (e.g include shop_content inside fragment_shop), the heights and widths of my included layout don't work anymore.
I've made a small example to show this. In this example, you can see that the height of the toolbar should take 17% of the given height. Everything works fine when I look at my design tab inside the child layout, but when importing this layout inside my fragment_shopping_cart, the view remains invisible / the height is not shown properly.
child_layout
<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"> <!-- Changing this to wrap_content makes weird stuff -->
<com.google.android.material.appbar.MaterialToolbar
android:id="#+id/calibrate_btn_background"
android:layout_width="match_parent"
android:layout_height="0dp"
android:background="#color/color_primary"
android:clickable="false"
app:layout_constraintHeight_percent="0.17" <!-- Height should take 0.17 -->
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
parent_layout
<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.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".framework.ui.view.fragments.shop.ShoppingCartFragment">
<com.google.android.material.appbar.MaterialToolbar
android:id="#+id/shopping_cart_toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/color_primary"
app:title="#string/bottom_nav_shopping_cart"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
</com.google.android.material.appbar.MaterialToolbar>
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/rv_shopping_cart"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintBottom_toTopOf="#id/shopping_cart_btn"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/shopping_cart_toolbar"
tools:listitem="#layout/shopping_cart_list_item" />
<include
android:id="#+id/shopping_cart_btn"
layout="#layout/child_layout"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
How it should look
How it looks
What am I doing wrong here? I appreciate every help. Note: I am new to responsive ui in Android
EDIT
As this question gets harder to understand, I will try to explain it better with this example: I have a layout called app_standard_checkout_btn that I use in several of my layouts (including it). This layout contains different views such as a toolbar (serves as a background), textview and other stuff.
Currently, the height of the toolbar is fix with 124dp and here lies the problem. I don't want the height to be 124dp but rather to be 0.15 of the entire available height in which the layout is included in (which is same as 124dp in some cases). How is this achievable?
<?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">
<data>
<variable
name="price"
type="Float" />
<variable
name="btnText"
type="String" />
<variable
name="btnIcon"
type="android.graphics.drawable.Drawable" />
<variable
name="btnTextCapitalized"
type="Boolean" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.appbar.MaterialToolbar
android:id="#+id/calibrate_btn_background"
android:layout_width="match_parent"
android:layout_height="124dp" <!-- THIS FIXED VALUE IS BAD -->
android:background="#color/color_btn_gray"
android:clickable="false"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<com.google.android.material.textview.MaterialTextView
android:id="#+id/calibrate_btn_tv_sum"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="#dimen/standard8dpMargin"
android:layout_marginEnd="#dimen/big16dpMargin"
android:text="#string/calibrate_btn_price"
android:textColor="#color/color_text_dark"
android:textSize="#dimen/textHeadlineNormal2"
app:layout_constraintEnd_toStartOf="#+id/shop_item_price"
app:layout_constraintTop_toTopOf="#+id/calibrate_btn_background" />
<TextView
android:id="#+id/shop_item_price"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#{price}"
android:textColor="#color/color_text_blue"
android:textSize="#dimen/textHeadlineNormal2"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="#+id/calibrate_btn_tv_sum"
app:layout_constraintEnd_toStartOf="#+id/calibbrate_btn_tv_intern_curr"
app:layout_constraintTop_toTopOf="#+id/calibrate_btn_tv_sum"
tools:text="4800.00" />
<TextView
android:id="#+id/calibbrate_btn_tv_intern_curr"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/currency"
android:textColor="#color/color_text_blue"
android:textSize="#dimen/textHeadlineNormal2"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="#+id/shop_item_price"
app:layout_constraintEnd_toEndOf="#+id/calibrate_btn_next"
app:layout_constraintTop_toTopOf="#+id/shop_item_price" />
<com.google.android.material.textview.MaterialTextView
android:id="#+id/calibrate_btn_tv_description"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:text="#string/calibrate_btn_desc"
android:textColor="#color/color_text_gray"
android:textSize="#dimen/textDescriptionNormal4"
app:layout_constraintEnd_toEndOf="#+id/calibrate_btn_next"
app:layout_constraintTop_toBottomOf="#+id/shop_item_price" />
<com.google.android.material.button.MaterialButton
android:id="#+id/calibrate_btn_next"
android:layout_width="match_parent"
android:layout_height="56dp"
android:layout_marginStart="#dimen/big16dpMargin"
android:layout_marginEnd="#dimen/big16dpMargin"
android:layout_marginBottom="#dimen/standard8dpMargin"
android:clickable="true"
android:focusable="true"
android:text="#{btnText}"
android:textAllCaps="#{btnTextCapitalized}"
android:textSize="#dimen/textDescriptionNormal1"
android:textStyle="normal"
app:backgroundTint="#color/color_btn_blue"
app:icon="#{btnIcon}"
app:iconGravity="textStart"
app:layout_constraintBottom_toBottomOf="#id/calibrate_btn_background"
app:layout_constraintEnd_toEndOf="#id/calibrate_btn_background"
app:layout_constraintStart_toStartOf="#+id/calibrate_btn_background" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
You need to constraint the top of the child_layout to the bottom of the ReyclerView
So add bleow constraint to the child_layout
app:layout_constraintTop_toBottomOf="#+id/rv_shopping_cart"
Upon this change, the entire parent layout will be:
<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.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".framework.ui.view.fragments.shop.ShoppingCartFragment">
<com.google.android.material.appbar.MaterialToolbar
android:id="#+id/shopping_cart_toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/color_primary"
app:title="#string/bottom_nav_shopping_cart"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
</com.google.android.material.appbar.MaterialToolbar>
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/rv_shopping_cart"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintBottom_toTopOf="#id/shopping_cart_btn"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/shopping_cart_toolbar"
tools:listitem="#layout/shopping_cart_list_item" />
<include
android:id="#+id/shopping_cart_btn"
layout="#layout/child_layout"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="#+id/rv_shopping_cart"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
EDIT
I don't want the height to be 124dp but rather to be 0.15 of the entire available height in which the layout is included in
Now you want the Toolbar to be 17% of the parent layout while it's not a direct child of it.. that looks strange and not matching with ConstraintLayout guidance as the Toolbar is not a direct child of the parent's ConstraintLayout
So, you can't constraint the Toolbar to the parent ConstraintLayout; instead you can constraint the entire child layout to the parent layout.. So you need to limit the height of the entire child layout by either by hard-coding it or by constraining it. And without constraining the height you'll get the layout disappear as in your shared picture.
In top answer I had constraint it to the bottom of the RecyclerView and this is what you already did in your shared RecyclerView constraints with app:layout_constraintBottom_toTopOf="#id/shopping_cart_btn". This may not be perfect as we can't predect the height of the RecyclerView at compile time.
So, here is another option of constraining the height of the child layout relative to the parent layout using app:layout_constraintHeight_percent constraint likewise you did with its Toolbar but with a percentage that is greater than the 17%. It's up to you to pick a suitable percentage, here I will pick 50%.
Now the height of the parent is 100%. The height of the child is 50%, and as you need the Toolbar height to be 17% of the parent, then now double it to be 34%. And you have to change it according to your picked value of the entire child layout.
Now the parent layout will be
Parent layout:
<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.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".framework.ui.view.fragments.shop.ShoppingCartFragment">
<com.google.android.material.appbar.MaterialToolbar
android:id="#+id/shopping_cart_toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/color_primary"
app:title="#string/bottom_nav_shopping_cart"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
</com.google.android.material.appbar.MaterialToolbar>
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/rv_shopping_cart"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/shopping_cart_toolbar"
tools:listitem="#layout/shopping_cart_list_item" />
<include
android:id="#+id/shopping_cart_btn"
layout="#layout/child_layout"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintHeight_percent="0.5"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
Child 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="0dp"> <!-- Changing this to wrap_content makes weird stuff -->
<com.google.android.material.appbar.MaterialToolbar
android:id="#+id/calibrate_btn_background"
android:layout_width="match_parent"
android:layout_height="0dp"
android:background="#color/color_primary"
android:clickable="false"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHeight_percent="0.34"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
this line
app:layout_constraintHeight_percent="0.17"
belongs to parent_layout, should be set for <include tag or at least for ConstraintLayout placed in child_layout (root view in file)

Scrollview inside constraint layout does not scroll to the bottom of the parent constraint

I have a form which has around 12/13 fields. I used a Scrollview inside a constraint layout. Below is the hierarchy of the XML layout. The problem is, it doesn't scroll to the bottom instead scrolls only to the first initial 10 views. The last 3 fields gets hidden as the view does not scroll any further.
PARENT LAYOUT
<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:id="#+id/activity_register"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:focusableInTouchMode="true"
android:orientation="vertical">
<!-- Textview and a button -->
<ScrollView
android:id="#+id/scrollView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:layout_marginTop="10dp"
android:orientation="vertical"
android:overScrollMode="never"
android:scrollbars="none"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="#+id/view"
tools:layout_constraintBottom_creator="1"
tools:layout_constraintLeft_creator="1"
tools:layout_constraintRight_creator="1"
tools:layout_constraintTop_creator="1"
tools:layout_editor_absoluteX="0dp"
tools:layout_editor_absoluteY="0dp">
<android.support.constraint.ConstraintLayout
android:id="#+id/constraintLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<!-- Child Views (12/13 views of the fields)-->
</android.support.constraint.ConstraintLayout>
</ScrollView>
</android.support.constraint.ConstraintLayout>
This layout works in my app.
The trick is to set these two attributes in ScrollView:
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
The simplified layout from my app:
<?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="match_parent"
android:layout_height="match_parent"
android:theme="#style/ThemeOverlay.AppCompat.Light">
<RelativeLayout
android:id="#+id/linear"
android:layout_width="0dp"
android:layout_height="56dp"
android:background="#color/title"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ScrollView
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="#id/linear">
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="#+id/titleView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginStart="8dp"
android:text="#string/title"
android:textSize="14sp"
app:layout_constraintBaseline_toBaselineOf="#+id/title"
app:layout_constraintLeft_toLeftOf="parent" />
<EditText
android:id="#+id/title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
android:hint="toilet title"
android:inputType="text"
android:textColor="#android:color/holo_red_dark"
android:textSize="12sp"
app:layout_constraintLeft_toLeftOf="#+id/open_hour"
app:layout_constraintLeft_toRightOf="#+id/titleView"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
...
Other Views in ScrollView
...
</android.support.constraint.ConstraintLayout>
</ScrollView>
</android.support.constraint.ConstraintLayout>
In my case NestedScrollView worked instead of ScrollView. Following is the snippet of my working layout:
<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">
<!-- Some Views Here -->
<android.support.v4.widget.NestedScrollView
android:layout_width="0dp"
android:layout_height="0dp"
android:fillViewport="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="#+id/view">
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<!-- Some Views That can be Scrolled Here -->
</android.support.constraint.ConstraintLayout>
</android.support.v4.widget.NestedScrollView>
</android.support.constraint.ConstraintLayout>
You have two solutions for this problem (the same solution but in two ways to do it):
If you put the Design mode in Android Studio, select your ScrollView and open attributes tab and in the layout_height, select "match_constraint".
If you use the Text mode in Android Studio, use this:
<ScrollView
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="#id/tb_details">
See that the ScrollView height is set to 0dp. Both of this ways resolve the same problem but these are the different ways to do it.
The ScrollView is not the root view, I have a Constraint layout wrapping the ScrollView as you.
Two Steps
Keep layout height for scroll view zero
android:layout_height="0dp"
Again for scroll view
android:fillViewport="true"
Try adding bottom constraint to scrollview (eg: app:layout_constraintBottom_toBottomOf="parent")
and change android:layout_height="wrap_content" to android:layout_height="0dp"
In my case NestedScrollView worked instead of ScrollView.
Following is the snippet of my working layout:
Please make sure that you haven't make any childview height to match parent(0 dp) inside constrianlayout also for scroll view android:fillViewport="true;
Ask me if any doubt Occur.
<android.support.v4.widget.NestedScrollView
android:id="#+id/scroll_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="#dimen/_90sdp"
android:fillViewport="true">
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:id="#+id/cvLayout"
android:animateLayoutChanges="true">
Just Put android:fillViewport="true" in Parent Layout
In my case, I had a tall TextView (height set to wrap_content) inside a ScrollView (height set to 0dp and being constraint on the top and bottom). No suggestions worked, but I solved the problem by wrapping the TextView inside a FrameLayout (height set to wrap_content).
Never keep 0dp height of childs of ConstraintLayout if it is inside SV/NestedSV
wrap_content works because in this case ScrollView knows its childens height.
For me, I needed to add a LinearLayout inside my ScrollView in order to constrain it
<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">
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
tools:layout_editor_absoluteX="1dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<View....</View>
</LinearLayout>
</ScrollView>
</androidx.constraintlayout.widget.ConstraintLayout>
I have resolve this issue. Inside ScrollView you can not use constraint Layout.
for using constrain inside scroll u have to use Relative layout is parent of constraint Layout..
so ur sequence should be:
ScrollView ---> Relative Layout ---> Constraint Layout
If you came here after searching "Soft Keyboard Hides the View elements"!
Then you just have to add a scrollView and the same layout element again.
Before
<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">
<ImageView
android:id="#+id/imageView3"
android:layout_width="246dp"
android:layout_height="168dp"
android:layout_marginTop="20dp"
android:src="#drawable/img"/>
<Button
android:id="#+id/btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</androidx.constraintlayout.widget.ConstraintLayout>
After
<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">
<ScrollView
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:fillViewport="true">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="#+id/imageView3"
android:layout_width="246dp"
android:layout_height="168dp"
android:layout_marginTop="20dp"
android:src="#drawable/img"/>
<Button
android:id="#+id/btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>
</androidx.constraintlayout.widget.ConstraintLayout>
For the horizontal scroll view case (parent is ConstraintLayout, immediate child is LinearLayout), I found that setting the four constraints, layout_width=0dp, and fillViewport=true was not enough. It still didn't scroll.
What did work in my case was to set the four constraints and change the element from ScrollView to HorizontalScrollView. In that case layout_width can be set to "wrap_content" and fillViewport can be omitted.
Additionally, I added a padding at the end of the immediate child of the HorizontalScrollView, to make the scrolling experience and the look better.
I faced another issue where i had nestedscrollview which has constrainlayout which has linearlayout. This linearlayout has child get added programatically. So scroll was not working. Solved by replacing CL with LL with vertical orientation
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintTop_toBottomOf="#+id/separatr"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:fillViewport="true"
android:fitsSystemWindows="true"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:orientation="vertical"
tools:background="#color/yellow_highlight"
android:paddingBottom="#dimen/box96">
<TextView
android:id="#+id/qansTv"
style="#style/BodyText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="#dimen/box200"
android:layout_marginTop="#dimen/box32"
android:layout_marginEnd="#dimen/box200"
android:text="Lorem ipsum dofdfd fsd fdfsd sdf sdfsd fsdfsd fd sdfd fsdfsdf sdfsd df sdfd fsdfsd fsdf sdfsd dflors fdfdf."
android:textColor="#color/white"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<LinearLayout
android:id="#+id/ansImageContainerLL"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:background="#color/red"
android:layout_marginEnd="#dimen/box64"
android:orientation="vertical"
android:layout_marginStart="#dimen/box64"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/qansTv" />
</LinearLayout>
</androidx.core.widget.NestedScrollView>
in my case I had to use 2 recyclerviews and since it didn't want to scroll all the way I found a way to set to which length of the scrollview to scroll, the length is set by changing the width of the TextView.
<?xml version="1.0" encoding="utf-8"?>
<HorizontalScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.ProjectsFragment"
android:background="#color/blue">
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="match_parent">
<TextView
android:id="#+id/scrollViewLength"
android:layout_width="2000dp"
android:layout_height="match_parent"
android:text="Change the width above"
android:visibility="invisible"/>
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:tag="exampletag"
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/recyclerView1"
android:tag="exampletag"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginTop="28dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
/>
</FrameLayout>
</HorizontalScrollView>
I know I'm late little bit ,I was facing the same issue what I did wrapped my RecyclerView Inside Linear or Relative layout and it worked like a charm,

Categories

Resources