Kolejność ograniczeń i modyfikatorów

W interfejsie tworzenia możesz łączyć wiele modyfikatorów, aby zmienić wygląd i styl funkcji kompozycyjnej. Te łańcuchy modyfikatorów mogą wpływać na ograniczenia przekazywane do funkcji kompozycyjnych, które definiują granice szerokości i wysokości.

Na tej stronie opisujemy, jak łańcuchowe modyfikatory wpływają na ograniczenia, a co za tym idzie na pomiar i rozmieszczanie elementów kompozycyjnych.

Modyfikatory w drzewie interfejsu

Aby zrozumieć, jak modyfikatory wpływają na siebie nawzajem, warto zwizualizować ich wygląd w drzewie interfejsu, które jest generowane na etapie kompozycji. Więcej informacji znajdziesz w sekcji Kompozycja.

W drzewie interfejsu możesz wizualizować modyfikatory jako węzły układu dla węzłów układu:

Kod elementów kompozycyjnych i modyfikatorów oraz ich wizualna reprezentacja jako drzewo interfejsu.
Rysunek 1. Modyfikatory zawijające węzły układu w drzewie interfejsu.

Dodanie więcej niż jednego modyfikatora do funkcji kompozycyjnej powoduje utworzenie łańcucha modyfikatorów. Gdy połączysz wiele modyfikatorów, każdy z nich otacza pozostałe elementy łańcucha i węzeł układu. Gdy na przykład dołączasz łańcuch clip i modyfikator size, węzeł modyfikatora clip opakowuje węzeł z modyfikatorem size, który następnie opakowuje węzeł układu Image.

Na etapie układu algorytm poruszający się po drzewie pozostaje taki sam, ale odwiedzany jest też każdy węzeł modyfikatora. W ten sposób modyfikator może zmienić wymagania dotyczące rozmiaru oraz jego umiejscowienie dla modyfikatora lub węzła układu, który uwzględnia.

Jak widać na Rysunku 2, implementacja elementów kompozycyjnych Image i Text składa się z łańcucha modyfikatorów obejmujących 1 węzeł układu. Implementacje Row i Column są po prostu węzłami układu, które opisują sposób rozmieszczenia elementów podrzędnych.

Poprzednia struktura drzewa, a teraz każdy węzeł ma prosty układ z wieloma modyfikatorami otaczającymi go.
Rysunek 2. Ta sama struktura drzewa co na Rysunku 1, ale z elementami kompozycyjnymi w interfejsie przedstawionymi jako łańcuchy modyfikatorów.

Podsumujmy:

  • Modyfikatory zawijają pojedynczy modyfikator lub węzeł układu.
  • Węzły układu mogą obejmować wiele węzłów podrzędnych.

W kolejnych sekcjach opisujemy, jak z tego modelu myślowego myśleć o łańcuchu modyfikatorów i jak wpływa on na rozmiar elementów kompozycyjnych.

Ograniczenia na etapie układu

Etap układu korzysta z 3-etapowego algorytmu, który znajduje szerokość i wysokość węzła układu oraz współrzędne x i y:

  1. Pomiar elementów podrzędnych: węzeł mierzy elementy podrzędne (jeśli występują).
  2. Ustal własny rozmiar: na podstawie tych pomiarów węzeł określa własny rozmiar.
  3. Umieść elementy podrzędne: każdy węzeł podrzędny jest umieszczany względem własnego węzła.

Constraints pomaga znaleźć odpowiednie rozmiary węzłów podczas pierwszych 2 etapów algorytmu. Ograniczenia określają minimalne i maksymalne granice szerokości i wysokości węzła. Gdy węzeł określi swój rozmiar, jego zmierzony rozmiar powinien mieścić się w tym zakresie.

Typy ograniczeń

Możliwe ograniczenia:

  • Ograniczony: węzeł ma maksymalną i minimalną szerokość oraz wysokość.
Ograniczone ograniczenia różnych rozmiarów w kontenerze.
Rysunek 3. Ograniczone ograniczenia.
  • Bez ograniczeń: węzeł nie jest ograniczony do żadnego rozmiaru. Maksymalne progi szerokości i wysokości są ustawione na nieskończoność.
Niepowiązane ograniczenia, których szerokość i wysokość są ustawione na nieskończoność. Ograniczenia wykraczają poza kontener.
Rysunek 4. Niepowiązane ograniczenia.
  • Ścisłe: węzeł jest pytany o wymagania dotyczące dokładnego rozmiaru. Progi minimalne i maksymalne są ustawione na tę samą wartość.
Dokładne ograniczenia, które są zgodne z wymaganiami dotyczącymi dokładnego rozmiaru w kontenerze.
Rysunek 5. Dokładne ograniczenia.
  • Kombinacja: węzeł korzysta z kombinacji powyższych typów ograniczeń. Na przykład ograniczenie może ograniczyć szerokość, zezwalając na nieskończoną maksymalną wysokość, lub określić dokładną szerokość, ale jednocześnie określić wysokość.
2 kontenery, które wyświetlają kombinacje ograniczonych i nieograniczonych ograniczeń oraz dokładnych szerokości i wysokości.
Rysunek 6. Kombinacje ograniczonych i nieograniczonych ograniczeń oraz dokładnych szerokości i wysokości.

W następnej sekcji opisano sposób przekazywania tych ograniczeń z elementu nadrzędnego do jednostki podrzędnej.

W jaki sposób ograniczenia są przekazywane z jednostki nadrzędnej do podrzędnej

W pierwszym kroku algorytmu opisanego na stronie Ograniczenia na etapie układu ograniczenia są przekazywane z elementu nadrzędnego do elementu podrzędnego w drzewie interfejsu.

Gdy węzeł nadrzędny mierzy swoje elementy podrzędne, ogranicza te ograniczenia każdemu z podrzędnych, aby poinformować, jak duży lub mały węzeł może być dozwolony. Następnie, gdy sam określi swój rozmiar, przestrzega również ograniczeń określonych przez rodziców.

Ogólnie algorytm działa w ten sposób:

  1. Aby określić rozmiar, jaki będzie on miał zająć, węzeł główny w drzewie interfejsu mierzy elementy podrzędne i przekazuje te same ograniczenia do swojego pierwszego węzła podrzędnego.
  2. Jeśli element podrzędny jest modyfikatorem, który nie ma wpływu na pomiar, przekierowuje te ograniczenia do następnego modyfikatora. Ograniczenia są przekazywane w łańcuchu modyfikatorów w niezmienionej postaci, chyba że zostanie osiągnięty modyfikator, który wpływa na pomiar. Rozmiar ograniczeń jest następnie odpowiednio zmieniany.
  3. Po dotarciu do węzła niemającego żadnych elementów podrzędnych (nazywanych „węzłem liścia”) określa on jego rozmiar na podstawie przekazanych ograniczeń i zwraca ten rozwiązany rozmiar do elementu nadrzędnego.
  4. Element nadrzędny dostosowuje swoje ograniczenia na podstawie pomiarów tego elementu podrzędnego i wywołuje jego kolejne elementy podrzędne z tymi dostosowanymi ograniczeniami.
  5. Po zmierzeniu wszystkich elementów podrzędnych węzła nadrzędnego określa on swój rozmiar i przekazuje go do własnego węzła nadrzędnego.
  6. W ten sposób przemierzane są najpierw całe drzewo. Ostatecznie wszystkie węzły określiły swoje rozmiary i zakończony jest pomiar.

Szczegółowy przykład znajdziesz w filmie Ograniczenia i kolejność modyfikatorów.

Modyfikatory, które mają wpływ na ograniczenia

W poprzedniej sekcji omówiliśmy, że niektóre modyfikatory mogą wpływać na rozmiar ograniczenia. W sekcjach poniżej opisujemy konkretne modyfikatory, które mają wpływ na ograniczenia.

size modyfikator

Modyfikator size deklaruje preferowany rozmiar treści.

Na przykład to drzewo interfejsu powinno być renderowane w kontenerze 300dp na 200dp. Ograniczenia są ograniczone, co umożliwia szerokości od 100dp do 300dp oraz wysokości od 100dp do 200dp:

Część drzewa interfejsu z modyfikatorem rozmiaru, który opakowuje węzeł układu, i reprezentacja ograniczeń ograniczonych ustawionych przez modyfikator rozmiaru w kontenerze.
Rysunek 7. Ograniczone ograniczenia w drzewie interfejsu i ich reprezentacja w kontenerze.

Modyfikator size dostosowuje ograniczenia przychodzące do przekazywanej wartości. W tym przykładzie wartość to 150dp:

Tak samo jak na Rysunku 7, z wyjątkiem modyfikatora rozmiaru, który dostosowuje ograniczenia przychodzące w celu dopasowania do przekazanej do niej wartości.
Rysunek 8. Modyfikator size dostosowuje ograniczenia do 150dp.

Jeśli szerokość i wysokość są mniejsze niż najmniejsze lub większe niż największa granica ograniczenia, modyfikator jak najwierniej odpowiada przekazywanemu ograniczeniom i jednocześnie zachowuje zgodność z przekazanymi ograniczeniami:

Dwa drzewa interfejsu i odpowiadające im reprezentacje w kontenerach. W pierwszym przypadku modyfikator rozmiaru akceptuje ograniczenia rosnące, a w drugim przypadku możliwie ściśle dostosowuje się do zbyt dużych ograniczeń, co skutkuje ograniczeniami wypełniającymi kontener.
Rysunek 9. Modyfikator size możliwie jak najściślej trzyma się przekazywanego ograniczenia.

Pamiętaj, że łączenie w łańcuch wielu modyfikatorów size nie działa. Pierwszy modyfikator size ustawia zarówno minimalne, jak i maksymalne ograniczenia na stałą wartość. Nawet jeśli drugi modyfikator rozmiaru żąda mniejszego lub większego rozmiaru, musi przestrzegać dokładnych granic przekazanych, więc nie zastępuje tych wartości:

Łańcuch składający się z 2 modyfikatorów rozmiaru w drzewie interfejsu i jego reprezentacja w kontenerze, która jest wynikiem przekazanej pierwszej wartości, a nie drugiej wartości.
Rysunek 10. Łańcuch 2 modyfikatorów size, w którym druga przekazana wartość (50dp) nie zastępuje pierwszej (100dp).

requiredSize modyfikator

Jeśli chcesz, aby węzeł zastąpił przychodzące ograniczenia, zamiast size użyj modyfikatora requiredSize. Modyfikator requiredSize zastępuje przychodzące ograniczenia i przekazuje podany przez Ciebie rozmiar jako dokładne wartości progowe.

Po przesłaniu rozmiaru z powrotem do drzewa węzeł podrzędny zostanie wyśrodkowany w dostępnym miejscu:

Modyfikator rozmiaru i wymagany rozmiar w łańcuchu w drzewie interfejsu oraz odpowiadająca mu reprezentacja w kontenerze. Ograniczenia modyfikatora requiredSize zastępują ograniczenia związane z modyfikatorem rozmiaru.
Rysunek 11. Modyfikator requiredSize zastępuje ograniczenia przychodzące z modyfikatora size.

Modyfikatory width i height

Modyfikator size dostosowuje szerokość i wysokość ograniczeń. Korzystając z modyfikatora width, możesz ustawić stałą szerokość, ale wysokość pozostawić niezdecydowaną. Podobnie dzięki modyfikatorowi height możesz ustawić stałą wysokość, ale pozostawić szerokość nieokreśloną:

Dwa drzewa interfejsu, jedno z modyfikatorem szerokości i reprezentacją kontenera, a drugie z modyfikatorem wysokości i jego reprezentacją.
Rysunek 12. Modyfikator width i modyfikator height ustawiają odpowiednio stałą szerokość i wysokość.

sizeIn modyfikator

Modyfikator sizeIn pozwala ustawić dokładne minimalne i maksymalne ograniczenia szerokości i wysokości. Jeśli potrzebujesz szczegółowej kontroli nad ograniczeniami, użyj modyfikatora sizeIn.

Drzewo interfejsu z modyfikatorem sizeIn z ustawioną minimalną i maksymalną szerokością oraz wysokością oraz jego reprezentacją w kontenerze.
Rysunek 13. Modyfikator sizeIn z ustawionymi parametrami minWidth, maxWidth, minHeight i maxHeight.

Przykłady

W tej sekcji widać i objaśniamy dane wyjściowe z kilku fragmentów kodu z łańcuchami modyfikatorów.

Image(
    painterResource(R.drawable.hero),
    contentDescription = null,
    Modifier
        .fillMaxSize()
        .size(50.dp)
)

Ten fragment kodu wygeneruje następujące dane wyjściowe:

  • Modyfikator fillMaxSize zmienia ograniczenia, ustawiając zarówno minimalną szerokość, jak i wysokość na wartość maksymalną, czyli 300dp szerokości i 200dp wysokości.
  • Mimo że modyfikator size chce użyć rozmiaru 50dp, i tak musi spełniać przychodzące minimalne ograniczenia. Dlatego modyfikator size zwraca też dokładne wartości progowe ograniczenia 300 przez 200, co w efekcie ignoruje wartość podaną w modyfikatorze size.
  • Obiekt Image przekracza te granice i raportuje rozmiar 300 dla 200, który jest przekazywany aż do samego dołu drzewa.

Image(
    painterResource(R.drawable.hero),
    contentDescription = null,
    Modifier
        .fillMaxSize()
        .wrapContentSize()
        .size(50.dp)
)

Ten fragment kodu wygeneruje następujące dane wyjściowe:

  • Modyfikator fillMaxSize dostosowuje ograniczenia tak, aby ustawić minimalną szerokość i wysokość do wartości maksymalnej – szerokości 300dp i 200dp wysokości.
  • Modyfikator wrapContentSize resetuje minimalne ograniczenia. Choć funkcja fillMaxSize spowodowała stałe ograniczenia, wrapContentSize resetuje ją do ograniczonych ograniczeń. Poniższy węzeł może teraz ponownie zająć całą przestrzeń lub być mniejszy.
  • Modyfikator size wyznacza ograniczenia na minimalną i maksymalną wartość 50.
  • Element Image przyjmuje wartość 50 według 50, a modyfikator size przekazuje tę informację do przodu.
  • Modyfikator wrapContentSize ma specjalną właściwość. Wykorzystuje element podrzędny i umieszcza w środku dostępnych minimalnych wartości progowych, które zostały do niego przesłane. Rozmiar, jaki przekazuje z elementami nadrzędnymi, jest więc równy minimalnych progach, które do niej zostały przekazane.

Łącząc tylko 3 modyfikatory, możesz zdefiniować rozmiar elementu kompozycyjnego i wyśrodkować go w jego elemencie nadrzędnym.

Image(
    painterResource(R.drawable.hero),
    contentDescription = null,
    Modifier
        .clip(CircleShape)
        .padding(10.dp)
        .size(100.dp)
)

Ten fragment kodu wygeneruje następujące dane wyjściowe:

  • Modyfikator clip nie zmienia ograniczeń.
    • Modyfikator padding obniża maksymalne ograniczenia.
    • Modyfikator size ustawia wszystkie ograniczenia na 100dp.
    • Element Image jest zgodny z tymi ograniczeniami i zgłasza rozmiar 100 według 100dp.
    • Modyfikator padding dodaje element 10dp we wszystkich rozmiarach, więc zwiększa raportowane dane szerokości i wysokości o 20dp.
    • Na etapie rysowania modyfikator clip działa na obszarze roboczym elementu 120 przez 120dp. Utworzy wtedy maskę kołową o tym rozmiarze.
    • Następnie modyfikator padding wstawia swoją zawartość o 10dp we wszystkich rozmiarach, więc zmniejsza rozmiar obszaru roboczego do 100 o 100dp.
    • Element Image jest narysowany na tym obszarze roboczym. Obraz jest przycinany na podstawie pierwotnego okręgu ustawionego na 120dp, więc wynik nie jest okrągły.