How to set a width in percent with maximum width in dp? - android

I have an ImageView that needs to stretch with screen width. But I do not want the view to stretch indefinitely. I also need to keep the ratio of the image to 16:9. I am having a hard time to set a maximum width when using percentage in ConstraintLayout. I found the ratio can be set using ConstraintLayout, but it is not required to use this layout as long as the ratio will be preserved (note that I cannot use a 3rd party library other than Glide). Here is what I have now.
<?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="wrap_content">
<ImageView
android:id="#+id/list_item_image"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintDimensionRatio="16:9"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="#id/list_item_title"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintWidth_percent="0.5"
app:layout_constraintWidth_max="163dp"
tools:src="#color/white" />
<TextView
android:id="#+id/list_item_title"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#id/list_item_image"
app:layout_constraintTop_toTopOf="parent"
tools:text="Test Title" />
</android.support.constraint.ConstraintLayout>
Without the app:layout_constraintWidth_max everything is working fine, but once that attribute is set, the percentage stops working at all and width is set to some arbitrary value (definitely not the 163dp I used). But the fun part is that if the max width is higher than the half of the screen width, the percentage is working again. It seems like those two attributes cannot work together, but I do not know how else to define what I need to do.

You can do this without constraint layout you can use LinearLayout or RelativeLayout, Set Image Width to match parent and scale your image to
Link for details:
https://thoughtbot.com/blog/android-imageview-scaletype-a-visual-guide

Indeed, it seems like combining app:layout_constraintWidth_percent="0.5" and app:layout_constraintWidth_max together does not allow to produce the expected result. A workaround for this would be to use a Guideline to constrain the ImageView with the desired percentage. You can then constrain the start of the TextView to the Guideline as well or to the end of the ImageView, depending on what you want:
<?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="wrap_content">
<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:id="#+id/list_item_image"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintDimensionRatio="16:9"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="#id/guideline"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintWidth_max="163dp"
tools:src="#android:color/black" />
<TextView
android:id="#+id/list_item_title"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#id/list_item_image"
app:layout_constraintTop_toTopOf="parent"
tools:text="Test Title" />
</android.support.constraint.ConstraintLayout>

Related

How to set size of layouts in Android as a percentage of the sceen size

I have a ConstraintLayout with an inner ConstraintLayout and a inner linear layout in Android. Here you can see my 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:id="#+id/outerConstraintLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="#+id/linearLayout"
android:layout_marginTop="#dimen/_5sdp"
android:layout_marginBottom="#dimen/_8sdp"
android:layout_width="#dimen/_235sdp"
android:layout_height="0dp"
android:orientation="vertical"
android:background="#drawable/rim"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.93"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.75">
</LinearLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/innerConstraintLayout"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="#+id/linearLayout"
app:layout_constraintEnd_toStartOf="#+id/linearLayout"
android:layout_marginLeft="#dimen/_10sdp"
android:layout_marginRight="#dimen/_30sdp"
android:background="#drawable/rim"
android:padding="12dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="#+id/linearLayout"
>
<TextView
android:id="#+id/textView_Name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Inner Constrained Layout"
android:textColor="#000000"
android:textSize="#dimen/_10ssp"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="#+id/button_okay"
android:layout_width="match_parent"
android:layout_height="#dimen/_25sdp"
android:background="#color/colorGreen"
android:text="Okay"
android:textAllCaps="false"
android:textColor="#121212"
android:textSize="#dimen/_8ssp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.553"
app:layout_constraintStart_toStartOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
The problem is that the two layouts have different proportions when being displayed on different screens (see screenshot):
This does not look good as depending on the used device the layouts look quite different regarding their proportions (width and height). Now my question is whether there is a way of just setting the layouts' width and height generally as a percentage of the screen size and thus make the proportions of the width and height of layouts independent of the screen size? Or how else would you design layouts sucht that their proportions between width and height is more or less independant of the screen size?
I'd appreciate every comment and will be happy if you share your experience on that issue?
Now my question is whether there is a way of just setting the layouts' width and height generally as a percentage of the screen size
It can be done using constarintLayout like this:
Take any view, give it android:layout_height="0dp" - now it will respect your constraints, in additions add to it app:layout_constraintHeight_percent="0.15"
Now the view got the height of 15% of the parent size.
the same can be done for the width android:layout_width="0dp"
together with app:layout_constraintWidth_percent="0.5" and now your view will take 50% of your parent size.
You can combine those 2 like this:
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintWidth_percent="0.5"
app:layout_constraintHeight_percent="0.15"
Now your view is both 15% of the parent Width and 50% the parent height, change those numbers and you can control your view size according to your needs.
<LinearLayout
...
android:layout_width="#dimen/_235sdp"
...
>
I assume in #dimen/_235sdp you have a value of 235dp. If so, that line gives your LinearLayout fixed width of 235dp on all devices, so you can't expect it to scale percentage-wise.
Try using a vertical Guideline with percentage value and remove all other fixed sizes:
<?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:id="#+id/outerConstraintLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.constraintlayout.widget.Guideline
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/guideline"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.3"/>
<LinearLayout
android:id="#+id/linearLayout"
android:layout_marginTop="#dimen/_5sdp"
android:layout_marginBottom="#dimen/_8sdp"
android:layout_width="0dp"
android:layout_height="0dp"
android:orientation="vertical"
android:background="#android:color/holo_red_dark"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="#id/guideline"
app:layout_constraintEnd_toEndOf="parent">
</LinearLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/innerConstraintLayout"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="#dimen/_10sdp"
android:layout_marginEnd="#dimen/_30sdp"
android:background="#android:color/holo_blue_dark"
android:padding="12dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="#id/guideline">
<TextView
android:id="#+id/textView_Name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Inner Constrained Layout"
android:textColor="#000000"
android:textSize="#dimen/_10ssp"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="#+id/button_okay"
android:layout_width="match_parent"
android:layout_height="#dimen/_25sdp"
android:background="#android:color/holo_green_light"
android:text="Okay"
android:textAllCaps="false"
android:textColor="#121212"
android:textSize="#dimen/_8ssp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
In the updated code I added a vertical guidline splitting the screen to 0.3 and 0.7, then I constrained the inner layouts against the guideline to keep the ratio. Now on any device, you should see the left inner layout taking always 0.3 of the width, and the right inner layout taking always 0.7 of the width.
Tip: try avoiding ConstraintLayout inside ConstraintLayout, it should be fully possible to constrain the inner content (i.e. TextView, Button) against the parent ConstraintLayout without breaking the layout.
I had almost the same problem and to solve this problem, I divided each layer into two modes (mobile and tablet) (the Android system itself can recognize the sizes) and expanded both.
In this way, my work was more regular and changes in the next modes were easily possible for me.
my solution:
Make your resource like this.
res/layout/my_layout.xml
layout for normal screen size ("default")
res/layout-large/my_layout.xml
layout for large screen size
If you do not know how to create a layout-large folder, all you have to do is create a folder with the same name in the Project Explorer path and place your layer there.
Then Android itself will automatically be placed in a separate folder for each layer you have in the Android Studio Live folder.
For example, the activity_main folder consists of two layers as shown below
First of all simplify views tree. Use virtual layouts instead of nesting. You can use Guideline, Flow, attribute app:layout_constraintDimensionRatio or chains with weight for ConstraintLayout's children to use needed proportions.
This article may help you
Another way is to create different layout with qualifiers. Would be better to use single layout for better design management.

How to position 2 Views relative to each other?

I would like to position 2 views relative to each other but not simply w.r.t the top, bottom, left or right but in a proportionate way. Let me explain. Here are 4 scenarios of positioning:
Of these, 2) and 4) are easy to do and have in-built support provided by the standard layout containers such as RelativeLayout, ConstraintLayout but my current task requires a positioning depicted in scenarios 1)/3)
A simple solution to this problem involves setting different left/top margins for both the Views w.r.t parent but this means if the need arises to place both the Views together to some other position, all the margins shall have to change.
Instead, what I would like is to have some sort of relative positioning arrangement between these 2 views that keeps them relatively at "right" distance no matter where they are placed as a unit in the parent.
How can I achieve the same? An efficient solution(with flattened hierarchy, no view hacks) would be appreciated.
An efficient solution(with flattened hierarchy, no view hacks) would be appreciated., You can use ConstraintLayout with guidelines.
guidelines have app:layout_constraintGuide_percent attribute making them responsive to the screen size.
you can use it while adding your buttons the app:layout_constraintWidth_percent and app:layout_constraintHeight_percent attributes (not mandatory, you can constraint your views to the guidelines but I believe that it is more simple).
Here is an example for your wanted layout with flattened hierarchy:
<?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">
<Button
android:id="#+id/button2"
android:layout_width="0dp"
android:layout_height="0dp"
android:text="Button"
app:layout_constraintHeight_percent=".1"
app:layout_constraintStart_toStartOf="#+id/guideline"
app:layout_constraintTop_toTopOf="#+id/guideline2"
app:layout_constraintWidth_percent=".3" />
<Button
android:id="#+id/button"
android:layout_width="0dp"
android:layout_height="0dp"
android:text="Button"
app:layout_constraintBottom_toTopOf="#+id/guideline4"
app:layout_constraintEnd_toStartOf="#+id/guideline"
app:layout_constraintHeight_percent=".1"
app:layout_constraintWidth_percent=".3" />
<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=".5" />
<android.support.constraint.Guideline
android:id="#+id/guideline2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent=".4" />
<android.support.constraint.Guideline
android:id="#+id/guideline4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent=".45" />
</android.support.constraint.ConstraintLayout>
It will look like this(I am adding screenshot from the preview for better understanding guidelines):
This was just an example but with those tools, you can create your layout however you would like to.
Some extra information
My solution does not contain any fixed size dimensions on my views, this will make the layout responsive(no need to build a layout for every screen size)
You may also find ConstraintLayout: Circular Positioning related to your question, but I don't think that this is the best thing for you in this specific case.
Yes it is possible using constraint layout checkout below XML code for Point 3.(Same point 2 will be implemeted let me know if you have query)
<?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:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.appcompat.widget.AppCompatButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/buttonA"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:text="Add"
android:layout_marginTop="15dp"
/>
<androidx.appcompat.widget.AppCompatButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintStart_toEndOf="#id/buttonA"
app:layout_constraintEnd_toEndOf="#id/buttonA"
app:layout_constraintTop_toBottomOf="#id/buttonA"
android:text="Add"
/>
</androidx.constraintlayout.widget.ConstraintLayout>`
Please check out below code this is kind of patch but works fine.Here we can put big block to relative to small block.As we have used constraint so will be stick together no matter wherever you put. let me know if i did any thing wrong.
Here we use one dummyView and also app:layout_constraintHorizontal_bias="0.1" for making it relative value changes from 0 to 1 like 1 means 100% stating left to small block smae way 0.5 means 50% from starting small blobk to left.
<?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:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.appcompat.widget.AppCompatButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/buttonA"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:text="Add"
android:layout_marginTop="15dp"
/>
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/dummyView"
app:layout_constraintTop_toBottomOf="#id/buttonA"
app:layout_constraintStart_toStartOf="#id/buttonA"
app:layout_constraintEnd_toEndOf="#id/buttonA"
app:layout_constraintHorizontal_bias="0.1"/>
<androidx.appcompat.widget.AppCompatButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="#id/buttonA"
app:layout_constraintStart_toEndOf="#id/dummyView"
android:text="Add"
/>
</androidx.constraintlayout.widget.ConstraintLayout>

ConstraintLayout: how to have a view be half the screen width and centered?

TL;DR
The view width must be exactly half of the screen, and be centered. Using ConstraintLayout.
Note that the view does not have any inner width.
<View android:background="#ff0000" ... />
Original question
I would like to achieve a layout where a view size is half the screen size, and centered horizontally.
Something like this: |--view--|
I can't find any way using ConstraintLayout. The best i found is by using app:layout_constraintHorizontal_weight="1" on 2 fake views positioned at the full left and full right respectively, and app:layout_constraintHorizontal_weight="1.5" on my view.
Any better way ?
With the beta release you can use percentage widths. If you cannot use the beta release, you can employ two vertical guidelines: one at 25% of the screen width and one at 75% of the width. The view with a width of 0dp would be constrained between these two guidelines. This setup will give you a view that is 1/2 of the screen width and also centered.
The following XML demonstrates both ways; one using the ConstraintLayout beta release and the second using features available in the current production release.
XML Layout
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/activity_main_inference"
android:layout_width="match_parent"
android:layout_height="match_parent">
<View
android:id="#+id/viewTop"
android:layout_width="0dp"
android:layout_height="100dp"
android:layout_marginTop="16dp"
android:background="#android:color/darker_gray"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintWidth_default="percent"
app:layout_constraintWidth_percent="0.5" />
<android.support.constraint.Guideline
android:id="#+id/guidelineLeft"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.25" />
<View
android:layout_width="0dp"
android:layout_height="100dp"
android:layout_marginTop="16dp"
android:background="#android:color/darker_gray"
app:layout_constraintEnd_toStartOf="#id/guidelineRight"
app:layout_constraintStart_toEndOf="#id/guidelineLeft"
app:layout_constraintTop_toBottomOf="#id/viewTop" />
<android.support.constraint.Guideline
android:id="#+id/guidelineRight"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.75" />
</android.support.constraint.ConstraintLayout>
As of** ConstraintLayout1.1.0-beta1**, you can use percent to define widths & heights.
android:layout_width="0dp"
app:layout_constraintWidth_default="percent"
app:layout_constraintWidth_percent=".4"
This will define the width to be 40% of the width of the screen. A combination of this and guidelines in percent allow you to create any percent based layout you want.
try this vertically divide
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.constraint.ConstraintLayout
android:id="#+id/clPart1"
android:layout_width="0dp"
android:layout_height="match_parent"
android:background="#color/white"
android:visibility="visible"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintHorizontal_chainStyle="spread"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="#+id/clPart2">
</android.support.constraint.ConstraintLayout>
<android.support.constraint.ConstraintLayout
android:id="#+id/clPart2"
android:layout_width="0dp"
android:layout_height="match_parent"
android:background="#color/black"
android:visibility="visible"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toRightOf="#+id/clPart1"
app:layout_constraintRight_toRightOf="parent">
</android.support.constraint.ConstraintLayout>
</android.support.constraint.ConstraintLayout>
With ConstraintLayout, you can center a view in the screen 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">
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="#FF0000"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintHeight_percent=".5"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintWidth_percent=".5"></LinearLayout>
</android.support.constraint.ConstraintLayout>
Update your gradle to the last version of ConstraintLayout:
dependencies {
...
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
}
ResultWhat you have to do is:
Just add this in your XML
<View
android:id="#+id/viewV1"
android:layout_height="match_parent"
android:background="#ff0000"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_width="match_parent"
/>
And this in your java.
First import these.
import android.graphics.Point;
import android.support.constraint.ConstraintLayout;
import android.view.Display;
import android.view.View;
Then add these lines in onCreate function of your java file.
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
int width1 = size.x;
//int height = size.y;
View v = findViewById(R.id.viewV1);
ConstraintLayout.MarginLayoutParams params = (ConstraintLayout.MarginLayoutParams) v.getLayoutParams();
params.width = width1/2; params.leftMargin = width1/4; params.rightMargin = width1/4;
v.setLayoutParams(params);
You can also set the Height using this method. And Yes, this View uses half the screen width whatever the screen size is.
As you don't want to do it via java. Add this to your XML.
<android.support.constraint.Guideline
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/guideline5"
app:layout_constraintGuide_begin="411dp"
android:orientation="vertical"
/>
By selecting this, move this guideline to end of the screen and note this value app:layout_constraintGuide_begin="411dp". Now whatever the value is this is your screen's width.
Add marginStart and marginEnd to your view as 411/4 dp. (calculate this value, XML is not going to do that).
This will make your view in center with half width as parent.
Remember not every screen with is 411dp. This will not work for every phone's screen size out there.

Android: ConstraintLayout - How to create a chain with equal weights

I have two views which have to be placed next to each other horizontally and they need to occupy 50% of the space.
This can be done via guidelines easily.
But the issue is that each of the views has to be able to move to take the space of the other view in case the other view is gone.
This is not possible via guidelines but possible when chains are used.
But the issue with the chain is that i am not able to make sure both (when both are visible) take up 50% of the total width horizontal areas assigned to them.
Could someone please see what the issue is with the code below:
<?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:background="#color/dark_background"
android:layout_width="0dp"
android:layout_height="0dp"
android:padding="15dp"
tools:layout_width="500dp"
tools:layout_height="300dp"
>
<!--<android.support.constraint.Guideline-->
<!--android:id="#+id/guideline"-->
<!--android:layout_width="0dp"-->
<!--android:layout_height="0dp"-->
<!--android:orientation="vertical"-->
<!--app:layout_constraintLeft_toRightOf="#id/title"-->
<!--app:layout_constraintRight_toRightOf="#id/title"-->
<!--app:layout_constraintGuide_percent="0.5"-->
<!--/>-->
<TextView
android:id="#+id/title"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="#+id/image"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="#+id/ic_share"
android:ellipsize="marquee"
android:maxLines="4"
android:textSize="20sp"
android:textColor="#000000"
android:text="This is a test content title. This would be changed eventually"
/>
<ImageView
android:id="#+id/image"
android:layout_width="0dp"
android:layout_height="0dp"
android:adjustViewBounds="true"
android:src="#drawable/ic_logo"
app:layout_constraintDimensionRatio="4:3"
app:layout_constraintLeft_toRightOf="#+id/title"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintVertical_bias="0.0"
/>
</android.support.constraint.ConstraintLayout>
Yeah, I think that's a bug. I filed it here:
https://code.google.com/p/android/issues/detail?id=248117

ConstraintLayout aspect ratio

Consider the following layout file:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
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/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#FF0000"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin">
<ImageView
android:layout_width="0dp"
android:layout_height="0dp"
android:background="#0000FF"
android:padding="16dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintDimensionRatio="H,3:1"
tools:layout_editor_absoluteX="16dp" />
</android.support.constraint.ConstraintLayout>
</RelativeLayout>
I am not sure how the app:layout_constraintDimensionRatio works. My understanding is the ratio will always be width:height. So 3:1 will always make the ImageView appear 3 times wider than height. The prefix H or W tells ConstraintLayout which dimension should respect the ratio. If it is H then it means width will be first computed from other constraints and then height will be adjusted according to the aspect ratio. However this is the result of the layout:
The height is 3 times larger than width which is unexpected. Can anyone explain to me how the dimensions are computed with respect to app:layout_constraintDimensionRatio setting?
Your understanding for the way app:layout_constraintDimensionRatio works is correct. If you set app:layout_constraintDimensionRatio="H,3:1" then it means width will be first computed from other constraints and then height will be adjusted according to the aspect ratio. The only problem with your implementation is that you added app:layout_constraintBottom_toBottomOf="parent" to the ImageView, so that it caused app:layout_constraintDimensionRatio to be ignored.
Here's the layout to size your ImageView in 3:1 aspect ratio:
<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="#FF0000">
<ImageView
android:id="#+id/imageView"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:background="#0000FF"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintDimensionRatio="H,3:1" />
</android.support.constraint.ConstraintLayout>
and here's the result view:
Basically, we have
layout_constraintDimensionRatio(width:height)
EXAMPLE
<!-- button which have width = it's content and height = 1/2 width -->
<Button
android:layout_width="wrap_content"
android:layout_height="0dp"
app:layout_constraintStart_toStartOf="parent" <!-- I still think that we don't need this attribute but I when I don't add this, constraint not working -->
android:text="Button TEST RATIO 1"
app:layout_constraintDimensionRatio="2:1" />
Output
<!-- button which have width = it's content and height = 1/2 width -->
<Button
android:layout_width="wrap_content"
android:layout_height="0dp"
app:layout_constraintStart_toStartOf="parent"
android:text="Button TEST RATIO 2"
app:layout_constraintDimensionRatio="2" /> <!-- 2 here <=> 2:1 <=> 2/1 (1:1 <=> 1, 1/2 <=> 0.5, ....) ->
Output
<!-- button which have width = match_parent and height = 1/2 width -->
<Button
android:layout_width="match_parent"
android:layout_height="0dp"
android:text="Button TEST RATIO 3"
app:layout_constraintDimensionRatio="2" />
Output
<!-- button which have width = match constraint and height = 1/2 width -->
<Button
android:layout_width="0dp"
android:layout_height="0dp"
android:text="Button TEST RATIO 4"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintDimensionRatio="2" />
Output
DEMO: https://github.com/PhanVanLinh/AndroidConstraintLayoutRatio
Take a look at these ImageView properties:
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
These properties override the layout_constraintDimensionRatio due to which the ImageView is constrained to the bottom, top and left of the main parent resulting in the View occupying the left, top and bottom portions of the main screen.
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
This would be one solution. You can omit layout_constraintBottom_toBottomOf if you want the View to appear on the top or vice-versa. It would probably be best to remove all the above constraints altogether except the layout_constraintDimensionRatio, which would be the most recommended solution.

Categories

Resources