Wrap_content view inside a ConstraintLayout stretches outside the screen

AndroidAndroid LayoutAndroid Constraintlayout

Android Problem Overview


I am trying to implement a simple chat bubble using a ConstraintLayout. This is what I am trying to achieve:

enter image description here enter image description here

However, wrap_content does not do what I want. It respects the margins, but expands outside of the view bounds. Here is my layout:

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

    <TextView
        android:id="@+id/chat_message"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:padding="16dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintHorizontal_bias="0"
        tools:background="@drawable/chat_message_bubble"
        tools:text="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris sodales accumsan tortor at bibendum."
        android:layout_marginStart="64dp"
        android:layout_marginLeft="64dp"
        android:layout_marginEnd="32dp"
        android:layout_marginRight="32dp"
        android:layout_marginTop="8dp"
        android:layout_marginBottom="8dp" />
</android.support.constraint.ConstraintLayout>

This renders as follows:

enter image description here

I am using com.android.support.constraint:constraint-layout:1.0.0-beta4.

Am I doing something wrong? Is it a bug or just an unintuitive behavior? Can I achieve the proper behavior using a ConstraintLayout (I know I can use other layouts, I am asking about ConstrainLayout specifically).

Android Solutions


Solution 1 - Android

Updated (ConstraintLayout 1.1.+)

Use app:layout_constrainedWidth="true" with android:layout_width="wrap_content"

Previously (deprecated):

app:layout_constraintWidth_default="wrap" with android:layout_width="0dp"

Solution 2 - Android

Outdated: See better answer

No, you cannot do what you want with ConstraintLayout as it is today (1.0 beta 4):

  • wrap_content only asks the widget to measure itself, but won't limit its expansion against eventual constraints
  • match_constraints (0dp) will limit the size of the widget against the constraints... but will match them even if wrap_content would have been smaller (your first example), which isn't what you want either.

So right now, you are out of luck for that particular case :-/

Now... we are thinking about adding extra capabilities to match_constraints to deal with this exact scenario (behaving as wrap_content unless the size ends being more than the constraints).

I cannot promise that this new feature will make it before the 1.0 release though.

Edit: we did add this capability in 1.0 with the attribute app:layout_constraintWidth_default="wrap" (with width set to 0dp). If set, the widget will have the same size as if using wrap_content, but will be limited by constraints (i.e. it won't expand beyond them)

Update Now those tags are deprecated, instead use layout_width="WRAP_CONTENT" and layout_constrainedWidth="true".

Solution 3 - Android

Yep, as mentioned in answer given by Nikolas Roard you should add app:layout_constraintWidth_default="wrap" and set width to 0dp. And to align your bubble right you should set 1.0 for layout_constraintHorizontal_bias.

Here's the final source code:

<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" >

    <TextView
        android:id="@+id/chat_message"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:padding="16dp"
        android:layout_marginTop="8dp"
        android:layout_marginStart="64dp"
        android:layout_marginEnd="8dp"
        android:layout_marginBottom="8dp"
        app:layout_constraintHorizontal_bias="1.0"
        app:layout_constraintWidth_default="wrap"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        android:background="@drawable/chat_message_bubble"
        android:text="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris sodales accumsan tortor at bibendum." />

</android.support.constraint.ConstraintLayout>

As a result it looks like:

enter image description here

Solution 4 - Android

Like the other answers already said, since ConstraintLayout 1.0 it's possible to achieve that, but as of the newest release (1.1.x) they've changed how you do it.

Since the release of ConstraintLayout 1.1 the old app:layout_constraintWidth_default="wrap" and app:layout_constraintHeight_default="wrap" attributes are now deprecated.

If you want to provide a wrap_content behavior, but still enforce the constraints on your View, you should set its width and/or height to wrap_content combined with the app:layout_constrainedWidth=”true|false” and/or app:layout_constrainedHeight=”true|false” attributes, as stated on the docs:

> 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”

As for the latest release, by the time I've answered this, ConstraintLayout is on version 1.1.2.

Solution 5 - Android

Deprecation of app:layout_constraintWidth_default text and its alternative

@nicolas-roard's answer of app:layout_constraintWidth_default="wrap" and android:layout_width="0dp" is now DEPRECATED.

Go ahead and use app:layout_constrainedWidth="true" and android:layout_width="wrap_content".

The reason for deprecation, I dont know. But its right in the source code of ConstraintLayout

Solution 6 - Android

I use this one

app:layout_constraintEnd_toEndOf="parent"

Solution 7 - Android

You should replace

android:layout_width="wrap_content"

with

android:layout_width="match_parent"

from your TextView and then adjust padding and margin accordingly. I have updated your code,

<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/chat_message"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginBottom="8dp"
    android:layout_marginEnd="10dp"
    android:layout_marginLeft="60dp"
    android:layout_marginRight="10dp"
    android:layout_marginStart="60dp"
    android:layout_marginTop="8dp"
    android:padding="16dp"
    app:layout_constraintTop_toTopOf="parent"
    tools:background="#c9c7c7"
    tools:text="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris sodales accumsan tortor at bibendum." />

You will get this result enter image description here

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMarcin JedynakView Question on Stackoverflow
Solution 1 - AndroidSilvia HView Answer on Stackoverflow
Solution 2 - AndroidNicolas RoardView Answer on Stackoverflow
Solution 3 - AndroidEugene BrusovView Answer on Stackoverflow
Solution 4 - AndroidMaukerView Answer on Stackoverflow
Solution 5 - AndroidBolajiView Answer on Stackoverflow
Solution 6 - AndroidjsHateView Answer on Stackoverflow
Solution 7 - AndroidMehulView Answer on Stackoverflow