W Compose możesz łączyć ze sobą wiele modyfikatorów, aby zmieniać wygląd i styl funkcji kompozycyjnych. Te łańcuchy modyfikatorów mogą wpływać na ograniczenia przekazywane do funkcji kompozycyjnych, które określają granice szerokości i wysokości.
Na tej stronie opisujemy, jak połączone modyfikatory wpływają na ograniczenia, a w konsekwencji na pomiar i umieszczanie funkcji kompozycyjnych.
Modyfikatory w drzewie iUI
Aby zrozumieć, jak modyfikatory wpływają na siebie nawzajem, warto wyobrazić sobie, jak wyglądają w drzewie UI, które jest generowane w fazie kompozycji. Więcej informacji znajdziesz w sekcji Kompozycja.
W drzewie UI możesz wizualizować modyfikatory jako węzły opakowujące węzły układu:
Dodanie do funkcji kompozycyjnej więcej niż 1 modyfikatora tworzy łańcuch modyfikatorów. Gdy połączysz ze sobą kilka modyfikatorów, każdy węzeł modyfikatora będzie otaczać pozostałą część łańcucha i węzeł układu. Jeśli na przykład połączysz modyfikatory clip i size, węzeł modyfikatora clip będzie zawierać węzeł modyfikatora size, który z kolei będzie zawierać węzeł układu Image.
W fazie układu algorytm, który przechodzi przez drzewo, pozostaje taki sam, ale odwiedzany jest też każdy węzeł modyfikatora. W ten sposób modyfikator może zmienić wymagania dotyczące rozmiaru i umiejscowienia modyfikatora lub węzła układu, który otacza.
Jak widać na rysunku 2, implementacja funkcji kompozycyjnych Image i Text składa się z łańcucha modyfikatorów, które opakowują pojedynczy węzeł układu.
Implementacje Row i Column to węzły układu, które opisują, jak rozmieścić elementy podrzędne.
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 sekcjach poniżej opisujemy, jak używać tego modelu mentalnego do analizowania łańcucha modyfikatorów i jego wpływu na rozmiar funkcji kompozycyjnych.
Ograniczenia na etapie układu
Faza układu wykorzystuje 3-etapowy algorytm, aby znaleźć szerokość, wysokość i współrzędne x, y każdego węzła układu:
- Mierzenie elementów podrzędnych: węzeł mierzy swoje węzły podrzędne, jeśli takie istnieją.
- Decydowanie o własnym rozmiarze: na podstawie tych pomiarów węzeł decyduje o własnym rozmiarze.
- Umieszczanie elementów podrzędnych: każdy węzeł podrzędny jest umieszczany względem pozycji węzła.
Constraints pomagają znaleźć odpowiednie rozmiary węzłów podczas pierwszych 2 kroków algorytmu. Ograniczenia określają minimalne i maksymalne granice 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 należeć do jednej z tych kategorii:
- Określone: węzeł ma maksymalną i minimalną szerokość oraz wysokość.
- Nieokreślone: węzeł nie jest ograniczony żadnym rozmiarem. Maksymalna szerokość i wysokość są ustawione na nieskończoność.
- Dokładne: węzeł ma spełnić dokładne wymagania dotyczące rozmiaru. Minimalne i maksymalne granice mają tę samą wartość.
- Kombinacja: węzeł jest zgodny z kombinacją poprzednich typów ograniczeń. Na przykład ograniczenie może określać szerokość, ale pozwalać na nieograniczoną maksymalną wysokość, lub ustawiać dokładną szerokość, ale określać wysokość.
W następnej sekcji opisano, jak te ograniczenia są przekazywane z elementu nadrzędnego do elementu podrzędnego.
Jak ograniczenia są przekazywane z elementu nadrzędnego do elementu podrzędnego
W pierwszym kroku algorytmu opisanego w sekcji Ograniczenia w fazie układu ograniczenia są przekazywane z elementu nadrzędnego do podrzędnego w drzewie UI.
Gdy węzeł nadrzędny mierzy swoje węzły podrzędne, przekazuje te ograniczenia każdemu z nich, aby poinformować je, jak duże lub małe mogą być. Następnie, gdy określa swój rozmiar, przestrzega też ograniczeń przekazanych przez elementy nadrzędne.
Ogólnie algorytm działa w ten sposób:
- Aby określić rozmiar, który ma zajmować, węzeł główny w drzewie UI mierzy swoje elementy podrzędne i przekazuje te same ograniczenia do pierwszego elementu podrzędnego.
- Jeśli element podrzędny jest modyfikatorem, który nie ma wpływu na pomiar, przekazuje 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 ma wpływ na pomiary. Ograniczenia są następnie odpowiednio zmieniane.
- Gdy zostanie osiągnięty węzeł, który nie ma żadnych węzłów podrzędnych (nazywany „węzłem liścia”), określa on swój rozmiar na podstawie przekazanych ograniczeń i zwraca ten rozmiar do węzła nadrzędnego.
- Element nadrzędny dostosowuje swoje ograniczenia na podstawie wymiarów tego elementu podrzędnego i wywołuje następny element podrzędny z tymi dostosowanymi ograniczeniami.
- Po zmierzeniu wszystkich elementów podrzędnych węzeł nadrzędny określa swój rozmiar i przekazuje go do swojego węzła nadrzędnego.
- W ten sposób całe drzewo jest przeszukiwane w głąb. W końcu wszystkie węzły określą swoje rozmiary i etap pomiaru zostanie zakończony.
Szczegółowy przykład znajdziesz w filmie Ograniczenia i kolejność modyfikatorów.
Modyfikatory wpływające na ograniczenia
W poprzedniej sekcji dowiedzieliśmy się, że niektóre modyfikatory mogą wpływać na rozmiar ograniczenia. W sekcjach poniżej opisujemy konkretne modyfikatory, które wpływają na ograniczenia.
Modyfikator size
Modyfikator size deklaruje preferowany rozmiar treści.
Na przykład to drzewo UI powinno być renderowane w kontenerze 300dp
przez 200dp. Ograniczenia są okreśłone, co pozwala na szerokość od 100dp do 300dp i wysokość od 100dp do 200dp:
Modyfikator size dostosowuje przychodzące ograniczenia do przekazanej wartości.
W tym przykładzie wartość to 150dp:
size dostosowuje ograniczenia do 150dp.Jeśli szerokość i wysokość są mniejsze niż najmniejsza granica ograniczenia lub większe niż największa granica ograniczenia, modyfikator dopasowuje przekazane ograniczenia tak dokładnie, jak to możliwe, zachowując przy tym ograniczenia przekazane w:
size, który w jak największym stopniu 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 żąda mniejszego lub większego rozmiaru, nadal musi przestrzegać przekazanych dokładnych granic, więc nie zastąpi tych wartości:
size, w którym druga przekazana wartość (50dp) nie zastępuje pierwszej (100dp).Modyfikator requiredSize
Jeśli chcesz, aby węzeł zastępował ograniczenia przychodzące, użyj modyfikatora requiredSize zamiast size. Modyfikator requiredSize zastępuje przychodzące ograniczenia i przekazuje określony przez Ciebie rozmiar jako dokładne granice.
Gdy rozmiar zostanie przekazany w górę drzewa, węzeł podrzędny zostanie wyśrodkowany w dostępnej przestrzeni:
requiredSize zastępuje ograniczenia przychodzące z modyfikatora size.Modyfikatory width i height
Modyfikator size dostosowuje zarówno szerokość, jak i wysokość ograniczeń. Za pomocą modyfikatora width możesz ustawić stałą szerokość, ale pozostawić wysokość nieokreśloną.
Podobnie za pomocą modyfikatora height możesz ustawić stałą wysokość, ale pozostawić szerokość nieokreśloną:
width i modyfikator height ustawiają odpowiednio stałą szerokość i wysokość.Modyfikator sizeIn
Modyfikator sizeIn umożliwia ustawienie dokładnych minimalnych i maksymalnych ograniczeń szerokości i wysokości. Jeśli potrzebujesz precyzyjnej kontroli nad ograniczeniami, użyj modyfikatora sizeIn.
sizeIn z ustawionymi wartościami minWidth, maxWidth, minHeight i maxHeight.Przykłady
W tej sekcji pokazujemy i objaśniamy dane wyjściowe kilku fragmentów kodu z modyfikatorami połączonymi w łańcuch.
Image( painterResource(R.drawable.hero), contentDescription = null, Modifier .fillMaxSize() .size(50.dp) )
Ten fragment kodu generuje te dane wyjściowe:
Image wypełnia maksymalny rozmiar w wyniku działania łańcucha modyfikatorów.- Modyfikator
fillMaxSizezmienia ograniczenia, aby ustawić zarówno minimalną szerokość, jak i wysokość na maksymalną wartość –300dpszerokości i200dpwysokości. - Mimo że modyfikator
sizechce użyć rozmiaru50dp, musi przestrzegać przychodzących ograniczeń minimalnych. Dlatego modyfikatorsizerównież zwróci dokładne granice ograniczeń300na200, skutecznie ignorując wartość podaną w modyfikatorzesize. Imageprzestrzega tych ograniczeń i zgłasza rozmiar300na200, który jest przekazywany w górę drzewa.
Image( painterResource(R.drawable.hero), contentDescription = null, Modifier .fillMaxSize() .wrapContentSize() .size(50.dp) )
Ten fragment kodu generuje te dane wyjściowe:
Image jest wyśrodkowany i ma rozmiar 50dp.- Modyfikator
fillMaxSizedostosowuje ograniczenia, aby ustawić zarówno minimalną szerokość, jak i wysokość na wartość maksymalną –300dpw przypadku szerokości i200dpw przypadku wysokości. - Modyfikator
wrapContentSizeresetuje minimalne ograniczenia. Tak więc, podczas gdyfillMaxSizespowodowało stałe ograniczenia,wrapContentSizeprzywraca je do ograniczeń określonych. Kolejny węzeł może teraz ponownie zajmować całą przestrzeń lub być mniejszy niż cała przestrzeń. - Modyfikator
sizeustawia ograniczenia na minimalne i maksymalne granice50. Imageprzyjmuje rozmiar50na50, a modyfikatorsizeprzekazuje go dalej.- Modyfikator
wrapContentSizema specjalną właściwość. Pobiera element podrzędny i umieszcza go w środku dostępnych minimalnych granic, które zostały mu przekazane. Rozmiar, który przekazuje do elementów nadrzędnych, jest więc równy minimalnym granicom, które zostały do niego przekazane.
Łącząc tylko 3 modyfikatory, możesz określić rozmiar funkcji kompozycyjnej i wyśrodkować ją w elemencie nadrzędnym.
Image( painterResource(R.drawable.hero), contentDescription = null, Modifier .clip(CircleShape) .padding(10.dp) .size(100.dp) )
Ten fragment kodu generuje te dane wyjściowe:
- Modyfikator
clipnie zmienia ograniczeń. - Modyfikator
paddingzmniejsza maksymalne ograniczenia. - Modyfikator
sizeustawia wszystkie ograniczenia na100dp. Imageprzestrzega tych ograniczeń i zgłasza rozmiar100dpna100dp.- Modyfikator
paddingdodaje10dpze wszystkich stron do rozmiaru zgłoszonego przezImage, więc układ z dopełnieniem zgłasza szerokość i wysokość120dp. - Teraz, na etapie rysowania, modyfikator
clipdziała na obszarze roboczym o wymiarach120dpna120dp. Spowoduje to utworzenie okrągłej maski o tym rozmiarze. - Modyfikator
paddingwstawia następnie zawartość z dopełnieniem10dpze wszystkich stron, co zmniejsza rozmiar obszaru roboczego dlaImagedo100dpna100dp. Imagejest rysowany na mniejszym obszarze roboczym. Obraz jest przycinany na podstawie pierwotnego okręgu o średnicy120dp, więc wynik nie jest okrągły.