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?
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).
I don't known why FrameLayout inside ConstraintLayout, and both use wrap_content, then the last item in the RecycleView just show half content.
If I remove FrameLayout, direct use recycleview, it can work!
<?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="wrap_content"
android:background="#drawable/finance_bg_book_list_dialog">
<TextView
android:id="#+id/tvToolbarTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/finance_bg_book_list_toolbar"
android:drawablePadding="10dp"
android:padding="14dp"
android:text="#string/finance_book"
android:textColor="#android:color/white"
android:textSize="?fontSizeLarge"
app:drawableStartCompat="#drawable/finance_ic_toolbar_shelf"
app:layout_constraintBottom_toTopOf="#+id/vulturLayout"
app:layout_constraintTop_toTopOf="parent"/>
<FrameLayout
android:id="#+id/vulturLayout"
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/tvToolbarTitle">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_contentCode="successful"/>
</FrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
You need some horizontal constraints on your textview.
ex : app:layout_constraintStart_toStartOf=
I recommend you set a dimension for the RecyclerView height. if you use the FrameLayout with a wrap_content height, your RecyclerView will not be scrollable and it will own show half the item at the last based on the screen size
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.
I have a scrolled content, so I put a constraint layout inside a scrollview, I have a problem when put an image inside a constraint layout, but the image show a space from top such as in screenshot below, how can I remove that space?
<?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.support.constraint.ConstraintLayout
android:id="#+id/constraintLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<!-- have whatever children you want inside -->
<ImageView
app:srcCompat="#drawable/main_header"
android:id="#+id/img_icon"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="#ffccbb"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintWidth_percent="1"
android:contentDescription="TODO" app:layout_constraintDimensionRatio="1:1"
app:layout_constraintHorizontal_bias="0.0" app:layout_constraintVertical_bias="0.0"/>
</android.support.constraint.ConstraintLayout>
</ScrollView>
In your Imageview you have added app:layout_constraintDimensionRatio="1:1" that means it will take space 1:1, so width and height also will be 1:1. But your image app:srcCompat="#drawable/main_header" is not 1:1. So you have to add an image which has width and height of the same size. Otherwise, you can add android:scaleType="fitXY" or android:scaleType="centerCrop" according to your expectation.
Try this, remove app:layout_constraintTop_toTopOf="parent" in your ImageView it works!
I just checked your code on my phone and it looks good.
One thing that I made different from you is that I have used a different image resource for the imageView.
So I think that you don't actually have a problem, I think that it's just the image and how it looks, try to change your image resource and see if this problem remains.
He is how my layout file looks like:
<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">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/constraintLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="#+id/img_icon"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="#drawable/main_header"
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>
</ScrollView>
I am trying to use layout_constraintDimensionRatio and layout_constraintWidth_percent attribute together in an ImageView, but I find that they cannot be able to work together.
My xml code is:
1.using layout_constraintWidth_percent only:
<?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"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:scaleType="fitXY"
app:layout_constraintWidth_percent="0.5"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="#mipmap/ic_launcher"/>
</android.support.constraint.ConstraintLayout>
its corresponding UI is:
layout_constraintWidth_percent_only.png
2.using layout_constraintWidth_percent and layout_constraintDimensionRatio:
<?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"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintDimensionRatio="w,2:1"
android:scaleType="fitXY"
app:layout_constraintWidth_percent="0.5"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="#mipmap/ic_launcher"/>
</android.support.constraint.ConstraintLayout>
its corresponding UI is:
layout_constraintWidth_percent_and_layout_constraintDimensionRatio.png
It's clear that when I use layout_constraintDimensionRatio, layout_constraintWidth_percent does not work.
What I really want is the width of the ImageView is 50% of its parent, and then the height of the ImageView is 50% of its width by using layout_constraintWidth_percent and layout_constraintDimensionRatio together.
Setting android:layout_height="0dp" to match constraint should help you achieve the desired result.
According to the documentation:
You can also use ratio if both dimensions are set to MATCH_CONSTRAINT (0dp). In this case the system sets the largest dimensions the satisfies all constraints and maintains the aspect ratio specified.
<?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"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_width="0dp"
android:layout_height="0dp"
android:scaleType="fitXY"
app:layout_constraintWidth_percent="0.5"
app:layout_constraintDimensionRatio="2:1"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="#mipmap/ic_launcher"/>
</android.support.constraint.ConstraintLayout>
Edit It seems app:layout_constraintWidth_percent does not provide actual horizontal constraints by itself to the View so the following will behave differently (first on has the right horizontal constraint set and the second does not):
<ImageView
android:layout_width="0dp"
android:layout_height="0dp"
android:scaleType="fitXY"
app:layout_constraintDimensionRatio="H,2:1"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintWidth_percent="0.5"
app:srcCompat="#mipmap/ic_launcher" />
and
<ImageView
android:layout_width="0dp"
android:layout_height="0dp"
android:scaleType="fitXY"
app:layout_constraintDimensionRatio="H,2:1"
app:layout_constraintHorizontal_bias="0"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintWidth_percent="0.5"
app:srcCompat="#mipmap/ic_launcher" />
We are constraining the width based as percentage of the parent and then constraining the height based on width by using H in app:layout_constraintDimensionRatio="H,2:1". In the first case the view does not show and in the second it does in fact display correctly. It looks like if you want to use app:layout_constraintWidth_percent you need to add both horizontal constraints and then you can correctly constrain height based on width.
As the alternative to this approach you can use Guideline set at 50% of parent width to constrain your ImageView and then constrain height according to the ratio:
<?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"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.constraint.Guideline
android:id="#+id/guideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.5" />
<ImageView
android:layout_width="0dp"
android:layout_height="0dp"
android:scaleType="fitXY"
app:layout_constraintDimensionRatio="H,2:1"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="#id/guideline"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintWidth_percent="0.5"
app:srcCompat="#mipmap/ic_launcher" />
</android.support.constraint.ConstraintLayout>