A exibição Wrap_content dentro de um ConstraintLayout se estende para fora da tela

132

Estou tentando implementar um simples balão de bate-papo usando um ConstraintLayout. Isto é o que estou tentando alcançar:

insira a descrição da imagem aqui insira a descrição da imagem aqui

No entanto, wrap_contentparece não funcionar corretamente com restrições. Ele respeita as margens, mas não calcula o espaço disponível corretamente. Aqui está o meu 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>

Isso renderiza da seguinte maneira:

insira a descrição da imagem aqui

Eu estou usando com.android.support.constraint:constraint-layout:1.0.0-beta4.

Estou fazendo algo errado? É um bug ou apenas um comportamento não intuitivo? Posso obter o comportamento adequado usando a ConstraintLayout(sei que posso usar outros layouts, estou perguntando ConstrainLayoutespecificamente).

Marcin Jedynak
fonte
você pode postar a exibição de texto junto com seu layout de restrição pai? como você sabe, atributos da disposição dos pais tem grande impacto na criança
Mohammed Atif
A propósito, no seu caso, acho que o viés horizontal é o culpado. tente remover layoutright à direita e viés #
Mohammed Atif
1
A polarização horizontal é necessária, caso contrário, se a bolha estiver centralizada. Sem o layout da direita para a direita, a margem certa não será levada em consideração, o que não é o que queremos. Tentei removê-los, como você recomendou, mas não ajudou.
Marcin Jedynak
1
problema é o viés horizontal 0, com certeza. Vou verificar as possíveis soluções e publicá-lo o mais rápido possível, pois também estou trabalhando com algo semelhante no layout de restrições.
Mohammed Atif 29/11
1
O balão de bate-papo @nmu vem tools:background="@drawable/chat_message_bubble". Para implementá-lo, você deve criar o arquivo chat_message_bubble.xml na pasta drawable e adicionar este código: <shape xmlns:android="http://schemas.android.com/apk/res/android"> <solid android:color="#FB4382"/> <corners android:radius="10dip"/> </shape>
Eugene Brusov

Respostas:

242

Desatualizado: veja melhor resposta

Não, você não pode fazer o que deseja com o ConstraintLayout como é hoje (1.0 beta 4):

  • wrap_content solicita apenas que o widget se avalie, mas não limitará sua expansão a eventuais restrições
  • match_constraints(0dp) vai limitar o tamanho do widget contra as restrições ... mas irá combiná-los, mesmo que wrap_contentteria sido menor (seu primeiro exemplo), o que não é o que você quer, quer.

Então, agora, você está sem sorte nesse caso em particular: - /

Agora ... estamos pensando em adicionar recursos extras match_constraintspara lidar com esse cenário exato (comportando-se como a wrap_contentmenos que o tamanho termine sendo mais do que as restrições).

Não posso prometer que esse novo recurso o fará antes do lançamento da versão 1.0.

Editar : adicionamos esse recurso na app:layout_constraintWidth_default="wrap"versão 1.0 com o atributo (com largura definida como 0dp). Se definido, o widget terá o mesmo tamanho que o wrap_content, mas será limitado por restrições (ou seja, não será expandido além delas)

Atualizar Agora essas tags estão obsoletas. Em vez disso, use layout_width = "WRAP_CONTENT" e layout_constrainedWidth = "true".

Nicolas Roard
fonte
1
Isso é um super problema para mim. Não posso usar o TextView com drawables compostos agora, porque se eu o definir como match_constraintsdrawable composto estará à direita, mesmo se houver texto muito curto.
Paul Woitaschek
2
@ NicolasRoard: os upls podem me ajudar com o layout de restrição, eu tenho uma imagem na metade superior com uma diretriz de 0,4 e o conteúdo abaixo, mas quando defino o layout de restrição como wrap_content, ele seleciona apenas 0,4 da tela (e metade do TextViews abaixo não são visíveis), eu usei app:layout_constraintWidth_default="wrap"também, e v1.0.2 da biblioteca mas não ajuda
Rat-a-tat-a-tat Ratatouille
3
app: layout_constraintWidth_default = "wrap" com largura, pois 0dp faz isso muito bem!
precisa saber é o seguinte
11
isso deve ser EXPLÍCITO na documentação / instruções.
SQLiteNoob
6
O Edit deve mudar para ter maior destaque? Meio que se perde embaixo do original. Aprecie a resposta. Obrigado @NicolasRoard.
Tom Howard
276

Atualizado (ConstraintLayout 1.1. +)

Use app:layout_constrainedWidth="true"comandroid:layout_width="wrap_content"

Anteriormente (descontinuado):

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

Silvia H
fonte
5
É verdade, desde o ConstraintLayout 1.1.0 beta 2, acredito. androidstudio.googleblog.com/2017/10/…
Fifer Sheep
2
Isso agora na versão 1.1: medium.com/google-developers/…
Esdras Lopez
amor stackoverflow! graças isso me ajudou! mantenha o conteúdo da embalagem, mas nunca vá além da restrição! #TIL
Dennis Anderson
Que resposta, não sabia que isso existia! Obrigado, cara, depois de 2 horas brincando com alternativas, isso funcionou muito bem!
dev2505 14/03
23

Sim, como mencionado na resposta dada por Nikolas Roard, você deve adicionar app:layout_constraintWidth_default="wrap"e definir a largura como 0dp. E para alinhar sua bolha corretamente, defina 1.0 para layout_constraintHorizontal_bias.

Aqui está o código fonte 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>

Como resultado, parece com:

insira a descrição da imagem aqui

Eugene Brusov
fonte
Eu acho que é porque OP quer pequena bolha na esquerda eo seu é certo, o que muda requisitos
Waza_Be
2
parte importante aqui éapp:layout_constraintHorizontal_bias="1.0"
Lester
9

Como as outras respostas já mencionadas, desde o ConstraintLayout 1.0 é possível conseguir isso, mas a partir da versão mais recente (1.1.x) elas mudaram a maneira como você faz isso.

Desde o lançamento do ConstraintLayout 1.1, os atributos antigo app:layout_constraintWidth_default="wrap"e agora estão obsoletos .app:layout_constraintHeight_default="wrap"

Se você deseja fornecer um wrap_contentcomportamento, mas ainda aplicar as restrições em sua Visualização, defina sua largura e / ou altura para wrap_contentcombinadas com os atributos app:layout_constrainedWidth=”true|false”e / ou app:layout_constrainedHeight=”true|false”, conforme indicado nos documentos :

WRAP_CONTENT: aplicando restrições (adicionado em 1.1) Se uma dimensão for definida como WRAP_CONTENT, nas versões anteriores à 1.1 elas serão tratadas como uma dimensão literal - ou seja, as restrições não limitarão a dimensão resultante. Embora em geral isso seja suficiente (e mais rápido), em algumas situações, convém usar WRAP_CONTENT, mas imponha restrições para limitar a dimensão resultante. Nesse caso, você pode adicionar um dos atributos correspondentes:

app: layout_constrainedWidth = ”true | false” app: layout_constrainedHeight = ”true | false”

Quanto à versão mais recente, no momento em que eu respondo isso, o ConstraintLayout está na versão 1.1.2 .

Mauker
fonte
3

Descontinuação do aplicativo: texto de layout_constraintWidth_default e sua alternativa

A resposta de @ nicolas-roard app:layout_constraintWidth_default="wrap"e android:layout_width="0dp"agora é DEPRECADA .

Vá em frente e use app:layout_constrainedWidth="true"e android:layout_width="wrap_content".

O motivo da depreciação, eu não sei. Mas está certo no código fonte do ConstraintLayout

Bolaji
fonte
-7

Eu uso esse

app:layout_constraintEnd_toEndOf="parent"
jsHate
fonte
como isso e a pergunta do OP? como isso envolve o conteúdo?
Alex
-8

Você deve substituir

android:layout_width="wrap_content"

com

android:layout_width="match_parent"

do TextView e ajuste o preenchimento e a margem de acordo. Eu atualizei seu código,

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

Você obterá este resultado insira a descrição da imagem aqui

Mehul
fonte
Você deve evitar o uso de "match_parent" para qualquer exibição em um ConstraintLayout. Veja "Note" aqui
Eugene Brusov 04/10