I have a LinearLayout with
app:layout_constraintDimensionRatio="1:2"
android:layout_width="match_parent"
app:layout_constraintBottom_toBottomOf="parent"
inside a ConstraintLayout.
It looks the way its supposed to be if the screen height is larger than two times the screen width.
However, on devices that are wider, the top of my layout is pushed out of the screen.
However I want the top to stay visible and have the bottom part move out of the screen instead. Here is how I want the layout to act like:
1: Long enough device, everything fine:
2: Device that is a little wider, still everything fine:
3: Device that is even wider, the top of the layout should still be visible and the bottom should be pushed down:
Solved: I did put it into a ScrollView but for app:layout_constraintDimensionRatio to also work, I needed to put the actual content into a ConstraintLayout in besaid ScrollView:
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="bottom"
android:orientation="vertical">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/layoutBgSnakes"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ImageView
android:id="#+id/imgView"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toTopOf="#id/imgView2"
app:layout_constraintDimensionRatio="1:1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:srcCompat="#drawable/..." />
<ImageView
android:id="#+id/imgView2"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintDimensionRatio="1:1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:srcCompat="#drawable/..." />
</androidx.constraintlayout.widget.ConstraintLayout>
</RelativeLayout>
</ScrollView>
Note: android:fillViewport="true" was the crucial line that made everything work.
Related
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).
The Row
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="10dp"
android:layout_marginVertical="2.5dp">
<com.google.android.material.card.MaterialCardView
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintDimensionRatio="1:1"
app:layout_constraintWidth_percent="0.5"
tools:ignore="MissingConstraints">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent" />
</com.google.android.material.card.MaterialCardView>
</androidx.constraintlayout.widget.ConstraintLayout>
I want every row to take 50% from the screen and everything works well but the remaining screen will be empty because I set ConstraintLayout as match_parent I tried to change it to wrap_content but not working.
How can I ignore the remaining screen to show other rows?
The problem is something like this
I want there to be some space after the last item in RecyclerView like the image.
The image is not in a state where the number of items is small, but in a state that is large enough to be scrollable.
In other words, when scrolling to the bottom, I want the last item to be positioned above the black bar of the image.
But what I have implemented is:
What I have implemented, as you can see in the image, is that the item penetrates the bar and is superimposed on the bottom.
When scrolling, it doesn't matter if the bar overlaps the item, but when scrolling to the bottom, I want the last item to be on top of the bar.
ADDITION:
These recycler views dynamically add and delete items.
For once you just post the XML code.
If you need other code, please tell me.
XML
<?xml version="1.0" encoding="utf-8"?>
<layout 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">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/rv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintTop_toTopOf="parent" />
<FrameLayout
android:id="#+id/button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="24dp"
android:background="#color/transparentBg"
app:layout_constraintBottom_toBottomOf="parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/add_exercise"
android:layout_width="150dp"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:padding="8dp">
<ImageView
android:id="#+id/add_icon"
android:layout_width="30dp"
android:layout_height="30dp"
android:src="#drawable/ic_add"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:tint="#color/black" />
<TextView
android:id="#+id/add_text"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:gravity="center"
android:text="ADD ROUTINE"
android:textAlignment="center"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/add_icon" />
</androidx.constraintlayout.widget.ConstraintLayout>
</FrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
If you want your items to be displayed beneath the add Icon (which I personally do not like) and add some extra space in the bottom you can
Add an empty view to the end of your adapter
set clipToPadding=false and add a bottom padding which make the recycler view to skip that amount of height from bottom, but still show them (not clipping them) like this (I'm not sure if 160dp is a good number sum up your dimensions)
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/rv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintTop_toTopOf="parent"
android:clipToPadding="false"
android:paddingBottom="160dp"/>
And if you want your recycler to be shown above the add button (which I think looks better) you can change it like this
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/rv"
android:layout_width="match_parent"
android:layout_height="0dp"
android:orientation="vertical"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="#id/button" />
You can set your FrameLayout to a specific height and then give your recyclerview margin bottom same as frame layout height.
Or you can just change your ConstraintLayout into a LinearLayout.
I was happily coding a constraintLayout with a constraintDimensionRatio 1:1, that gives me a centered square with some padding.
<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.constraintlayout.widget.ConstraintLayout
android:id="#+id/board"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginStart="32dp"
android:layout_marginEnd="32dp"
android:background="#color/black"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintDimensionRatio="1:1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
BUT, for my usecase, I had to dynamically change the ratio ; so I tried a 10:1, and I discover that my view is always vertically centered and with some padding, but overflows the screen with its height :(
Is there a way to have a fully-centered view, that works with any constraintRatio, that could be kept in its parent layout and exploiting all available space in this one ?
Thanks !
I don't know if I fully understood, but if you want keep the ratio 10:1 but keep the view inside the parent, just change both layout_height and android:layout_width to 0dp, like so:
<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.constraintlayout.widget.ConstraintLayout
android:id="#+id/board"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="32dp"
android:layout_marginEnd="32dp"
android:background="#color/black"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintDimensionRatio="1:10"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
Guys, I need to make my ConstraintLayout scroll-able, so I placed it inside an ScrollView 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"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
android:overScrollMode="never">
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="#+id/img"
android:layout_margin="64dp"
android:layout_width="0dp"
android:layout_height="0dp"
android:scaleType="fitXY"
app:srcCompat="#drawable/avd"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="#id/btn"
app:layout_constraintDimensionRatio="1:1"
app:layout_constraintHeight_min="64dp"
app:layout_constraintHeight_max="256dp"/>
<Button
android:id="#+id/btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="button"
app:layout_constraintTop_toBottomOf="#id/img"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
</android.support.constraint.ConstraintLayout>
</ScrollView>
But the problem is that I like to scroll layout when all constraints has reached their minimum size(means all controls has reached to their specified margins and layout cannot get smaller anymore). But it seems when ScrollView needs to show scrolls, it specifies a very large size for ConstraintLayout's height, so my layout scales up to max possible size. If you try this layout in portrait and then landscape, you notice how it changes.
I wonder if there is any way to start scrolling when all constraint has reached their minimum size. Any idea how I can do this?