ConstraintLayout from bottom to top - android

I have layout like this:
<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">
<androidx.fragment.app.FragmentContainerView
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="0dp"
android:background="#color/colorPrimary"
android:minHeight="300dp"
app:layout_constraintBottom_toTopOf="#+id/recyclerView"
app:layout_constraintHeight_min="300dp"
app:layout_constraintTop_toTopOf="parent" />
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
FragmentContainerView and RecyclerView have dynamic sizes, and FragmentContainerView should not be less than 300dp and fit all available spase. RecyclerView should be on the bottom and can contains from 1 to 20 items. Current solution works ok only for case RecyclerView contains few items, but for other case it overlaps FragmentContainerView.
Is it possible to align RecyclerView to bottom but restrict max size to have free space = 300dp at the top?

I think you need to do:
Add app:layout_constraintTop_toBottomOf="#id/container" to the RecyclerView
Remove app:layout_constraintBottom_toTopOf="#+id/recyclerView" From the FragmentContainerView
This will make the FragmentContainerView height not restricted to the height of the RecyclerView .. and Make the RecyclerView height limited between the bottom of the FragmentContainerView & the bottom of the parent.

Try adding app:layout_constraintTop_toBottomOf="#id/container" in RecyclerView

Related

Align two views in opposites sides (one at the top and one at the bottom) and be able to push the bottom view when the top view grows?

I basically have an EditText aligned at the top of the view and there's a RecyclerView on the bottom of the view that can also grow (with the newest item on the bottom)
That's easily doable with a constraint layout but my problem is that when the EditText grows it should start pushing down the list. But the list was initially aligned at the bottom of the parent. (and everything should be scrollable)
I hope this image makes things more clear
The trick here is to avoid forming a vertical chain (so that the EditText at the top always stays in place) and also to leverage the app:layout_constrainedHeight attribute on the RecyclerView in order to make it shrink when the EditText grows.
<?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">
<EditText
android:id="#+id/text"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/list"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constrainedHeight="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/text"
app:layout_constraintVertical_bias="1"/>
</androidx.constraintlayout.widget.ConstraintLayout>
The combination of android:layout_height="wrap_content" and app:layout_constrainedHeight="true", along with both top and bottom constraints, means that the RecyclerView will always be only as tall as its items or the available space below the EditText, whichever is smaller.
The app:layout_constraintVertical_bias="1" attribute ensures that, when the list doesn't fill the screen, it sits at the bottom.
I would add to the previous answer and if you want to be able to scroll your layout you can use sth like this:
<androidx.core.widget.NestedScrollView 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:fillViewport="true">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:id="#+id/edit_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent" />
<androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="#id/edit_text"
app:layout_constraintVertical_bias="1.0" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>
This will make everything align as you want to and you are able to scroll down to see your full recyclerView. NestedScrollView will make sure that everything runs smoothly.

Is it possible to make an ImageView cover the whole screen, if it's contained in a fragment in a ViewPager that doesn't cover the whole screen?

I am using a ViewPager in an activity layout which is a ConstraintLayout. This ViewPager is constrained in order to be displayed below a sibling widget. This ViewPager, so, doesn't cover the whole screen.
However, in the fragments of this ViewPager, there is an ImageView that must be displayed covering the whole screen. This ImageView is unique per fragment of this ViewPager (implying that each ImageView must actually be contained in each ViewPager's fragments).
The problem is: since this ImageView is within the fragments of the ViewPager that doesn't cover the whole screen, then it's impossible to use something like match_parent for this ImageView, since it will match the ViewPager which, obviously, doesn't cover all the screen (since it's shown below a sibling widget).
What could I do to make the ImageView fill the whole screen?
When you show the imageView fragment in view pager you can change your constraints programmatically. Here there is simple example for this
ConstraintLayout: change constraints programmatically
fragment.xml
<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">
<androidx.viewpager2.widget.ViewPager2
android:id="#+id/viewPagerImage"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
viewpger_item.xml
<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:orientation="vertical">
<androidx.appcompat.widget.AppCompatImageView
android:id="#+id/imgPool"
android:layout_width="0dp"
android:layout_height="0dp"
android:scaleType="fitXY"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

How to set the length of the RecyclerView to not exceed the screen

I have RecyclerView, texts, buttons etc ... inside NestedScrollView.
When the recyclerview menu has a lot of items become high-altitude (match_parent) all elements such as buttons and text will be by the scrollbar to show elements , I want the height to be automatic but without the other elements disappearing.
How do I do this What do I add?
Make your layout look something like this:
<android.support.constraint.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">
<LinearLayout
android:width="match_parent"
android:height="wrap_content"
android:id="#+id/top_elements_holder"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="#id/recyclerview">
<!-- Anything above the RecyclerView goes here -->
</LinearLayout>
<RecyclerView
android:width="match_parent"
android:height="0dp"
android:id="#+id/recyclerview"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="#id/top_elements_holder"
app:layout_constraintBottom_toTopOf="#id/bottom_elements_holder"
/>
<LinearLayout
android:width="match_parent"
android:height="wrap_content"
android:id="#+id/bottom_elements_holder"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="#id/recyclerview"
app:layout_constraintBottom_toBottomOf="parent">
<!-- Anything below the RecyclerView goes here -->
</LinearLayout>
</android.support.constraint.ConstraintLayout>
You'll obviously need to modify it to suit your needs.
With ConstraintLayout, you can set the RecyclerView's height to match_constraint (0dp), and set its top and bottom constraints. If you have elements above the RecyclerView, put them in the top LinearLayout, and the same for the bottom.
For more info on how ConstraintLayout works, you should read the documentation.

Align items in a RecyclerView at the bottom

I have a RecyclerView inside of a ConstraintLayout whose top starts at the bottom of a textView, and whose bottom stretches down to the parent. I want the items in this RecyclerView to default to the bottom of the RecyclerView. I tried adding gravity="bottom" and also tried the same thing with foregroundGravity and layout_gravity. I also tried adding layout_gravity="bottom" to my recyclerView item's layout. Still, all the items in the recyclerView continues to default to the top. Is there anything i can do to make sure the items are at the bottom? Here is the xml:
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/my_tv"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="needed to unlock next coupon"
android:textColor="#color/gray"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/irrelevant_tv"
android:layout_marginTop="#dimen/spacing_tiny"
android:gravity="center"
/>
<android.support.v7.widget.RecyclerView
android:id="#+id/rv"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginTop="#dimen/spacing_xl"
android:paddingTop="#dimen/spacing_large"
android:overScrollMode="always"
app:layoutManager="android.support.v7.widget.LinearLayoutManager"
app:layout_constraintTop_toBottomOf="#id/my_tv"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</android.support.constraint.ConstraintLayout>
I don't want to do wrap_content on recyclerView either, because otherwise it is not scrollable (I always have 3 items in this recyclerView, and based on the user's display settings, the recyclerView can get pushed off the screen, which requires me to be able to scroll)
You can use the method LinearLayoutManager#setStackFromEnd(boolean).
Then your items will be rendered starting from bottom of view.
See the docs.
You can also add this to XML layout:
app:stackFromEnd="true"

A big white space area is showing at the bottom of my ScrollView in my case

I have a ScrollView inside which a ConstraintLayout, inside the ConstraintLayout there is a RecyclerView.
The structure is like this:
<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_height="match_parent"
android:layout_width="match_parent"
android:orientation="vertical"
android:fillViewport="true"
android:overScrollMode="never">
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<android.support.v7.widget.RecyclerView
android:id="#+id/my_list"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginBottom="8dp"
android:layout_marginTop="15dp"
android:clipToPadding="false"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="parent"
app:layout_constraintVertical_bias="0.0" />
</android.support.constraint.ConstraintLayout>
</ScrollView>
My code populate a list of objects to the RecyclerView, no problem there. The only problem is there is a big white space area showing at the bottom of the ScrollView , I can't understand why? Could someone please point me to the right direction? Thanks in advance!
(A problem with this result is that for example if I have only one object in my list, there is no need to scroll the view, but it is still scrollable with the big white space area at the bottom.)
Lost the ScrollView, RecyclerView can scroll on its own.
Also match_parent is not supported by ConstraintLayout
You need to constraint all sides to the parent and have 0dp (match_constraint) for width and height
<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:orientation="vertical">
<android.support.v7.widget.RecyclerView
android:id="#+id/my_list"
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="parent"
android:layout_marginBottom="8dp"
android:layout_marginTop="15dp"
android:clipToPadding="false"
/>
</android.support.constraint.ConstraintLayout>
Notes
Your ConstraintLayout has match_parent for width and height.
You RecyclerView has 0dp for width and height, which means to match the constraint, and your RecyclerView is constraint to all sides to the parent.
You recycler view will scroll when content is more that fits on screen
After using wrap_content instead of match_content for RecyclerView, my problem get solved.
This is a ConstraintLayout bug (when wrapping a ConstraintLayout in a ScrollView) and was fixed in the new beta release. I had the same issue and updated to 1.1.0-beta4 and that solved it. Check here for latest releases:
https://dl.google.com/dl/android/maven2/com/android/support/constraint/group-index.xml

Categories

Resources