How to make view "wrap_content but not larger than" with ConstraintLayout? - android

I'm having 3 view in a row: title, version and imageview (working as button):
title should be wrap_content but respecting the following rules
version should be wrap_content, to right of the title and to left of imageview
imageview has fixed size and is at right top corner of the parent
The problem is if title is too large, the version is moved to right and rule "version is to the left of imageview" is not respected:
So i need to limit title width and make version visible and not moved to the right.
Here is XML:
<?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:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:background="#b3b2b2">
<!-- -->
<TextView
android:id="#+id/LibraryWithVersionItem.title"
android:layout_width="0dp"
android:textStyle="bold"
android:textSize="#dimen/fontSize18"
android:textColor="#color/mySecondaryDarkColor"
android:layout_height="wrap_content"
android:ellipsize="middle"
tools:text="ExampleLibrary 01234567890123456789012345"
app:layout_constraintTop_toTopOf="parent"
android:layout_marginTop="8dp"
android:layout_marginLeft="8dp"
app:layout_constraintLeft_toLeftOf="parent"
/>
<Spinner
android:id="#+id/LibraryWithVersionItem.versions"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:textSize="#dimen/fontSize16"
android:textColor="#color/mySecondaryDarkColor"
tools:listitem="#layout/library_version"
android:layout_marginTop="#dimen/margin8"
android:layout_marginLeft="#dimen/margin8"
android:layout_marginRight="#dimen/margin8"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toRightOf="#+id/LibraryWithVersionItem.title"
app:layout_constraintRight_toLeftOf="#+id/LibraryWithVersionItem.info"
app:layout_constraintHorizontal_bias="0.0"/>
<TextView
android:id="#+id/LibraryWithVersionItem.sentence"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="#id/LibraryWithVersionItem.title"
tools:text="Some library description in one sentence\nbut two lines"
android:layout_marginTop="#dimen/margin8"
android:layout_marginLeft="#dimen/margin8"
app:layout_constraintRight_toLeftOf="#+id/LibraryWithVersionItem.install"
android:layout_marginRight="8dp"
app:layout_constraintHorizontal_bias="0.0"/>
<TextView
android:id="#+id/LibraryWithVersionItem.isInstalled"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="#string/LibraryManager.installed"
android:textColor="#1a7c1a"
android:layout_marginTop="#dimen/margin8"
android:layout_marginBottom="#dimen/margin8"
android:layout_marginLeft="#dimen/margin8"
android:layout_marginRight="#dimen/margin8"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="#id/LibraryWithVersionItem.sentence"
app:layout_constraintRight_toLeftOf="#+id/LibraryWithVersionItem.install"
app:layout_constraintHorizontal_bias="0.0"/>
<!-- information button -->
<ImageView
android:id="#+id/LibraryWithVersionItem.info"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingTop="#dimen/margin8"
android:paddingLeft="#dimen/margin8"
android:paddingRight="#dimen/margin8"
android:paddingBottom="#dimen/margin8"
android:scaleType="center"
android:src="#drawable/ic_info_outline_white_24dp"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<!-- install button -->
<ImageView
android:id="#+id/LibraryWithVersionItem.install"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="#dimen/margin8"
android:paddingRight="#dimen/margin8"
android:paddingTop="#dimen/margin8"
android:paddingBottom="#dimen/margin8"
android:scaleType="center"
android:src="#drawable/ic_get_app_white_24dp"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="#+id/LibraryWithVersionItem.info"/>
</android.support.constraint.ConstraintLayout>
PS 1. layout_width="0dp" + app:layout_constraintWidth_default="wrap" seems to be exactly what i need ("wrap_content but not breaking the constraints") but it does not work (still larger than required):
<TextView
android:id="#+id/LibraryWithVersionItem.title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
android:ellipsize="middle"
android:textColor="#color/mySecondaryDarkColor"
android:textSize="#dimen/fontSize18"
android:textStyle="bold"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintWidth_default="wrap"
tools:text="ExampleLibrary 01234567890123456789012345"
PS 2. Setting min constraint width for the version (app:layout_constraintWidth_min="60dp") does not help too - it's invisible as it's moved too right.

Title and version should be in the chain and app:layout_constraintWidth_default="wrap" used:
<?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:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:background="#b3b2b2">
<!-- information button -->
<ImageView
android:id="#+id/LibraryWithVersionItem.info"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingTop="#dimen/margin8"
android:paddingLeft="#dimen/margin8"
android:paddingRight="#dimen/margin8"
android:paddingBottom="#dimen/margin8"
android:scaleType="center"
android:src="#drawable/ic_info_outline_white_24dp"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<!-- -->
<TextView
android:id="#+id/LibraryWithVersionItem.title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:ellipsize="middle"
android:textColor="#color/mySecondaryDarkColor"
android:textSize="#dimen/fontSize18"
android:textStyle="bold"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintWidth_default="wrap"
tools:text="ExampleLibrary 01234567890123456789012345"
app:layout_constraintRight_toLeftOf="#+id/LibraryWithVersionItem.versions"
android:layout_marginRight="8dp"
android:layout_marginLeft="8dp"
android:paddingBottom="1dp"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintHorizontal_bias="0.0"/>
<Spinner
android:id="#+id/LibraryWithVersionItem.versions"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="#dimen/fontSize16"
android:textColor="#color/mySecondaryDarkColor"
tools:listitem="#layout/library_version"
app:layout_constraintRight_toLeftOf="#id/LibraryWithVersionItem.info"
app:layout_constraintLeft_toRightOf="#+id/LibraryWithVersionItem.title"
android:layout_marginRight="0dp"
app:layout_constraintBottom_toBottomOf="#+id/LibraryWithVersionItem.title"
android:layout_marginBottom="0dp"/>
<TextView
android:id="#+id/LibraryWithVersionItem.sentence"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="#+id/LibraryWithVersionItem.title"
tools:text="Some library description in one sentence\nbut two lines"
android:layout_marginTop="5dp"
android:layout_marginLeft="#dimen/margin8"
app:layout_constraintRight_toLeftOf="#+id/LibraryWithVersionItem.install"
android:layout_marginRight="8dp"
app:layout_constraintHorizontal_bias="0.0"
android:layout_marginStart="#dimen/margin8"
android:layout_marginEnd="8dp"/>
<TextView
android:id="#+id/LibraryWithVersionItem.isInstalled"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="#string/LibraryManager.installed"
android:textColor="#1a7c1a"
android:layout_marginTop="#dimen/margin8"
android:layout_marginLeft="#dimen/margin8"
android:layout_marginRight="#dimen/margin8"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="#+id/LibraryWithVersionItem.sentence"
app:layout_constraintRight_toLeftOf="#+id/LibraryWithVersionItem.install"
app:layout_constraintHorizontal_bias="0.0"
android:layout_marginStart="#dimen/margin8"
android:layout_marginEnd="#dimen/margin8"/>
<!-- install button -->
<ImageView
android:id="#+id/LibraryWithVersionItem.install"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="#dimen/margin8"
android:paddingRight="#dimen/margin8"
android:paddingTop="#dimen/margin8"
android:paddingBottom="#dimen/margin8"
android:scaleType="center"
android:src="#drawable/ic_get_app_white_24dp"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="#+id/LibraryWithVersionItem.info"/>
</android.support.constraint.ConstraintLayout>
I've tried to align version to title baseline but if the title is 2 or more lines it's aligned to the first line and it's not desired. So i had to align version to title bottom and hardcode title -3 bottom padding.
However, it looks as desired in Android Studio:
but on hardware device it looks different:
When analyzing in Layout Inspector i can see title width is calculated wrong:
Probably it's side effect of using it in RecyclerView but anyway...

You want to set android:layout_width="0dp".
Using wrap_content, the view will grow infinitely with the content. By using 0dp and setting its constraints, the view will have the maximum size as default, and the content will grow inside it reaches the limit.
Using android:layout_width="wrap_content"
Using android:layout_width="0dp"
From here-on, do your magic. You can set the TextView's android:maxLines="1" and android:ellipsize="end", adding three dots when reaching the maximum size.
Final layout xml
<?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">
<TextView
android:id="#+id/item_a_receber_historico"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:maxLines="1"
android:ellipsize="end"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:text="John Dreadpool Lennon Of House Stark Man This Name Is Huge!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="#+id/item_a_receber_valor"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<TextView
android:id="#+id/item_a_receber_valor"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginTop="8dp"
android:text="R$420,00"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>

i achieve this by setting layout_width to wrap_content and maxWidth to a value

In ConstraintLayout you can add one or mre guidelines horizontally or vertically which help to divide the screen in sections.
I ussually add the guidelines using the *_pct atribute which set the position as a percentage of the screen width/height.

Related

Last view is getting cropped in constraint layout

I want to build a listview whose every item can have different height as per text content length.
Below is the layout of my listview item. When I tried to set lengthy content on title, the bottom textview is getting cropped, however I wanted parent constraint layout to be expanded as per the text.
Layout
<?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"
android:background="#color/background"
android:minHeight="90dp"
android:padding="16dp">
<ImageView
android:id="#+id/iv_notification_thumbnail"
android:layout_width="36dp"
android:layout_height="36dp"
android:src="#drawable/ic_avatar"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="ContentDescription" />
<TextView
android:id="#+id/tv_notification_title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="8dp"
android:fontFamily="#font/roboto"
android:text="If the cont"
android:textColor="#color/white"
android:textSize="14sp"
app:layout_constraintEnd_toStartOf="#id/tv_notification_time"
app:layout_constraintStart_toEndOf="#id/iv_notification_thumbnail"
app:layout_constraintTop_toTopOf="#id/iv_notification_thumbnail" />
<TextView
android:id="#+id/tv_notification_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="#font/roboto"
android:text="#string/value_place_holder"
android:textColor="#color/text_desc"
android:textSize="12sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="#id/tv_notification_title" />
<TextView
android:id="#+id/tv_notification_desc"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginTop="4dp"
android:fontFamily="#font/roboto_medium"
android:text="#string/submit_to_oms"
android:textColor="#color/text_desc"
android:textSize="10sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="#id/tv_notification_title"
app:layout_constraintStart_toStartOf="#id/tv_notification_title"
app:layout_constraintTop_toBottomOf="#id/tv_notification_title"
tools:ignore="SmallSp" />
<ImageButton
android:id="#+id/ib_unread_dot"
android:layout_width="8dp"
android:layout_height="8dp"
android:background="#drawable/shape_circle_orange"
android:clickable="false"
android:visibility="visible"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="ContentDescription" />
</androidx.constraintlayout.widget.ConstraintLayout>
0dp makes the view follow the defined constraints as priority, and when there is no left space in the Item, it still follows the constraints, making the bottom of the view at the bottom of the parent and the top on the bottom of the title. There is no space between these two constraints when the title is too big.
Instead of 0dp, change the layout_height to wrap_content and it should wrap it's content:
<TextView
android:id="#+id/tv_notification_desc"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:fontFamily="#font/roboto_medium"
android:text="#string/submit_to_oms"
android:textColor="#color/text_desc"
android:textSize="10sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="#id/tv_notification_title"
app:layout_constraintStart_toStartOf="#id/tv_notification_title"
app:layout_constraintTop_toBottomOf="#id/tv_notification_title"
tools:ignore="SmallSp" />

Android - TextView inside a ConstraintLayout goes off to infinity to the right - how to pin with ImageView and have ellipsis too

I am trying to make my TextView has a dynamic width and an ImageView pinned to the end of it, inside of a ConstraintLayout. When the text is very long, I want to use an ellipsis and have the ImageView pin to the view to the right of it.
Here is an example of what I am trying to achieve visually:
With my code, I am able to achieve the first image with thisIsShortText but when I have long text, it looks bad, like this:
The TextView and ImageView just go off to the right to infinity. Can anyone help me fix this? This is the XML code I have. If you just put it into your Android Studio it will look like my images. Thank you:
<?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="70dp">
<!-- This view does not move or change size. -->
<View
android:id="#+id/firstView"
android:layout_width="35dp"
android:layout_height="35dp"
android:background="#android:color/holo_red_dark"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
</View>
<!-- This view's width is dynamic and changes size based on it's text length.
If the length of text is too long to fit, it uses an ellipsize. -->
<TextView
android:id="#+id/textview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:ellipsize="end"
android:maxLines="1"
android:text="thisIsVeryLongTextThatIsTooLongAndIsLong"
android:textColor="#color/primary_text_dark"
android:textSize="16sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="#id/firstView"
app:layout_constraintTop_toTopOf="parent" />
<!-- This view is pinned to the end of textView. -->
<ImageView
android:id="#+id/imageview"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_marginStart="8dp"
android:background="#android:color/holo_purple"
android:src="#android:drawable/ic_dialog_info"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="#id/textview"
app:layout_constraintTop_toTopOf="parent" />
<!-- This view does not move or change size. -->
<View
android:id="#+id/secondView"
android:layout_width="80dp"
android:layout_height="35dp"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:background="#android:color/holo_blue_light"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="#id/thirdView"
app:layout_constraintTop_toTopOf="parent" />
<!-- This view does not move or change size. -->
<View
android:id="#+id/thirdView"
android:layout_width="35dp"
android:layout_height="35dp"
android:background="#android:color/holo_orange_dark"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
You can achieve that by adding the below to the TextView:
Enabling width constraints.
Using a packed chain with a 0 horizontal bias.
Constraint the end to the start of the right view (imageview)
And constraint the end of the info imageview to the start of the secondView
So, you need to add the following to the textview:
app:layout_constrainedWidth="true"
app:layout_constraintHorizontal_bias="0"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintEnd_toStartOf="#id/secondView"
And to the imageview:
app:layout_constraintEnd_toStartOf="#+id/secondView"
Now the entire layout:
<?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="70dp">
<!-- This view does not move or change size. -->
<View
android:id="#+id/firstView"
android:layout_width="35dp"
android:layout_height="35dp"
android:background="#android:color/holo_red_dark"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
</View>
<!-- This view's width is dynamic and changes size based on it's text length.
If the length of text is too long to fit, it uses an ellipsize. -->
<TextView
android:id="#+id/textview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:ellipsize="end"
android:maxLines="1"
android:text="thisIsVeryLongTextThatIsTooLongAndIsLong"
android:textColor="#color/primary_text_dark"
android:textSize="16sp"
app:layout_constrainedWidth="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="#id/imageview"
app:layout_constraintHorizontal_bias="0"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintStart_toEndOf="#id/firstView"
app:layout_constraintTop_toTopOf="parent" />
<!-- This view is pinned to the end of textView. -->
<ImageView
android:id="#+id/imageview"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:background="#android:color/holo_purple"
android:src="#android:drawable/ic_dialog_info"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="#+id/secondView"
app:layout_constraintStart_toEndOf="#id/textview"
app:layout_constraintTop_toTopOf="parent" />
<!-- This view does not move or change size. -->
<View
android:id="#+id/secondView"
android:layout_width="80dp"
android:layout_height="35dp"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:background="#android:color/holo_blue_light"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="#id/thirdView"
app:layout_constraintTop_toTopOf="parent" />
<!-- This view does not move or change size. -->
<View
android:id="#+id/thirdView"
android:layout_width="35dp"
android:layout_height="35dp"
android:background="#android:color/holo_orange_dark"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Preview:

Android ConstraintLayout: Views not respecting margins

I am attempting to create a layout where various pieces of data are separated by a line (View), but the design requires an equal top and bottom spacing from the line. I am trying to use margins to accomplish this, but I am not getting the results I expected. Based on the official documentation, as long as the constraints are set for the margin direction, they should be respected. For some reason the top margin gives us the correct spacing, however the bottom margin does not give any spacing at all. I have created a sample containing only the pertinent layout axml to reproduce, along with a large enough margin to visualize the issue:
<?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:padding="20dp">
<TextView android:text="NAME"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:id="#+id/account_name_label"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
/>
<TextView android:text="Your Name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:id="#+id/account_name"
app:layout_constraintTop_toBottomOf="#+id/account_name_label"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
/>
<View
android:id="#+id/line1"
app:layout_constraintTop_toBottomOf="#+id/account_name"
app:layout_constraintBottom_toTopOf="#+id/account_joined_label"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:layout_width="0dp"
android:layout_height="1dp"
android:background="#000000"
android:layout_marginTop="100dp"
android:layout_marginBottom="100dp"
/>
<TextView android:text="JOINED"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:id="#+id/account_joined_label"
app:layout_constraintTop_toBottomOf="#+id/line1"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
/>
<TextView android:text="January 1, 2019"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:id="#+id/account_joined"
app:layout_constraintTop_toBottomOf="#+id/account_joined_label"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
/>
</android.support.constraint.ConstraintLayout>
The above results in the following, visually:
Now, I can add the android:layout_marginTop="100dp" to the first TextView after the line View to "fix" this, however I want to reuse the styles for the line View, without having to worry about remembering to add a top margin to whatever happens to be the first View after the line View. What am I missing?
Update: Here is what the layout SHOULD look like:
You need to connect the bottom of account_joined to the bottom of parent and the bottom of account_joined_label to the top of account_joined. So you can try this one:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="20dp">
<TextView android:text="NAME"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:id="#+id/account_name_label"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
<TextView android:text="Your Name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:id="#+id/account_name"
app:layout_constraintTop_toBottomOf="#+id/account_name_label"
app:layout_constraintRight_toRightOf="parent" />
<View
android:id="#+id/line1"
app:layout_constraintTop_toBottomOf="#+id/account_name"
app:layout_constraintBottom_toTopOf="#+id/account_joined_label"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:layout_width="0dp"
android:layout_height="1dp"
android:background="#000000"
android:layout_marginTop="100dp"
android:layout_marginBottom="100dp"/>
<TextView android:text="JOINED"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:id="#+id/account_joined_label"
app:layout_constraintTop_toBottomOf="#+id/line1"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toTopOf="#+id/account_joined" />
<TextView android:text="January 1, 2019"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:id="#+id/account_joined"
app:layout_constraintTop_toBottomOf="#+id/account_joined_label"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toBottomOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Some info before the code:
When you use something like android:layout_marginTop="100dp" you are making your layout to a non-responsive one.
Why: In android, different phones got dofferent screen size and what may look good on 1 device with 100dp margin may not look good on another device.
So if possible try not to use large values as fixed sizes, the next part of the question will explain how to handle this.
Here is where the fun begins:
You can simply use Guidelines to fix your margin problems - it will be responsive to all screen sizes and won't have hardcoded value like 120dp.
All you have to do is to constraint "NAME" to the top constraint and "JOINED" to the bottom constraint 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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/account_name_label"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:text="NAME"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="#+id/guideline9" />
<TextView
android:id="#+id/account_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:text="Your Name"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/account_name_label" />
<View
android:id="#+id/line1"
android:layout_width="0dp"
android:layout_height="1dp"
android:layout_marginStart="8dp"
android:background="#000000"
app:layout_constraintBottom_toTopOf="#+id/account_joined_label"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/account_name" />
<TextView
android:id="#+id/account_joined_label"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:text="JOINED"
app:layout_constraintBottom_toTopOf="#+id/guideline8"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<TextView
android:id="#+id/account_joined"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:text="January 1, 2019"
app:layout_constraintBottom_toTopOf="#+id/account_joined_label"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<android.support.constraint.Guideline
android:id="#+id/guideline8"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.85" />
<android.support.constraint.Guideline
android:id="#+id/guideline9"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.15" />
</android.support.constraint.ConstraintLayout>
And it will look like this:
Now don't be scared, your layout looks ok - it's just my lame lame skills in editing photos (check this on your device).
The important thing is that you can change the look of your layout by changing the value of this line in your guidelines:
app:layout_constraintGuide_percent="0.15"
If anything was not understandable feel free to ask.

ConstraintLayout set constraints on views to grow but not touch

I have three views in a constraint layout A (textview), B(textview) and C (imageview). B have dynamic text and hence I want it to grow as much as possible but without touching C. It can have multiple lines but I don't want to fix its width and shouldn't make C off screen. How can I use constraint layout for such layout. This is what I want to achieve https://i.stack.imgur.com/EIbnz.png If the text is more, make it multiline. This is what I get https://i.stack.imgur.com/VG7Z5.png
.The last image view is pushed out of screen if text is long.
<?xml version="1.0" encoding="utf-8"?><androidx.constraintlayout.widget.ConstraintLayout
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:background="#drawable/button_background_rounded_gray"
android:id="#+id/container"
android:layout_width="wrap_content"
android:layout_height="30dp">
<androidx.appcompat.widget.AppCompatTextView
android:id="#+id/docIcon"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:textAllCaps="true"
android:gravity="center"
android:text="PDF"
android:textColor="#color/tcWhite"
android:background="#drawable/button_background_rounded_red"
android:layout_marginStart="10dp"
android:textSize="7sp"
android:layout_width="20dp"
android:layout_height="20dp"/>
<androidx.appcompat.widget.AppCompatTextView
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:textSize="12sp"
android:id="#+id/docName"
tools:text="Accommodation Voucher - Circus at Disneyland Paris - Demo - 11 Oct.pdf"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
app:layout_constraintStart_toEndOf="#+id/docIcon"
android:layout_gravity="center_vertical"/>
<androidx.appcompat.widget.AppCompatImageView
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:id="#+id/docStatus"
app:srcCompat="#drawable/ic_picture_as_pdf_red_24dp"
android:layout_marginEnd="10dp"
android:layout_width="20dp"
android:layout_height="20dp"
app:layout_constraintStart_toEndOf="#+id/docName"/>
You don't show how the overall width for ConstraintLayout that you posted is determined. For this answer, I use match_parent but another constraint will work as well.
I key to allowing the text to expand to the constraints but still honor the constraints is to set app:layout_constrainedWidth="true" on the TextView. I have also placed the three views into a horizontal chain. See the ConstraintLayout Developer Guide.
WRAP_CONTENT : enforcing constraints (Added in 1.1)If a dimension is set to WRAP_CONTENT, in versions before 1.1 they will be treated as a literal dimension -- meaning, constraints will not limit the resulting dimension. While in general this is enough (and faster), in some situations, you might want to use WRAP_CONTENT, yet keep enforcing constraints to limit the resulting dimension. In that case, you can add one of the corresponding attribute:
app:layout_constrainedWidth=”true|false”
app:layout_constrainedHeight=”true|false”
activity_main.xml
<androidx.appcompat.widget.AppCompatTextView
android:id="#+id/docIcon"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_marginStart="10dp"
android:background="#drawable/ic_launcher_background"
android:gravity="center"
android:text="PDF"
android:textColor="#android:color/white"
android:textSize="7sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="#+id/docName"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:textAllCaps="true" />
<androidx.appcompat.widget.AppCompatTextView
android:id="#+id/docName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:text="This is a very long name. This is a very long name. This is a very long name. "
android:textSize="12sp"
app:layout_constrainedWidth="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="#+id/docStatus"
app:layout_constraintStart_toEndOf="#+id/docIcon"
app:layout_constraintTop_toTopOf="parent" />
<androidx.appcompat.widget.AppCompatImageView
android:id="#+id/docStatus"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_marginEnd="10dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#+id/docName"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="#drawable/ic_launcher_foreground" />
</androidx.constraintlayout.widget.ConstraintLayout>
Here is a simpler demonstration.
activity_main.xml
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="400dp"
android:layout_height="wrap_content"
android:background="#android:color/darker_gray">
<Button
android:id="#+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:text="Button"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<EditText
android:id="#+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Type here..."
app:layout_constrainedWidth="true"
app:layout_constraintEnd_toStartOf="#+id/imageView"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toEndOf="#+id/button"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="#+id/imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="#mipmap/ic_launcher" />
</androidx.constraintlayout.widget.ConstraintLayout>
Add those two properties to the second AppCompactTextView
app:layout_constraintRight_toRightOf="#id/docStatus"
app:layout_constraintHorizontal_bias="1"
And make the width of that textView to 0dp.

Text wrapping in Constraint layout

Trying to make a really simple layout for a settings page using ConstraintLayout.
Simple text views to the left one below the other and a switch to the right to the center.
The layout I have works fine for newer devices, but as soon I switch to a Nexus 4 or older, the switch goes below/disappears from the view.
Here is my layout code,
<android.support.constraint.ConstraintLayout
android:id="#+id/locationLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="parent">
<TextView
android:id="#+id/locationTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="#string/location_title"
android:textStyle="bold"
app:layout_constraintEnd_toStartOf="#id/guidelineLocationLayout"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:textSize="16sp"/>
<TextView
android:id="#+id/locationDescription"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="#string/location_description"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="#+id/locationTitle"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintLeft_toLeftOf="#id/locationTitle"
app:layout_constraintRight_toLeftOf="#id/guidelineLocationLayout"
android:textSize="12sp"
/>
<Switch
android:id="#+id/locationPermissionSwitch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="#id/guidelineLocationLayout"
app:layout_constraintTop_toBottomOf="parent"
app:layout_constraintBottom_toTopOf="parent"/>
<View
android:id="#+id/viewLocationLayout"
android:layout_width="fill_parent"
android:layout_height="1dip"
android:background="#d6d6d6"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/locationDescription"/>
<android.support.constraint.Guideline
android:id="#+id/guidelineLocationLayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_end="48dp" />
</android.support.constraint.ConstraintLayout>
And here are how the constraints look like for the Pixel 2XL,
Here is how they look on a smaller device,
I have used 0dp width for the long description and defined left and right constraints, anything else I could do?
You can use barriers instead of guidelines because a Barrier references multiple widgets as input, and creates a virtual guideline based on the most extreme widget on the specified side.
According to the Documentation
Similar to a guideline, a barrier is an invisible line that you can
constrain views to. Except a barrier does not define its own position;
instead, the barrier position moves based on the position of views
contained within it. This is useful when you want to constrain a view
to the a set of views rather than to one specific view.
Hope this helps you. I've used barrier instead of guideline.
<?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:id="#+id/locationLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="parent">
<TextView
android:id="#+id/locationTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="Save location to the song"
android:textSize="16sp"
android:textStyle="bold"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/locationDescription"
android:layout_width="261dp"
android:layout_height="32dp"
android:text="Your location is only requested when a new song is identified. Location details are never sent to the server"
android:textSize="12sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="#+id/locationTitle" />
<android.support.constraint.Barrier
android:id="#+id/barrier"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="end"
app:constraint_referenced_ids="locationDescription,locationTitle" />
<Switch
android:id="#+id/locationPermissionSwitch"
android:layout_width="41dp"
android:layout_height="26dp"
android:layout_marginBottom="8dp"
android:layout_marginTop="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#+id/barrier"
app:layout_constraintTop_toTopOf="parent" />
<View
android:id="#+id/viewLocationLayout"
android:layout_width="fill_parent"
android:layout_height="1dip"
android:background="#d6d6d6"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/locationDescription" />
</android.support.constraint.ConstraintLayout>
You need to change the constraints of the switch like this
<Switch
android:id="#+id/locationPermissionSwitch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="#id/guidelineLocationLayout"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
You are constraining the bottom of the switch to the top of the parent and top of the switch to the bottom of the parent. You have to change it to layout_constraintTop_toTopOf and layout_constraintBottom_toBottomOf

Categories

Resources