35

I'm trying to utilize a ConstraintLayout (version 1.0.2) to set the height of 2 side-by-side views to match the tallest one of them. This serves as a ViewHolder in for a RecyclerView, where each TextView gets an arbitrary length of text...

If I set each to wrap_content, the shorter one will shrink. If I set both to 0dp (match_contraints), both end up 0 height.

Here's the setup:

<?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_marginLeft="2dp"
    android:layout_marginRight="2dp"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <TextView
        android:id="@+id/id1"
        android:layout_width="60dp"
        android:layout_height="0dp"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toStartOf="@+id/id2"/>

    <TextView
        android:id="@+id/id2"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toEndOf="@+id/id1"
        app:layout_constraintEnd_toEndOf="parent"/>

</android.support.constraint.ConstraintLayout>

I suppose this is a bug, as "0dp" should act more like match_parent than actual 0 dp.

On iOS, by the way, the equivalent Auto Layout rules (of setting views' heights to match top and bottom of parent) produce the expected result.

Of course this is pretty simple using LinearLayout, but this layout plays part in a larger layout, and I'd like to trim the view hierarchy...

jazzgil
  • 2,250
  • 2
  • 19
  • 20

5 Answers5

8

Answering, in case anyone is looking out for answer in future.

ConstraintLayout introduced Barrier in v1.1 to achieve one such functionality asked by the OP in the question

The above mentioned functionality can be achieved using below 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_marginLeft="2dp"
    android:layout_marginRight="2dp"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

  <TextView
      android:id="@+id/id1"
      android:layout_width="60dp"
      android:layout_height="wrap_content"
      app:layout_constraintTop_toTopOf="parent"
      app:layout_constraintLeft_toLeftOf="parent"
      app:layout_constraintBottom_toBottomOf="@+id/barrier"
      app:layout_constraintVertical_bias="0.0"
      android:text="@string/id1_text" />

  <TextView
      android:id="@+id/id2"
      android:layout_width="0dp"
      android:layout_height="wrap_content"
      app:layout_constraintLeft_toRightOf="@+id/id1"
      app:layout_constraintRight_toRightOf="parent"
      app:layout_constraintTop_toTopOf="parent"
      app:layout_constraintBottom_toBottomOf="@+id/barrier"
      app:layout_constraintVertical_bias="0.0"
      android:text="@string/id2_text" />

  <android.support.constraint.Barrier
      android:id="@+id/barrier"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      app:barrierDirection="bottom"
      app:constraint_referenced_ids="id1,id2" />

</android.support.constraint.ConstraintLayout>
PunitD
  • 2,293
  • 1
  • 20
  • 29
  • 1
    You should use Ctrl+K or Cmd+K to properly format your source code chunks. – Eugene Brusov Nov 15 '17 at 19:21
  • Did you mean to put `app:layout_constraintBottom_toBottomOf="@+id/barrier"` on the second text field as well? Or is it not needed? – HughHughTeotl Mar 12 '18 at 21:38
  • 10
    Actually, I don't think this works at all. By putting `layout_height`s of `0dp` on `id1` and `wrap_content` on `id2`, you're saying that `id2` must fit its content and that `id1` must match whatever that is. Ie, if `id1` is taller than `id2`, the row won't resize to fit it. – HughHughTeotl Mar 12 '18 at 22:35
  • @HughHughTeotl Yes, you are right. Both textview should have `bottom constraint` against `Barrier`. And also there is no point in using `layout_height` as `0dp` for both of the `textview` since we want them to have height equal to `max(tv1,tv2)'s` content height. – PunitD Mar 13 '18 at 03:47
  • 4
    @Droidwala But what should `layout_height` be set to? If `0dp` then it takes up an undefined amount of space, since there's no defined height for the barrier to butt up against. If `wrap_content` the elements just take the height of their contents, regardless of where the barrier is. So it seems like barriers can't be used to change the height of the things they reference... right? Or am I missing something? – HughHughTeotl Mar 13 '18 at 13:35
  • 1
    @HughHughTeotl It should be `wrap_content` because you don't want one element to adjust its height as per other elements. That's not the use case of Barrier. It should be used in a case you want to position a 3rd element in relation to group of elements. In above case if you would like to add Button below these 2 textviews(with varying height) you would be using Barrier so as to make sure you always see it below those 2 textviews and not simply try to figure out which textview will have greater content and align button below it.You simply constrain top of your button to barrier's bottom. – PunitD Mar 13 '18 at 14:41
  • 4
    @Droidwala Thanks. This was the use case in the original question - and I'd come to the conclusion that Barrier couldn't do that, which you've confirmed. Frustrating, but thanks for the comments :) – HughHughTeotl Mar 13 '18 at 17:54
  • 10
    So this isn't the answer and it isn't possible? – behelit Jun 01 '19 at 00:10
  • 7
    it can be done using LinearLayout, place 2 view inside it with height match_parent, while the parent's height is wrap content – koceeng Apr 04 '20 at 04:37
  • @behelit do you know the solution now? Nothing works for me atm, not even barriers. // edit: This works as a workaround with LinearLayout: https://stackoverflow.com/questions/47305334/how-to-set-linear-layout-childs-height-as-tallest-child-height – solidogen May 12 '20 at 12:37
  • 1
    @koceeng 's answer is the only one working for me. I wasn't able to achieve the same using ConstraintLayout – reavcn Nov 11 '21 at 15:22
0

This might help you.

<android.support.constraint.ConstraintLayout
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin">

    <TextView
        android:id="@+id/tv_1"
        android:layout_width="150dp"
        android:layout_height="match_parent"
        android:layout_marginEnd="8dp"
        android:layout_marginRight="8dp"
        android:background="@color/colorAccent"
        android:gravity="center"
        android:padding="@dimen/activity_vertical_margin"
        android:text="sjdjhshdjhdjhsdgfjhgsdjfgjsdgfjsdgfhgdsjhfghs"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toLeftOf="@+id/tv_2"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/tv_2"
        android:layout_width="150dp"
        android:layout_height="match_parent"
        android:background="@color/colorPrimary"
        android:gravity="center"
        android:padding="@dimen/activity_vertical_margin"
        android:text="sjdjhsjhd"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toRightOf="@+id/tv_1"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</android.support.constraint.ConstraintLayout>

enter image description here

enter image description here

Eugene Brusov
  • 17,146
  • 6
  • 52
  • 68
S Haque
  • 6,881
  • 5
  • 29
  • 35
0

This is tricky and slow, but it works.

The point is:

  • Add additional invisible same layout for measure height. This one has wrap_content height attribute, so it will stretch parent if it is big enough.
  • Set your visible layout height to 0dp, so it will fill rest of parent.

As you can see the capture below, we have two layouts. Hidden one is wrap_contents

enter image description here

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <TextView
        android:id="@+id/view_1"
        android:layout_width="wrap_content"
        android:layout_height="0dp"
        android:background="#DDDDDD"
        android:text="@android:string/yes"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toLeftOf="@+id/view_2"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/view_1_invisible"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="#DDDDDD"
        android:text="@android:string/yes"
        android:visibility="invisible"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toLeftOf="@+id/view_2"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/view_2"
        android:layout_width="100dp"
        android:layout_height="0dp"
        android:background="#DDDDDD"
        android:text="@android:string/httpErrorBadUrl"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toRightOf="@+id/view_1"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/view_2_invisible"
        android:layout_width="100dp"
        android:layout_height="wrap_content"
        android:background="#DDDDDD"
        android:text="@android:string/httpErrorBadUrl"
        android:visibility="invisible"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toRightOf="@+id/view_1"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>
Stanley Ko
  • 3,383
  • 3
  • 34
  • 60
0

I've managed to do this with LinearLayout

  • parent to be height = wrap content
  • children to be height = match parent
  • children width = 0 and same weight

image

 <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_height="wrap_content"
        android:layout_width="match_parent"
        android:orientation="horizontal"
        >
<TextView
        android:layout_weight="1"
        android:id="@+id/id1"
        android:layout_height="match_parent"
        android:layout_width="0dp"
        android:background="@color/green_400"
        android:text="11"
        android:textSize="50sp"
        />

<TextView
        android:layout_weight="1"
        android:id="@+id/id2"
        android:layout_height="wrap_content"
        android:layout_width="0dp"
        android:background="@color/cat_grey_lite"
        android:text="2222222222"
        android:textSize="50sp"
        />
</LinearLayout>
GaRRaPeTa
  • 5,459
  • 4
  • 37
  • 61
-2

<TextView
    android:id="@+id/txt_service_request_id"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:background="@drawable/bg_rectangle_blue"
    android:gravity="center"
    android:padding="8dp"
    android:text="@string/service_request_id"
    android:textColor="@android:color/white"
    android:textSize="12sp"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toStartOf="@+id/txt_service_request_status"
    app:layout_constraintHorizontal_bias="0.5"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent" />

<TextView
    android:id="@+id/txt_service_request_status"
    android:layout_width="0dp"
    android:layout_height="0dp"
    android:background="@drawable/bg_rectangle_blue"
    android:gravity="center"
    android:padding="8dp"
    android:text="@string/service_request_status"
    android:textColor="@android:color/white"
    android:textSize="12sp"
    app:layout_constraintBottom_toBottomOf="@+id/txt_service_request_id"
    app:layout_constraintEnd_toStartOf="@+id/txt_service_request_desc"
    app:layout_constraintHorizontal_bias="0.5"
    app:layout_constraintStart_toEndOf="@+id/txt_service_request_id"
    app:layout_constraintTop_toTopOf="parent" />


<TextView
    android:id="@+id/txt_service_request_desc"
    android:layout_width="0dp"
    android:layout_height="0dp"
    android:background="@drawable/bg_rectangle_blue"
    android:gravity="center"
    android:padding="8dp"
    android:text="@string/service_request_desc"
    android:textColor="@android:color/white"
    android:textSize="12sp"
    app:layout_constraintBottom_toBottomOf="@+id/txt_service_request_id"
    app:layout_constraintEnd_toStartOf="@+id/txt_service_request_cat"
    app:layout_constraintHorizontal_bias="0.5"
    app:layout_constraintStart_toEndOf="@+id/txt_service_request_status"
    app:layout_constraintTop_toTopOf="parent" />

<TextView
    android:id="@+id/txt_service_request_cat"
    android:layout_width="0dp"
    android:layout_height="0dp"
    android:background="@drawable/bg_rectangle_blue"
    android:gravity="center"
    android:padding="8dp"
    android:text="@string/service_request_cat"
    android:textColor="@android:color/white"
    android:textSize="12sp"
    app:layout_constraintBottom_toBottomOf="@+id/txt_service_request_id"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintHorizontal_bias="0.5"
    app:layout_constraintStart_toEndOf="@+id/txt_service_request_desc"
    app:layout_constraintTop_toTopOf="parent" />

Assigning equal width and Height

Developine
  • 12,483
  • 8
  • 38
  • 42
  • I don't get it. Why would this solve it? For all we know your parent constraintLayout could have a fixed size. – behelit Jun 01 '19 at 00:07
  • 1
    Edit: I found your site and can see the full source. It looks like you're just matching the other views to the height of the first one. This only works if the first view is larger than the rest and doesn't work if the 2nd/3rd views grow – behelit Jun 01 '19 at 00:17