Kolejność ograniczeń i modyfikatorów

W sekcji „Tworzenie” możesz łączyć ze sobą wiele modyfikatorów, aby zmieniać wygląd i wygląd komponentu. Te łańcuchy modyfikatorów mogą wpływać na ograniczenia przekazywane do komponentów, które definiują granice szerokości i wysokości.

Na tej stronie wyjaśniamy, jak zmodyfikowane modyfikatory wpływają na ograniczenia, a w konsekwencji na pomiar i umiejscowienie komponentów.

Modyfikatory w drzewie interfejsu użytkownika

Aby zrozumieć, jak modyfikatory wpływają na siebie nawzajem, warto zwizualizować, jak są one wyświetlane w drzewie interfejsu użytkownika, które jest generowane w trakcie fazy tworzenia. Więcej informacji znajdziesz w sekcji Kompozycja.

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

Kod dla komponentów i modyfikatorów oraz ich wizualizacja w postaci drzewa interfejsu.
Rysunek 1. Modyfikatory otaczające węzły układu w drzewie interfejsu użytkownika.

Dodanie więcej niż jednego modyfikatora do kompozytowanego tworzy łańcuch modyfikatorów. Gdy połączysz ze sobą wiele modyfikatorów, każdy z nich obejmuje pozostałą część łańcucha oraz węzeł układu. Jeśli na przykład połączysz modyfikator clip z modyfikatorem size, węzeł modyfikatora clip spowoduje oznaczenie węzła modyfikatora size, który z kolei spowoduje oznaczenie węzła układu Image.

W fazie układu algorytm przechodzący po drzewie pozostaje taki sam, ale odwiedza też każdy węzeł modyfikatora. Dzięki temu modyfikator może zmienić wymagania dotyczące rozmiaru i umieszczenie modyfikatora lub węzła układu, który otacza.

Jak widać na rysunku 2, implementacja komponentów ImageText składa się z łańcucha modyfikatorów otaczających pojedynczy węzeł układu. Implementacje RowColumn to po prostu węzły układu, które opisują sposób rozmieszczania elementów podrzędnych.

Struktura drzewa z wcześniej, ale teraz każdy węzeł to tylko prosty układ z wiele modyfikatorami otaczającymi go.
Rysunek 2. Ta sama struktura drzewa jak na rysunku 1, ale z elementami kompozytowymi w drzewie interfejsu użytkownika wizualizowanymi jako ciągi modyfikatorów.

Podsumowując:

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

W kolejnych sekcjach opisujemy, jak za pomocą tego modelu mentalnego analizować łańcuchy modyfikatorów i jak wpływają one na rozmiar elementów składanych.

Ograniczenia na etapie układu

Etap układu polega na znalezieniu szerokości, wysokości i współrzędnych x, y każdego węzła układu za pomocą algorytmu składającego się z 3 etapów:

  1. Pomiar podrzędnych: węzeł mierzy swoje podrzędne, jeśli takie istnieją.
  2. Decide own size (określ własny rozmiar): na podstawie tych pomiarów węzeł określa swój rozmiar.
  3. Umieszczanie podrzędnych węzłów: każdy podrzędny węzeł jest umieszczany względem pozycji węzła.

Constraints pomagają znaleźć odpowiednie rozmiary węzłów w pierwszych 2 krokach algorytmu. Ograniczenia określają minimalne i maksymalne wartości szerokości i wysokości węzła. Gdy węzeł określa swój rozmiar, zmierzony rozmiar powinien mieścić się w tym zakresie.

Typy ograniczeń

Ograniczenie może być jednym z tych elementów:

  • Ograniczony: węzeł ma maksymalną i minimalną szerokość oraz wysokość.
Ograniczenia w ramach kontenera o różnych rozmiarach.
Rysunek 3. Ograniczenia z zakresem działania.
  • Bez ograniczeń: węzeł nie jest ograniczony żadnym rozmiarem. Maksymalne wartości szerokości i wysokości są ustawione na nieskończoność.
ograniczenia bez ograniczeń, w których szerokość i wysokość mają wartość nieskończoność; Ograniczenia wykraczają poza kontener.
Rysunek 4. Ograniczenia bez ograniczeń.
  • Dokładne: węzeł musi spełniać dokładne wymagania dotyczące rozmiaru. Minimalne i maksymalne wartości mają tę samą wartość.
Dokładne ograniczenia, które odpowiadają dokładnemu wymaganiu dotyczącemu rozmiaru w kontenerze.
Rysunek 5. Ograniczenia dokładne.
  • Kombinacja: węzeł stosuje kombinację wymienionych powyżej typów ograniczeń. Na przykład ograniczenie może określać szerokość, ale nie ograniczać maksymalnej wysokości, lub określać dokładną szerokość, ale nie wysokość.
Dwa kontenery, które pokazują kombinacje ograniczonych i nieograniczonych ograniczeń oraz dokładne wartości szerokości i wysokości.
Rysunek 6. Kombinacje ograniczonych i nieograniczonych ograniczeń oraz dokładnych szerokości i wysokości.

W następnej sekcji opisujemy, jak te ograniczenia są przekazywane z elementu nadrzędnego do podrzędnego.

Jak ograniczenia są przekazywane z elementu nadrzędnego do podrzędnego

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

Gdy węzeł nadrzędny mierzy swoje węzły podrzędne, przekazuje te ograniczenia do każdego węzła podrzędnego, aby wiedział, jak duży lub mały może być. Następnie, gdy określa swój rozmiar, musi też przestrzegać ograniczeń przekazanych przez swoich nadrzędnych.

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

  1. Aby określić rozmiar, który chce zająć, węzeł główny w drzewie interfejsu użytkownika mierzy swoje elementy podrzędne i przekazuje te same ograniczenia do pierwszego elementu podrzędnego.
  2. Jeśli element podrzędny jest modyfikatorem, który nie wpływa na pomiar, przekazuje ograniczenia do następnego modyfikatora. Ograniczenia są przekazywane w łańcuchu modyfikatorów bez zmian, chyba że zostanie osiągnięty modyfikator, który wpływa na pomiar. Następnie odpowiednio zmieniane są rozmiary ograniczeń.
  3. Gdy zostanie osiągnięty węzeł, który nie ma żadnych węzłów podrzędnych (nazywany „węzłem końcowym”), określa on swój rozmiar na podstawie podanych ograniczeń i zwraca ten rozmiar do węzła nadrzędnego.
  4. Element nadrzędny dostosowuje swoje ograniczenia na podstawie pomiarów podrzędnego i wywołuje następny element podrzędny z tymi dostosowanymi ograniczeniami.
  5. Gdy wszystkie elementy podrzędne zostaną zmierzone, węzeł nadrzędny określa swój rozmiar i przekazuje go swojemu rodzicowi.
  6. W ten sposób całe drzewo jest przeszukiwane metodą głębokresową. Ostatecznie wszystkie węzły określają swoje rozmiary i kończy się etap pomiaru.

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

Modyfikatory wpływające na ograniczenia

Z poprzedniej sekcji wiesz już, że niektóre modyfikatory mogą wpływać na rozmiar ograniczeń. W następnych sekcjach opisujemy konkretne modyfikatory, które wpływają na ograniczenia.

modyfikator size,

Modyfikator size określa preferowany rozmiar treści.

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

Część drzewa interfejsu z modyfikatorem rozmiaru otaczającym węzeł układu oraz przedstawieniem ograniczeń ustawionych przez modyfikator rozmiaru w kontenerze.
Rysunek 7. Ograniczone ograniczenia w drzewie interfejsu użytkownika i jego reprezentacja w kontenerze.

Modyfikator size dostosowuje docierające ograniczenia do wartości, która została mu przekazana. W tym przykładzie wartość to 150dp:

To samo co na rysunku 7, ale z modyfikatorem rozmiaru dostosowującym docierające ograniczenia do wartości przekazanej mu przez modyfikator.
Rysunek 8. Modyfikator size dostosowuje ograniczenia do wartości 150dp.

Jeśli szerokość i wysokość są mniejsze od najmniejszego ograniczenia lub większe od największego ograniczenia, modyfikator dopasowuje się do podanych ograniczeń w jak największym stopniu, zachowując jednocześnie ograniczenia podane w ramach:

Dwa drzewa interfejsu użytkownika i ich odpowiedniki w kontenerach. W pierwszym przypadku modyfikator rozmiaru akceptuje ograniczenia wejściowe, a w drugim dostosowuje się do ograniczeń zbyt dużych w jak największym stopniu, co powoduje, że ograniczenia wypełniają kontener.
Rysunek 9. Modyfikator size, który jak najdokładniej przestrzega przekazanego ograniczenia.

Pamiętaj, że łączenie 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 zażąda mniejszego lub większego rozmiaru, musi on nadal mieścić się w dokładnych granicach, więc nie zastąpi tych wartości:

Łańcuch dwóch modyfikatorów rozmiaru w drzewie interfejsu użytkownika i jego reprezentacja w kontenerze, która jest wynikiem przekazanej pierwszej wartości, a nie drugiej.
Rysunek 10. Łańcuch 2 modyfikatorów size, w którym druga wartość przekazana (50dp) nie zastępuje pierwszej wartości (100dp).

modyfikator requiredSize,

Jeśli chcesz, aby twój węzeł zastąpił docierające ograniczenia, użyj modyfikatora requiredSize zamiast size. Modyfikator requiredSize zastępuje docierające ograniczenia i przekazuje podany przez Ciebie rozmiar jako dokładne granice.

Gdy rozmiar zostanie przekazany z powrotem do drzewa, węzeł podrzędny zostanie wyśrodkowany w dostępnej przestrzeni:

Modyfikator size i requiredSize połączone w drzewie interfejsu użytkownika oraz odpowiadająca im reprezentacja w kontenerze. Ograniczenia modyfikatora requiredSize zastępują ograniczenia modyfikatora size.
Rysunek 11. Modyfikator requiredSize zastępuje ograniczenia przychodzące z modyfikatora size.

modyfikatory widthheight,

Modyfikator size dostosowuje zarówno szerokość, jak i wysokość ograniczeń. Za pomocą modyfikatora width możesz ustawić stałą szerokość, ale pozostawić nieokreśloną wysokość. Podobnie za pomocą modyfikatora height możesz ustawić stałą wysokość, ale pozostawić szerokość nieokreśloną:

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

modyfikator sizeIn,

Modyfikator sizeIn umożliwia ustawienie dokładnych ograniczeń minimalnych i maksymalnych dla szerokości i wysokości. Jeśli chcesz mieć szczegółową kontrolę nad ograniczeniami, użyj modyfikatora sizeIn.

drzewo interfejsu użytkownika z modyfikatorem sizeIn z ustawionymi minimalną i maksymalną szerokością oraz wysokością, a także jego reprezentacją w kontenerze;
Rysunek 13. Modyfikator sizeIn z ustawionymi wartościami minWidth, maxWidth, minHeightmaxHeight.

Przykłady

Ta sekcja pokazuje i wyjaśnia dane wyjściowe z kilku fragmentów kodu z łańcuchowymi modyfikatorami.

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

Ten fragment kodu powoduje wyświetlenie tych danych wyjściowych:

  • Modyfikator fillMaxSize zmienia ograniczenia, aby ustawić minimalną szerokość i wysokość na maksymalną wartość – 300dp w szerokości i 200dp – w wysokości.
  • Mimo że modyfikator size chce użyć rozmiaru 50dp, musi on nadal przestrzegać minimalnych ograniczeń wejściowych. Dlatego modyfikator size będzie też zwracać dokładne granice ograniczenia 300 przez 200, ignorując przy tym wartość podawaną w modyfikatorze size.
  • Element Image podąża za tymi granicami i podaje rozmiar 300 według 200, który jest przekazywany w górę po drzewie.

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

Ten fragment kodu powoduje wyświetlenie tych danych wyjściowych:

  • Modyfikator fillMaxSize dostosowuje ograniczenia, aby ustawić minimalną szerokość i wysokość do maksymalnej wartości – 300dp w przypadku szerokości i 200dp w przypadku wysokości.
  • Modyfikator wrapContentSize zeruje ograniczenia minimalne. Chociaż fillMaxSize spowodowało ograniczenie, wrapContentSize przywraca je do ograniczeń. Następny węzeł może znowu zajmować całą przestrzeń lub być mniejszy niż cała przestrzeń.
  • Modyfikator size ustawia minimalne i maksymalne wartości parametru 50.
  • Wartość Image jest przekształcana na rozmiar 50 przez 50, a modyfikator size przekazuje tę wartość dalej.
  • Modyfikator wrapContentSize ma specjalną właściwość. Zabiera ono swoje dziecko i umieszcza je w środku dostępnych minimalnych granic, które zostały mu przekazane. Rozmiar, który jest przekazywany do elementów nadrzędnych, jest więc równy minimalnym granicom, które zostały mu przekazane.

Łącząc tylko 3 modyfikatory, możesz zdefiniować rozmiar kompozytu i wyśrodkować go w rodzicu.

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

Ten fragment kodu powoduje wyświetlenie tych danych wyjściowych:

  • Modyfikator clip nie zmienia ograniczeń.
    • Modyfikator padding zmniejsza maksymalne ograniczenia.
    • Modyfikator size ustawia wszystkie ograniczenia na 100dp.
    • Funkcja Image przestrzega tych ograniczeń i podaje rozmiar 100 w ramach 100dp.
    • Modyfikator padding dodaje 10dp do wszystkich rozmiarów, co zwiększa zgłaszaną szerokość i wysokość o 20dp.
    • W fazie rysowania modyfikator clip działa na płótnie o wymiarach 120 przez 120dp. W tym celu tworzy maskę koła o takim rozmiarze.
    • Modyfikator padding wstawia następnie zawartość o wartość 10dp we wszystkich rozmiarach, przez co zmniejsza rozmiar płótna do 100 o wartość 100dp.
    • Na tym obszarze roboczym jest narysowany element Image. Obraz jest przycięty na podstawie oryginalnego koła o promieniu 120dp, więc wynik nie jest okrągły.