Widok Wrap_content wewnątrz ConstraintLayout rozciąga się poza ekran

140

Próbuję zaimplementować prosty bąbelek czatu przy użyciu pliku ConstraintLayout. Oto, co staram się osiągnąć:

wprowadź opis obrazu tutaj wprowadź opis obrazu tutaj

Jednak wrap_contentwydaje się , że nie działa poprawnie z ograniczeniami. Szanuje marginesy, ale nie oblicza prawidłowo dostępnej przestrzeni. Oto mój układ:

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

To renderuje się następująco:

wprowadź opis obrazu tutaj

Używam com.android.support.constraint:constraint-layout:1.0.0-beta4.

czy robię coś źle? Czy to błąd, czy tylko nieintuicyjne zachowanie? Czy mogę osiągnąć właściwe zachowanie za pomocą ConstraintLayout(wiem, że potrafię używać innych układów, o które ConstrainLayoutdokładnie pytam ).

Marcin Jedynak
źródło
czy możesz opublikować widok tekstu wraz z jego macierzystym układem ograniczającym? jak wiecie, atrybuty układu rodzica mają ogromny wpływ na dziecko
Mohammed Atif
Nawiasem mówiąc, w twoim przypadku winowajcą jest nastawienie poziome. spróbuj usunąć layout na prawo od i bias
Mohammed Atif
1
Konieczne jest odchylenie poziome, w przeciwnym razie, jeśli bańka jest wyśrodkowana. Bez układu prawa do prawej, prawy margines nie będzie brany pod uwagę, co nie jest tym, czego chcemy. Próbowałem je usunąć, tak jak radziłeś, ale to nie pomogło.
Marcin Jedynak
1
problemem jest na pewno odchylenie poziome 0. Sprawdzę możliwe rozwiązania i opublikuję je jak najszybciej, ponieważ pracuję również z czymś podobnym w zakresie układu ograniczeń.
Mohammed Atif
1
Bańka czatu @nmu pochodzi z tools:background="@drawable/chat_message_bubble". Aby go zaimplementować, musisz utworzyć plik chat_message_bubble.xml w folderze do rysowania, a następnie dodać ten kod: <shape xmlns:android="http://schemas.android.com/apk/res/android"> <solid android:color="#FB4382"/> <corners android:radius="10dip"/> </shape>
Eugene Brusov

Odpowiedzi:

252

Nieaktualne: zobacz lepszą odpowiedź

Nie, nie możesz robić tego, co chcesz z ConstraintLayout w obecnej postaci (1.0 beta 4):

  • wrap_content prosi jedynie widżet o dokonanie pomiaru samego siebie, ale nie ogranicza jego rozwinięcia w przypadku ewentualnych ograniczeń
  • match_constraints(0DP) będzie ograniczyć rozmiar widgetu przeciwko ograniczeniom ... ale nawet jeśli będzie je dopasować wrap_contentbyłby mniejszy (Twój pierwszy przykład), który jest nie to, co chcesz, albo.

Więc teraz nie masz szczęścia w tym konkretnym przypadku: - /

Teraz ... myślimy o dodaniu dodatkowych możliwości, aby match_constraintsporadzić sobie z tym konkretnym scenariuszem (zachowując się tak, jakby wrap_contentrozmiar nie był większy niż ograniczenia).

Nie mogę jednak obiecać, że ta nowa funkcja będzie działać przed wydaniem 1.0.

Edycja : dodaliśmy tę możliwość w wersji 1.0 z atrybutem app:layout_constraintWidth_default="wrap"(z szerokością ustawioną na 0dp). Jeśli ustawione, widżet będzie miał taki sam rozmiar, jak przy użyciu wrap_content, ale będzie ograniczony przez ograniczenia (tj. Nie będzie się rozszerzał poza nie)

Aktualizacja Teraz te tagi są przestarzałe, zamiast tego użyj layout_width = "WRAP_CONTENT" i layout_constrainedWidth = "true".

Nicolas Roard
źródło
1
To dla mnie super problem. Nie mogę teraz używać TextView ze złożonymi obiektami rysunkowymi, ponieważ jeśli ustawię go match_constraintsna złożony, możliwy do rysowania będzie po prawej stronie, nawet jeśli jest bardzo krótki tekst.
Paul Woitaschek
2
@NicolasRoard: czy u pls mogą mi pomóc z układem ograniczeń, mam obraz w górnej połowie z wytyczną 0,4 i zawartością poniżej, ale kiedy ustawię układ ograniczeń na wrap_content, wybiera tylko 0,4 ekranu (i połowę podglądy tekstu poniżej nie są widoczne), ja app:layout_constraintWidth_default="wrap"też użyłem i v1.0.2 biblioteki, ale to nie pomaga
Rat-a-tat-a-tat Ratatouille
3
app: layout_constraintWidth_default = "zawiń" z szerokością równą 0dp ładnie to robi!
Tunji_D
11
powinno to być JASNE w dokumentacji / instrukcjach.
SQLiteNoob
6
Czy Edycja powinna mieć większe znaczenie? Trochę gubi się pod oryginałem. Doceń odpowiedź. Dzięki @NicolasRoard.
Tom Howard,
301

Zaktualizowano (ConstraintLayout 1.1. +)

Używaj app:layout_constrainedWidth="true"zandroid:layout_width="wrap_content"

Wcześniej (przestarzałe):

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

Silvia H.
źródło
6
To prawda, uważam, że od ConstraintLayout 1.1.0 beta 2. androidstudio.googleblog.com/2017/10/…
Fifer Sheep
2
To teraz w wersji 1.1: medium.com/google-developers/…
Esdras Lopez
kocham stackoverflow! dzięki, to pomogło mi! zachowaj zawartość opakowania, ale nigdy nie wykraczaj poza ograniczenia! #TIL
Dennis Anderson
Co za odpowiedź, nie wiedziałem, że to istnieje! Dzięki człowiekowi, po 2 godzinach zabawy z alternatywami to zadziałało!
dev2505
25

Tak, jak wspomniałem w odpowiedzi udzielonej przez Nikolasa Roarda , należy dodać app:layout_constraintWidth_default="wrap"i ustawić szerokość na 0dp. Aby ustawić bąbelek w prawo, należy ustawić wartość 1,0 dla layout_constraintHorizontal_bias.

Oto ostateczny kod źródłowy:

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

W efekcie wygląda to tak:

wprowadź opis obrazu tutaj

Eugene Brusov
źródło
Myślę, że to dlatego, że OP chce małej bańki po lewej stronie, a twoja ma rację, co zmienia wymagania
Waza_Be
2
ważna część tutajapp:layout_constraintHorizontal_bias="1.0"
Lester,
9

Podobnie jak inne odpowiedzi już powiedziane, od ConstraintLayout 1.0 jest to możliwe, ale od najnowszej wersji (1.1.x) zmienili sposób, w jaki to robisz.

Od wydania ConstraintLayout 1.1 stare atrybuty app:layout_constraintWidth_default="wrap"i są obecnie przestarzałe .app:layout_constraintHeight_default="wrap"

Jeśli chcesz zapewnić wrap_contentzachowanie, ale nadal egzekwować ograniczenia w swoim Widoku, powinieneś ustawić jego szerokość i / lub wysokość na wrap_contentpołączenie z atrybutami app:layout_constrainedWidth=”true|false”i / lub app:layout_constrainedHeight=”true|false”, jak podano w dokumentach :

WRAP_CONTENT: wymuszanie ograniczeń (dodane w 1.1) Jeśli wymiar jest ustawiony na WRAP_CONTENT, w wersjach wcześniejszych niż 1.1 będą traktowane jako wymiar dosłowny - co oznacza, że ​​ograniczenia nie będą ograniczały wymiaru wynikowego. Chociaż ogólnie jest to wystarczające (i szybsze), w niektórych sytuacjach możesz chcieć użyć WRAP_CONTENT, ale nadal wymuszaj ograniczenia, aby ograniczyć wynikowy wymiar. W takim przypadku możesz dodać jeden z odpowiednich atrybutów:

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

Jeśli chodzi o najnowszą wersję, zanim odpowiem na to pytanie, ConstraintLayout jest w wersji 1.1.2 .

Mauker
źródło
3

Wycofanie app: layout_constraintWidth_default text i jego alternatywa

@ nicolas-roard odpowiada app:layout_constraintWidth_default="wrap"i android:layout_width="0dp"jest teraz WYCOFANE .

Śmiało i użyj app:layout_constrainedWidth="true"i android:layout_width="wrap_content".

Nie wiem, powód wycofania. Ale ma rację w kodzie źródłowym ConstraintLayout

Bolaji
źródło
-7

Używam tego

app:layout_constraintEnd_toEndOf="parent"
jsHate
źródło
jak to odpowiada na pytanie OP? jak to zawija zawartość?
Alex
-8

Powinieneś wymienić

android:layout_width="wrap_content"

z

android:layout_width="match_parent"

z TextView, a następnie odpowiednio dostosuj dopełnienie i marginesy. Zaktualizowałem Twój kod,

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

Otrzymasz ten wynik wprowadź opis obrazu tutaj

Mehul
źródło
Należy unikać używania „match_parent” dla dowolnego widoku w ConstraintLayout. Spójrz na "Notatkę" tutaj
Eugene Brusov