43

I'm having 3 view in a row: title, version and imageview (working as button):

  1. title should be wrap_content but respecting the following rules
  2. version should be wrap_content, to right of the title and to left of imageview
  3. imageview has fixed size and is at right top corner of the parent

enter image description here

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:

enter image description here

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.

4ntoine
  • 19,816
  • 21
  • 96
  • 220

4 Answers4

50

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.

enter image description here

enter image description here

However, it looks as desired in Android Studio:

enter image description here

but on hardware device it looks different:enter image description here

When analyzing in Layout Inspector i can see title width is calculated wrong:enter image description here

Probably it's side effect of using it in RecyclerView but anyway...

4ntoine
  • 19,816
  • 21
  • 96
  • 220
  • 4
    I noticed that side effect too for RecyclerViews, solved it by doing .requestLayout() on the stretched textview, but not sure performant doing that onBind is – James Andrew Jun 16 '17 at 15:10
  • I have the same issue with RecyclerView using ConstraintLayout v1.1.3 – reavcn Sep 19 '19 at 14:50
  • I never knew `app:layout_constraintWidth_default` was a property, thanks! – Oblivionkey3 Jun 23 '21 at 22:28
  • Great answer! Thanks for the guidance. Just as a reference for 2022. I added this setup with the `app:layout_constraintWidth_default="wrap"` with `android:layout_width="0dp"` and got a console warning. Changing to `android:layout_width="wrap_content"` and adding `app:layout_constrainedWidth="true"` without `app:layout_constraintWidth_default` it works exactly as expected without console error. – Pieter van der Vyver Aug 26 '22 at 14:31
10

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"


Using android:layout_width="0dp" Using android:layout_width="wrap_content"


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. MaxLines="1" and Ellipsize="end"

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>
Taha Sami
  • 1,565
  • 1
  • 16
  • 43
Vitor Hugo Schwaab
  • 1,545
  • 20
  • 31
0

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

kumara
  • 171
  • 1
  • 1
  • 6
-2

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.

Juan
  • 5,525
  • 2
  • 15
  • 26
  • Yes i know, but it does not work because it's neither percentage nor fixed size. it's image wrap_content width – 4ntoine May 21 '17 at 17:54
  • Would setting a minwidth for the version, or a maxwidth for the version solve you problem? – Juan May 21 '17 at 18:05
  • minwidth for the version is unknown. it can easily be "1.0" and "9.9.9 alpha 34" – 4ntoine May 21 '17 at 18:18
  • in the TextView Tag for the version it should exist: android:minWidth = "30dp" – Juan May 21 '17 at 18:23
  • min width can't be hardcoded as it's unknown and according to my previous comment it can be very different and unknown beforehand (30dp and 130dp) – 4ntoine May 21 '17 at 18:41
  • Well, you cant put a foot size 10 in a shoe size 8. So If you want to use the same layout and have it adapt to size, you are bound to relative measueres. You can do it programatically, or use Contraintlayout with guidelines, or linearlayout with weight sum. I think you will have to think of doing some tradeoff. – Juan May 22 '17 at 01:27
  • i can't see any problems here. title width should be just right calculated according to content size and constraints - see my answer – 4ntoine May 22 '17 at 05:33
  • @4ntoine Well I think you did see it and just assumend that extending the titie to 2 or more rows is ok. Which to me is also a valid alternative. – Juan May 22 '17 at 12:19
  • both wrapping and ellipsize is ok – 4ntoine May 22 '17 at 12:35