I used constraintLayout and layout_constraintDimensionRatio="1:1"
(width is wrap_content, height is 0dp (match_constraint))
As a result, I expected width and height to be 1:1, but it's not working.
What is wrong?
I attached code and screenshot.
<?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">
<TextView
android:id="#+id/t1"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:background="#android:color/holo_blue_bright"
android:gravity="center"
android:text="Hello World!11"
app:layout_constraintDimensionRatio="1:1" />
</android.support.constraint.ConstraintLayout>
screenshot
I quote android developer site about Constraintlayout.
https://developer.android.com/reference/android/support/constraint/ConstraintLayout.html#DimensionConstraints
Ratio :: You can also define one dimension of a widget as a ratio of
the other one. In order to do that, you need to have at least one
constrained dimension be set to 0dp (i.e., MATCH_CONSTRAINT), and set
the attribute layout_constraintDimentionRatio to a given ratio. For
example:
<Button android:layout_width="wrap_content"
android:layout_height="0dp"
app:layout_constraintDimensionRatio="1:1" />
will set the height of the button to be the same as its width.
but it was not working.
You forget to add your constraints
<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">
<TextView
android:id="#+id/t1"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:background="#android:color/holo_blue_bright"
android:gravity="center"
android:text="Hello World!11"
app:layout_constraintDimensionRatio="1" />
</android.support.constraint.ConstraintLayout>
0dp is only applied to the child views of ConstraintLayout.
Any view should apply the attribute rules of its parent.
As off version 1.1.0 this has changed.
You can now define:
app:layout_constraintDimensionRatio="1:1"
app:layout_constraintDimensionRatio="W,1:1"
app:layout_constraintDimensionRatio="H,1:1"
Check the link below to find all the documentation regarding DimensionConstraints:
Link to the docs
In my case I have a problem like i have to fill my layout inside container with A4 size paper ratio.
Problem
I am getting A4 size resume pages as images from backend so i have to append those images in Viewpager in which i am using ImageView to display those images.
Solution
I went through Constraint layout document in which Ratio section is there. So i can use layout_constraintDimensionRatio for solving my problem.
So my xml that is used to Display the whole Layout is following, in my case i have used app:layout_constraintDimensionRatio="1:1.27" as with:height ratio but the actual ratio is app:layout_constraintDimensionRatio="1:1.41"
<?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:background="#color/orange">
<!-- divider line which i used as restricting my A4 size container height-->
<View
android:id="#+id/divider"
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#color/headline_title_color"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias=".85"/>
<!-- A4 size Image View-->
<ImageView
android:id="#+id/resumeContainer"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginLeft="12dp"
android:layout_marginTop="16dp"
android:layout_marginRight="12dp"
android:layout_marginBottom="16dp"
android:background="#color/green"
android:text="#string/change"
android:src="#drawable/banner"
app:layout_constraintBottom_toTopOf="#id/divider"
app:layout_constraintDimensionRatio="1:1.27"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
/>
<!-- for Bottom two buttons -->
<com.bold.job.utils.CustomButton
android:id="#+id/preview"
style="#style/tertiaryButtonStyle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:onClick="preview"
android:text="#string/preview_resume"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="#id/guideline"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="#id/divider"
/>
<android.support.constraint.Guideline
android:id="#+id/guideline"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.5" />
<com.bold.job.utils.CustomButton
android:id="#+id/preview2"
style="#style/tertiaryButtonStyle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:onClick="preview"
app:layout_constraintLeft_toRightOf="#id/guideline"
app:layout_constraintRight_toRightOf="parent"
android:text="#string/preview_resume"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="#id/divider"
/>
</android.support.constraint.ConstraintLayout>
Please notice the last line, adding constraints around the edges makes the constraint work.
You can also use the design view in Studio, and drag and drop the constraints between objects.
<TextView
android:id="#+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Available chats" />
<ListView
android:id="#+id/listChats"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="#+id/textView"/>
Related
I have two TextViews, one above the other. I would like the vertical middle of the two TextViews to be at the same position as the vertical middle of the ImageView. (This is so, regardless of the amount of text that may go into either TextView, everything will always look neat, vertically.)
I created what I need perfectly using two LinearLayouts (as the space above the title is the same as the space beneath the description):
But Android Studio was unable to covert it to ConstraintLayout successfully, as it just dumped the TextViews at the bottom of the layout. I've played with a lot of attributes, but could not quite arrive at the desired layout.
My question is similar to this one, except that I am trying to center_vertical align a pair of views rather than a single one - which means I have no view edge to align to the centre of the ImageView/container.
Is it possible to achieve what I'm after with ConstraintLayout? (I expect I may be able to do it with a single RelativeLayout, but I would like to use the layout_constraintDimensionRatio attribute on my ImageView which presumably leave me needing to use ConstraintLayout.)
In case it helps, here's the code for my aforementioned LinearLayout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
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="wrap_content"
android:orientation="horizontal">
<ImageView
android:id="#+id/imageView"
android:layout_width="#dimen/resources_list_image_size"
android:layout_height="#dimen/resources_list_image_size"
android:layout_marginEnd="#dimen/activity_horizontal_margin"
android:layout_marginRight="#dimen/activity_horizontal_margin"
android:layout_gravity="center_vertical"
android:contentDescription="#string/resource_image"
android:scaleType="centerCrop"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:orientation="vertical">
<TextView
android:id="#+id/textViewTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="#style/MyTextAppearanceMedium"
tools:text="Title" />
<TextView
android:id="#+id/textViewDescription"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="#style/MyTextAppearanceSmall"
tools:text="Description" />
</LinearLayout>
</LinearLayout>
Update: Solution
Thanks to Ben P's answer, this is my final code:
<?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="wrap_content">
<!-- Add guideline to align imageView to. -->
<androidx.constraintlayout.widget.Guideline
android:id="#+id/guideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.3" />
<ImageView
android:id="#+id/imageView"
android:layout_width="0dp"
android:layout_height="0dp"
android:contentDescription="#string/resource_image"
android:scaleType="centerCrop"
app:layout_constraintDimensionRatio="H,1:1"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="#id/guideline"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
<TextView
android:id="#+id/textViewTitle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="#dimen/activity_horizontal_margin"
android:layout_marginLeft="#dimen/activity_horizontal_margin"
app:layout_constraintBottom_toTopOf="#id/textViewDescription"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#id/imageView"
app:layout_constraintTop_toTopOf="parent"
android:textAppearance="#style/MyTextAppearanceMedium"
app:fontFamily="#font/roboto_slab_regular"
app:layout_constraintVertical_chainStyle="packed"
tools:text="#string/enter_title_colon" />
<TextView
android:id="#+id/textViewDescription"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="#dimen/activity_horizontal_margin"
android:layout_marginLeft="#dimen/activity_horizontal_margin"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#id/imageView"
app:layout_constraintTop_toBottomOf="#id/textViewTitle"
app:fontFamily="#font/roboto_slab_light"
android:textAppearance="#style/MyTextAppearanceSmall"
tools:text="Description" />
</androidx.constraintlayout.widget.ConstraintLayout>
It sounds like you could solve this problem by using a packed chain anchored to the top and bottom of the ImageView. You'll also need to use horizontal bias and a constrained width in order to get wrapping to work correctly.
<?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">
<View
android:id="#+id/anchor"
android:layout_width="80dp"
android:layout_height="80dp"
android:layout_margin="64dp"
android:background="#caf"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<TextView
android:id="#+id/one"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintVertical_chainStyle="packed"
app:layout_constraintHorizontal_bias="0"
app:layout_constrainedWidth="true"
app:layout_constraintTop_toTopOf="#id/anchor"
app:layout_constraintStart_toEndOf="#id/anchor"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toTopOf="#id/two"/>
<TextView
android:id="#+id/two"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintHorizontal_bias="0"
app:layout_constrainedWidth="true"
app:layout_constraintTop_toBottomOf="#id/one"
app:layout_constraintStart_toEndOf="#id/anchor"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="#id/anchor"/>
</androidx.constraintlayout.widget.ConstraintLayout>
The important attributes here are:
app:layout_constraintVertical_chainStyle="packed" on the first view, which causes the two textviews to stack right on top of each other
app:layout_constraintHorizontal_bias="0" on both views, which means that when the text is not long enough to reach the edge of the screen it will stick to the edge of the anchor view
app:layout_constrainedWidth="true" on both views, which prevents the textview from ever being wider than its constraints, and so the text wraps to a new line
If you want to use ConstraintLayout you could use something like this:
<?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">
<ImageView
android:id="#+id/imageView"
android:layout_width="200dp"
android:layout_height="200dp"
android:contentDescription="description"
android:scaleType="centerCrop"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<LinearLayout
android:id="#+id/linearLayout"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="#+id/imageView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#+id/imageView"
app:layout_constraintTop_toTopOf="#+id/imageView">
<TextView
android:id="#+id/textViewTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:text="Title" />
<TextView
android:id="#+id/textViewDescription"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:text="Description" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
You can use this layout:
<?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">
<TextView
android:id="#+id/textView2"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="#color/colorAccent"
android:text="I am 5% of the screen height"
app:layout_constraintBottom_toTopOf="#+id/textView3"
app:layout_constraintEnd_toEndOf="#+id/textView3"
app:layout_constraintHeight_percent="0.05"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toStartOf="#+id/textView3"
app:layout_constraintTop_toTopOf="#+id/imageView2" />
<TextView
android:id="#+id/textView3"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintHeight_percent="0.15"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:background="#color/colorPrimary"
android:text="I am 15% of the screen height (And the image is 20% screen size in height) "
app:layout_constraintBottom_toBottomOf="#+id/imageView2"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#+id/imageView2"
app:layout_constraintTop_toBottomOf="#+id/textView2" />
<ImageView
android:id="#+id/imageView2"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintHeight_percent="0.20"
app:layout_constraintDimensionRatio="1:1"
android:scaleType="fitXY"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="#drawable/rose" />
</android.support.constraint.ConstraintLayout>
It will look like this:
One important thing about this layout:
You can control your aspect ratio (for the image) with app:layout_constraintDimensionRatio="x:y" and by passing "1:1" make it square
And by the way - I am using support library for no reason on this example, you can use androidx
I have an imageview that I will place different images.
This images can have many sizes like 200x200 200x400 400x200...
Above imageview I have an adview and below this imageview I need 4 buttons.
The problem is, I'd like the image be below adview, but stop jumping position when ad loads. It goes down when an ad loads, I'd to stop this move, make the image fix, but above the adview.
My xml:
<?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=".MainActivity">
<LinearLayout
android:id="#+id/ad_view"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginBottom="49dp"
android:orientation="horizontal"
app:layout_constraintBottom_toTopOf="#+id/imageView1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<com.google.android.gms.ads.AdView xmlns:ads="http://schemas.android.com/apk/res-auto"
android:id="#+id/adView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
ads:adSize="SMART_BANNER"
ads:adUnitId="ca-app-pub-xxx/xxx">
</com.google.android.gms.ads.AdView>
</LinearLayout>
<ImageView
android:id="#+id/imageView1"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:scaleType="fitXY"
android:layout_marginTop="89dp"
android:contentDescription="img"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/ad_view" />
<TextView
android:id="#+id/a1"
android:layout_width="127dp"
android:layout_height="50dp"
android:gravity="center"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintHorizontal_bias="0.207"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.447" />
<TextView
android:id="#+id/a2"
android:layout_width="127dp"
android:layout_height="50dp"
android:gravity="center"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintHorizontal_bias="0.806"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.447" />
<TextView
android:id="#+id/a3"
android:layout_width="127dp"
android:layout_height="50dp"
android:gravity="center"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintHorizontal_bias="0.207"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.582" />
<TextView
android:id="#+id/a4"
android:layout_width="127dp"
android:layout_height="50dp"
android:gravity="center"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintHorizontal_bias="0.806"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.582" />
</androidx.constraintlayout.widget.ConstraintLayout>
TL;DR
The fastest solution would be to change your ad view android:layout_height="wrap_content" into android:layout_height="fixed size" so your ad view will have a single height and won't change because of its wrap_content attribute (If your ad view is not loaded you can think of wrap_content as height of 0 and only after its loaded it will have height, thus the layout jump).
Why is it bad?
your layout won't be responsive.
How to fix?
Read the answer below.
Long but better answer:
You can use guidelines with app:layout_constraintGuide_percent=".2" to tell your guideline to be at the top of your screen (80%) and constraint your ad view to your guideline - this way your layout will won't jump (it will have its space to load into).
Another thing, different phones got different screen size, in your layout you are using fixed size on your view (fixed size is 50dp for example) and the result is that what may look good on one screen (your android studio preview screen) will not look good on another screen (your actual phone).
Here is an example to achieve your wanted look using ConstaintLayout:
<?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=".MainActivity">
<Button
android:id="#+id/adView"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
app:layout_constraintHeight_percent="0.08"
android:text="add view"
app:layout_constraintBottom_toTopOf="#+id/guideline"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="#+id/imageView1"
android:layout_width="0dp"
android:layout_height="0dp"
android:src="#drawable/ic_launcher_background"
android:scaleType="fitXY"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHeight_percent="0.4"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="#+id/guideline"
app:layout_constraintWidth_percent="0.6" />
<TextView
android:id="#+id/a1"
android:layout_width="0dp"
android:layout_height="0dp"
android:gravity="center"
android:text="a1"
app:layout_constraintHeight_percent="0.08"
app:layout_constraintWidth_percent="0.25"
app:layout_constraintBottom_toTopOf="#+id/a3"
app:layout_constraintEnd_toStartOf="#+id/a2"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="#+id/imageView1"
app:layout_constraintTop_toBottomOf="#+id/imageView1" />
<TextView
android:id="#+id/a2"
android:layout_width="0dp"
android:layout_height="0dp"
android:gravity="center"
android:text="a2"
app:layout_constraintHeight_percent="0.08"
app:layout_constraintWidth_percent="0.25"
app:layout_constraintBottom_toBottomOf="#+id/a1"
app:layout_constraintEnd_toEndOf="#+id/imageView1"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="#+id/a1"
app:layout_constraintTop_toTopOf="#+id/a1"
app:layout_constraintVertical_bias="0.0" />
<TextView
android:id="#+id/a3"
android:layout_width="0dp"
android:layout_height="0dp"
android:gravity="center"
android:text="a3"
app:layout_constraintHeight_percent="0.08"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="#+id/a1"
app:layout_constraintStart_toStartOf="#+id/a1"
app:layout_constraintTop_toBottomOf="#+id/a1" />
<androidx.constraintlayout.widget.Guideline
android:id="#+id/guideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent=".2" />
<TextView
android:id="#+id/a4"
android:layout_width="0dp"
android:layout_height="0dp"
android:gravity="center"
android:text="a4"
app:layout_constraintBottom_toBottomOf="#+id/a3"
app:layout_constraintEnd_toEndOf="#+id/a2"
app:layout_constraintHeight_percent="0.08"
app:layout_constraintStart_toStartOf="#+id/a2"
app:layout_constraintTop_toTopOf="#+id/a3" />
</androidx.constraintlayout.widget.ConstraintLayout>
Here is how it will look (I am adding a screenshot from the layout editor for better understanding ConstaintLayout)
Some extra information:
ConstraintLayout is not meant to have nested view groups (in your case you have LinearLayout inside constraintlayout).
ConstraintLayout allows you to create large and complex layouts with a flat view hierarchy (no nested view groups). It's similar to RelativeLayout in that all views are laid out according to relationships between sibling views and the parent layout, but it's more flexible than RelativeLayout and easier to use with Android Studio's Layout Editor.
You can Use ConstraintLayout with guidelines and Chains to support different screen sizes, you won't have to use fixed sizes on your views and you will be able to use a single layout to support different screen size.
Give the adview or it's surrounding layout a minimum height equal to the smart banner content in your case likely 90px.
It's jumping because with no content loaded your wrap_content height = 0, then it gets a new height of x, so your imageview shifts down x.
This layout will display a View with a color and another with another color.
When layout_constraintWidth_percent = 1 the views are the same width. When I set it between 0.92 <> 1 the foreground view becomes bigger then the background.
Can anyone solve this? I need the foreground to be x percentage of the background
<?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:paddingTop="15dp"
android:paddingBottom="15dp"
>
<View
android:id="#+id/background"
android:layout_width="match_parent"
android:layout_height="100dp"
android:layout_marginEnd="16dp"
android:layout_marginStart="16dp"
android:background="#color/colorPrimary"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
/>
<View
android:id="#+id/foreground"
android:layout_width="0dp"
android:layout_height="80dp"
android:background="#color/colorAccent"
app:layout_constraintWidth_percent="0.94"
app:layout_constraintHorizontal_bias="0"
app:layout_constraintBottom_toBottomOf="#id/background"
app:layout_constraintLeft_toLeftOf="#id/background"
app:layout_constraintRight_toRightOf="#id/background"
app:layout_constraintTop_toTopOf="#id/background"
/>
</android.support.constraint.ConstraintLayout>
Remove the start and end margins of the background. If you want left and right margins, put them on the parent ConstraintLayout instead. As it is now you have margins on background but not on foreground.
Also set the background width to 0dp (the same as foreground). This way the background will be the full width of the parent ConstraintLayout (which can itself apply the margins you want) and the foreground will be the specified percentage of the background. Also set the horizontal bias of the foreground to 0.5 if you want it to be centered.
Like this
<?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:paddingTop="15dp"
android:paddingBottom="15dp"
android:layout_marginEnd="16dp"
android:layout_marginStart="16dp"
>
<View
android:id="#+id/background"
android:layout_width="0dp"
android:layout_height="100dp"
android:background="#color/colorPrimary"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
/>
<View
android:id="#+id/foreground"
android:layout_width="0dp"
android:layout_height="80dp"
android:background="#color/colorAccent"
app:layout_constraintWidth_percent="0.94"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintBottom_toBottomOf="#id/background"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="#id/background"
/>
</android.support.constraint.ConstraintLayout>
As stated from the doc, the percentage is relative to the parent:
When a dimension is set to MATCH_CONSTRAINT, the default behavior is
to have the resulting size take all the available space. Several
additional modifiers are available:
layout_constraintWidth_min and layout_constraintHeight_min : will set
the minimum size for this dimension
layout_constraintWidth_max and
layout_constraintHeight_max : will set the maximum size for this
dimension
layout_constraintWidth_percent and
layout_constraintHeight_percent : will set the size of this dimension
as a percentage of the parent
The app:layout_constraintWidth_percent attribute is calculated according to the parent ConstraintLayout's dimension and not the horizontal constraints of the View. So you need to wrap the foreground in another ConstraintLayout like this (which is a bit ugly because of the nested layout):
<?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:paddingTop="15dp"
android:paddingBottom="15dp">
<View
android:id="#+id/background"
android:layout_width="0dp"
android:layout_height="100dp"
android:layout_marginEnd="16dp"
android:layout_marginStart="16dp"
android:background="#color/colorPrimary"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<android.support.constraint.ConstraintLayout
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="#id/background"
app:layout_constraintLeft_toLeftOf="#id/background"
app:layout_constraintRight_toRightOf="#id/background"
app:layout_constraintTop_toTopOf="#id/background">
<View
android:id="#+id/foreground"
android:layout_width="0dp"
android:layout_height="80dp"
android:background="#color/colorAccent"
app:layout_constraintHorizontal_bias="0"
app:layout_constraintWidth_percent="0.94"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
</android.support.constraint.ConstraintLayout>
</android.support.constraint.ConstraintLayout>
Keep in mind that using app:layout_constraintWidth_percent and margins on a View at the same time can potentially lead to some problems because the margins aren't taken into account for the width percentage.
You can also consider removing the margins from the background and possibly adding them to root ConstraintLayout as padding and I think this would help avoid having a nested layout:
<?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:paddingTop="15dp"
android:paddingBottom="15dp"
android:paddingStart="16dp"
android:paddingEnd="16dp">
<View
android:id="#+id/background"
android:layout_width="0dp"
android:layout_height="100dp"
android:background="#color/colorPrimary"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<View
android:id="#+id/foreground"
android:layout_width="0dp"
android:layout_height="80dp"
android:background="#color/colorAccent"
app:layout_constraintWidth_percent="0.94"
app:layout_constraintHorizontal_bias="0"
app:layout_constraintBottom_toBottomOf="#id/background"
app:layout_constraintLeft_toLeftOf="#id/background"
app:layout_constraintRight_toRightOf="#id/background"
app:layout_constraintTop_toTopOf="#id/background"/>
</android.support.constraint.ConstraintLayout>
I've been experimenting with ConstraintLayout, is there a way to set the max width of a view to a percentage of the parent (and a height of match constraint and dimension ratio of 1:1)?
Here is the code without using max width:
<?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="wrap_content">
<FrameLayout
android:id="#+id/frameLayout3"
android:layout_width="0dp"
android:layout_height="259dp"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:background="#android:color/black"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toEndOf="#+id/imageView"
app:layout_constraintTop_toTopOf="parent"/>
<ImageView
android:id="#+id/imageView"
android:layout_width="0dp"
android:layout_height="0dp"
android:src="#android:drawable/ic_menu_add"
app:layout_constraintBottom_toBottomOf="#+id/frameLayout3"
app:layout_constraintDimensionRatio="1:1"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintWidth_percent="0.3"/>
</android.support.constraint.ConstraintLayout>
This is the result:
Tablet:
Phone:
I achieved the max width percentage using two attributes:
app:layout_constraintWidth_max="wrap"
app:layout_constraintWidth_percent="0.4"
Example:
<TextView
android:id="#+id/textView2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:text="Helo world"
android:textAlignment="viewStart"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintWidth_max="wrap"
app:layout_constraintWidth_percent="0.4" />
The text width will increase to 40% of parent and then wrap if the content exceeds that.
If I'm understanding your problem right then You're almost there. I think you're giving frameLayout static height that's why it is not giving the appropriate result on tablet.. because you set the height according to phone preview. What you need to do is make the height of frameLayout relative to imageView.. so when imageView grows in size the frameLayout also grows with it.
I think you should do something like this
<?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="wrap_content">
<ImageView
android:id="#+id/imageView"
android:layout_width="0dp"
android:layout_height="0dp"
android:src="#android:drawable/ic_menu_add"
app:layout_constraintDimensionRatio="1:1"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintWidth_percent="0.3" />
<FrameLayout
android:id="#+id/frameLayoutTwo"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="#android:color/black"
app:layout_constraintBottom_toBottomOf="#+id/imageView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#+id/imageView"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
I checked and this gives the same result in phone and tablet. Correct me if I misunderstood your problem.
No, there is not. I think we should file a feature request. I am pretty sure that PercentRelativeLayout also does not have this feature. (This answer is accurate for ConstraintLayout 1.1)
You can set a LinearLayout or other ViewGroup as exact percent width and place your wrap_content view inside this layout.
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="#+id/image_place_holder"
android:layout_width="0dp"
android:layout_height="0dp"
android:scaleType="centerCrop"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<!-- This LinearLayout will have exact 80% of parent width-->
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintWidth_percent="0.8">
<!-- This MaterialCardView will get a wrap_content width,
with a max width of his parent LinearLayout, which is 80% -->
<com.google.android.material.card.MaterialCardView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="#dimen/half_activity_horizontal_margin"
android:layout_marginTop="#dimen/half_activity_vertical_margin"
android:layout_marginEnd="#dimen/half_activity_horizontal_margin"
android:layout_marginBottom="#dimen/half_activity_vertical_margin"
android:backgroundTint="?attr/colorPrimary">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxLines="1"
android:paddingStart="#dimen/half_activity_horizontal_margin"
android:paddingEnd="#dimen/half_activity_horizontal_margin"
android:text="Lorem ipsum"
android:textAppearance="?attr/textAppearanceCaption" />
</com.google.android.material.card.MaterialCardView>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
I need to build a square that always spreads over the entire width of the screen (portrait orientation), whatever the size of the screen. Below this square and some fixed height widgets, I want to allocate the remaining available space to a text field.
The simplified code below shows what I have tried so far:
<?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"
tools:context=".ScMainFull"
>
<android.support.constraint.ConstraintLayout
android:id="#+id/Grid"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintDimensionRatio="1:1"
android:layout_margin="16dp"
app:layout_constraintVertical_chainStyle="spread_inside"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toTopOf="#+id/button1"
/>
<Button
android:id="#+id/button1"
android:layout_width="0dp"
android:layout_height="48dp"
android:text="1"
android:layout_margin="16dp"
app:layout_constraintTop_toBottomOf="#+id/Grid"
app:layout_constraintBottom_toTopOf="#+id/Report"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
/>
<TextView
android:id="#+id/Report"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_margin="16dp"
app:layout_constraintTop_toBottomOf="#+id/button1"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
/>
</android.support.constraint.ConstraintLayout>
On the vertical axis, the available space (total height less vertical margins and fixed height button) is evenly distributed between the two widgets that have layout_height="0dp" ignoring the horizontal constraints in the first widget.
What should I change in this code to have the space allocated to the textview calculated after the square has been built to occupy the full width of the screen? Another way to ask the same question would be: how can I force the horizontal constraints on the square to get priority over its vertical constraints?
Just remove the squared top ConstraintLayout from the chain.
<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.support.constraint.ConstraintLayout
android:id="#+id/Grid"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintDimensionRatio="1"
android:layout_margin="16dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
/>
<Button
android:id="#+id/button1"
android:layout_width="0dp"
android:layout_height="48dp"
android:text="1"
android:layout_margin="16dp"
app:layout_constraintVertical_chainStyle="spread_inside"
app:layout_constraintTop_toBottomOf="#+id/Grid"
app:layout_constraintBottom_toTopOf="#+id/Report"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
/>
<TextView
android:id="#+id/Report"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_margin="16dp"
app:layout_constraintTop_toBottomOf="#+id/button1"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
/>
</android.support.constraint.ConstraintLayout>
You are doing it wrong if you are thinking about nesting another ViewGroup.