La vue Wrap_content à l'intérieur d'un ConstraintLayout s'étend à l'extérieur de l'écran

132

J'essaie d'implémenter une simple bulle de discussion en utilisant un fichier ConstraintLayout. C'est ce que j'essaye de réaliser:

entrez la description de l'image ici entrez la description de l'image ici

Cependant, wrap_contentsemblent ne pas fonctionner correctement avec les contraintes. Il respecte les marges, mais ne calcule pas correctement l'espace disponible. Voici ma mise en page:

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

Cela se traduit comme suit:

entrez la description de l'image ici

J'utilise com.android.support.constraint:constraint-layout:1.0.0-beta4.

Est-ce que je fais quelque chose de mal? Est-ce un bug ou simplement un comportement peu intuitif? Puis-je obtenir le bon comportement en utilisant un ConstraintLayout(je sais que je peux utiliser d'autres mises en page, je pose la question ConstrainLayoutspécifiquement).

Marcin Jedynak
la source
pouvez-vous publier la vue de texte avec sa disposition de contrainte parente? comme vous le savez, les attributs de la disposition des parents ont un grand impact sur l'enfant
Mohammed Atif
Au fait, dans votre cas, je suppose que le biais horizontal est le coupable. essayez de supprimer la disposition de droite à droite et de biais
Mohammed Atif
1
Un biais horizontal est nécessaire, sinon si la bulle est centrée. Sans mise en page à droite, la bonne marge ne sera pas prise en compte, ce qui n'est pas ce que nous voulons. J'ai essayé de les supprimer, comme vous l'avez conseillé, mais cela n'a pas aidé.
Marcin Jedynak
1
le problème est le biais horizontal 0 à coup sûr. Je vais vérifier les solutions possibles et le publier dès que possible car je travaille également avec quelque chose de similaire sur la disposition des contraintes.
Mohammed Atif
1
La bulle de chat @nmu vient de tools:background="@drawable/chat_message_bubble". Pour l'implémenter, vous devez créer le fichier chat_message_bubble.xml dans le dossier drawable puis ajouter ce code: <shape xmlns:android="http://schemas.android.com/apk/res/android"> <solid android:color="#FB4382"/> <corners android:radius="10dip"/> </shape>
Eugene Brusov

Réponses:

242

Obsolète: voir une meilleure réponse

Non, vous ne pouvez pas faire ce que vous voulez avec ConstraintLayout tel qu'il est aujourd'hui (1.0 beta 4):

  • wrap_content demande seulement au widget de se mesurer, mais ne limitera pas son expansion contre d'éventuelles contraintes
  • match_constraints(0DP) va limiter la taille du widget contre les contraintes ... mais les jumellera même si wrap_contentaurait été plus petit (votre premier exemple), ce qui est pas ce que vous voulez soit.

Alors maintenant, vous n'avez pas de chance pour ce cas particulier: - /

Maintenant ... nous pensons ajouter des capacités supplémentaires pour match_constraintsfaire face à ce scénario exact (se comporter comme à wrap_contentmoins que la taille ne soit plus que les contraintes).

Je ne peux cependant pas promettre que cette nouvelle fonctionnalité sera disponible avant la version 1.0.

Edit : nous avons ajouté cette capacité dans 1.0 avec l'attribut app:layout_constraintWidth_default="wrap"(avec une largeur définie à 0dp). S'il est défini, le widget aura la même taille que s'il utilisait wrap_content, mais sera limité par des contraintes (c'est-à-dire qu'il ne s'étendra pas au-delà d'elles)

Mettre à jour Maintenant, ces balises sont obsolètes, utilisez à la place layout_width = "WRAP_CONTENT" et layout_constrainedWidth = "true".

Nicolas Roard
la source
1
C'est un super problème pour moi. Je ne peux pas utiliser TextView avec des drawables composés pour le moment car si je le définis sur match_constraintsle composé, le drawable sera à l'extrême droite, même s'il y a du texte très court.
Paul Woitaschek
2
@NicolasRoard: pouvez-vous m'aider avec la mise en page des contraintes, j'ai une image dans la moitié supérieure avec une ligne directrice de 0,4 et un contenu en dessous, mais lorsque je règle la mise en page des contraintes sur wrap_content, il ne sélectionne que 0,4 de l'écran (et la moitié de la textviews ci-dessous ne sont pas visibles), j'ai utilisé app:layout_constraintWidth_default="wrap"aussi, et v1.0.2 de la bibliothèque mais ça n'aide pas
Rat-a-tat-a-tat Ratatouille
3
app: layout_constraintWidth_default = "wrap" avec une largeur comme 0dp le fait bien!
Tunji_D
11
cela devrait être EXPLICITE dans la documentation / les instructions.
SQLiteNoob
6
L' édition devrait-elle prendre une plus grande importance? Un peu se perd sous l'original. Appréciez la réponse. Merci @NicolasRoard.
Tom Howard
276

Mis à jour (ConstraintLayout 1.1. +)

Utiliser app:layout_constrainedWidth="true"avecandroid:layout_width="wrap_content"

Précédemment (obsolète):

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

Silvia H
la source
5
C'est vrai, depuis ConstraintLayout 1.1.0 beta 2, je crois. androidstudio.googleblog.com/2017/10/…
Fifer Sheep
2
Ceci maintenant dans la version 1.1: medium.com/google-developers/…
Esdras Lopez
adore stackoverflow! merci cela m'a aidé! gardez le contenu enveloppant, mais ne dépassez jamais la contrainte! #TIL
Dennis Anderson le
Quelle réponse, je ne savais pas que cela existait! Merci mec, après 2 heures de jeu avec des alternatives, cela a fonctionné un régal!
dev2505
23

Oui, comme mentionné dans la réponse donnée par Nikolas Roard, vous devez ajouter app:layout_constraintWidth_default="wrap"et définir la largeur à 0dp. Et pour aligner votre bulle à droite, vous devez définir 1.0 pour layout_constraintHorizontal_bias.

Voici le code source final:

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

En conséquence, il ressemble à:

entrez la description de l'image ici

Eugène Brusov
la source
Je pense que c'est parce que OP veut une petite bulle à gauche et la vôtre a raison, ce qui change les exigences
Waza_Be
2
la partie importante ici estapp:layout_constraintHorizontal_bias="1.0"
Lester
9

Comme les autres réponses déjà dites, depuis ConstraintLayout 1.0, il est possible d'y parvenir, mais à partir de la dernière version (1.1.x), ils ont changé la façon dont vous le faites.

Depuis la sortie de ConstraintLayout 1.1, les anciens attributs app:layout_constraintWidth_default="wrap"et sont désormais obsolètes .app:layout_constraintHeight_default="wrap"

Si vous souhaitez fournir un wrap_contentcomportement, tout en appliquant les contraintes sur votre vue, vous devez définir sa largeur et / ou sa hauteur sur wrap_contentcombinées avec les attributs app:layout_constrainedWidth=”true|false”et / ou app:layout_constrainedHeight=”true|false”, comme indiqué dans la documentation :

WRAP_CONTENT: application de contraintes (Ajouté dans 1.1) Si une dimension est définie sur WRAP_CONTENT, dans les versions antérieures à 1.1, elles seront traitées comme une dimension littérale - ce qui signifie que les contraintes ne limiteront pas la dimension résultante. Bien qu'en général cela soit suffisant (et plus rapide), dans certaines situations, vous voudrez peut-être utiliser WRAP_CONTENT, tout en continuant à appliquer des contraintes pour limiter la dimension résultante. Dans ce cas, vous pouvez ajouter l'un des attributs correspondants:

app: layout_constrainedWidth = "true | false" application: layout_constrainedHeight = "true | false"

En ce qui concerne la dernière version, au moment où j'y ai répondu, ConstraintLayout est sur la version 1.1.2 .

Mauker
la source
3

Abandon de l'application: layout_constraintWidth_default text et son alternative

La réponse de @ nicolas-roard app:layout_constraintWidth_default="wrap"et android:layout_width="0dp"est maintenant DÉPRECÉE .

Allez-y et utilisez app:layout_constrainedWidth="true"et android:layout_width="wrap_content".

La raison de la dépréciation, je ne sais pas. Mais c'est juste dans le code source de ConstraintLayout

Bolaji
la source
-7

J'utilise celui-ci

app:layout_constraintEnd_toEndOf="parent"
jsHate
la source
comment cela répond-il à la question de OP? comment cela enveloppe-t-il le contenu?
Alex
-8

Tu devrais remplacer

android:layout_width="wrap_content"

avec

android:layout_width="match_parent"

à partir de votre TextView, puis ajustez le remplissage et la marge en conséquence. J'ai mis à jour votre 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." />

Vous obtiendrez ce résultat entrez la description de l'image ici

Mehul
la source
Vous devez éviter d'utiliser "match_parent" pour toute vue dans un ConstraintLayout. Regardez "Note" ici
Eugene Brusov