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ż jednego modyfikatora powoduje utworzenie łańcucha modyfikatorów. Gdy połączysz ze sobą wiele modyfikatorów, każdy węzeł modyfikatora 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 otoczy węzeł modyfikatora size, który z kolei otoczy 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 zmieniać wymagania dotyczące rozmiaru i umiejscowienia modyfikatora lub węzła układu, który otacza.
Jak pokazano na rysunku 2, implementacja funkcji kompozycyjnych Image i Text składa się z łańcucha modyfikatorów otaczających pojedynczy węzeł układu.
Implementacje Row i Column to węzły układu, które opisują sposób rozmieszczenia elementów podrzędnych.
Podsumowując:
- Modyfikatory otaczają pojedynczy modyfikator lub węzeł układu.
- Węzły układu mogą rozmieszczać wiele węzłów podrzędnych.
W sekcjach poniżej opisujemy, jak używać tego modelu myślowego do wnioskowania o połączeniu modyfikatorów i jak wpływa ono na rozmiar funkcji kompozycyjnych.
Ograniczenia w fazie układu
Faza układu obejmuje algorytm składający się z 3 kroków, który pozwala znaleźć szerokość, wysokość oraz współrzędne x i 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ą.
- Określanie własnego rozmiaru: na podstawie tych pomiarów węzeł określa własny rozmiar.
- Umieszczanie elementów podrzędnych: każdy węzeł podrzędny jest umieszczany względem własnej pozycji węzła.
Constraints pomagają znaleźć odpowiednie rozmiary węzłów w pierwszych 2 krokach algorytmu. Ograniczenia określają minimalną i maksymalną szerokość oraz wysokość węzła. Gdy węzeł określi swój rozmiar, jego zmierzony rozmiar powinien mieścić się w tym zakresie.
Rodzaje 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 określać dokładną szerokość, ale zapewniać ograniczoną wysokość.
W następnej sekcji opisujemy, jak te ograniczenia są przekazywane z elementu nadrzędnego do elementu podrzędnego.
Jak ograniczenia są przekazywane z elementu nadrzędnego do 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 do każdego 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 jego 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 węzeł nie ma węzłów podrzędnych (nazywa się go „węzłem liściowym”), określa 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 pomiarów elementu podrzędnego i wywołuje kolejny element podrzędny z tymi dostosowanymi ograniczeniami.
- Gdy wszystkie elementy podrzędne elementu nadrzędnego zostaną zmierzone, element nadrzędny określa swój rozmiar i przekazuje tę informację do swojego elementu nadrzędnego.
- W ten sposób całe drzewo jest przeszukiwane w głąb. W końcu wszystkie węzły ustalą swoje rozmiary i etap pomiaru zostanie zakończony.
Szczegółowy przykład znajdziesz w filmie Constraints and modifier order (Ograniczenia i kolejność modyfikatorów).
Modyfikatory, które wpływają 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 wartości, która jest do niego przekazywana.
W tym przykładzie wartość to 150dp:
size dostosowuje ograniczenia do 150dp.Jeśli szerokość i wysokość są mniejsze niż najmniejsze ograniczenie lub większe niż największe ograniczenie, modyfikator dopasowuje przekazane ograniczenia tak ściśle, jak to możliwe, przy jednoczesnym zachowaniu przekazanych ograniczeń:
size Modyfikator, który w jak największym stopniu dostosowuje się do przekazanego ograniczenia.Pamiętaj, że łączenie kilku 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, nadal musi się on trzymać przekazanych dokładnych granic, więc nie zastąpi tych wartości:
size, w którym druga przekazana wartość (50dp) nie zastępuje pierwszej wartości (100dp).Modyfikator requiredSize
Jeśli chcesz, aby węzeł zastępował przychodzące ograniczenia, użyj modyfikatora requiredSize zamiast size. Modyfikator requiredSize zastępuje przychodzące ograniczenia i przekazuje określony rozmiar jako dokładne granice.
Gdy rozmiar zostanie przekazany z powrotem w górę drzewa, węzeł podrzędny zostanie wyśrodkowany w dostępnej przestrzeni:
requiredSize zastępuje przychodzące ograniczenia 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 znajdziesz dane wyjściowe z kilku fragmentów kodu z połączonymi modyfikatorami oraz ich wyjaśnienie.
Image( painterResource(R.drawable.hero), contentDescription = null, Modifier .fillMaxSize() .size(50.dp) )
Ten fragment kodu generuje te dane wyjściowe:
Image osiąga maksymalny rozmiar w wyniku działania łańcucha modyfikatorów.- Modyfikator
fillMaxSizezmienia ograniczenia, aby ustawić zarówno minimalną szerokość, jak i wysokość na wartość maksymalną –300dpw przypadku szerokości i200dpw przypadku wysokości. - Mimo że modyfikator
sizechce użyć rozmiaru50dp, musi nadal przestrzegać przychodzących ograniczeń minimalnych. Modyfikatorsizezwróci też dokładne granice ograniczeń300na200, co spowoduje zignorowanie wartości podanej w modyfikatorzesize. - Element
Imagejest zgodny z tymi granicami i zgłasza rozmiar300×200, 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. Dlatego, gdyfillMaxSizespowoduje ustalenie stałych ograniczeń,wrapContentSizeprzywróci ograniczenia określone. Węzeł może teraz ponownie zajmować całą przestrzeń lub być mniejszy od niej. - Modyfikator
sizeustawia ograniczenia na minimalne i maksymalne granice50. Imagema rozmiar50×50, a modyfikatorsizeprzekazuje ten rozmiar dalej.- Modyfikator
wrapContentSizema specjalną właściwość. Pobiera element podrzędny i umieszcza go na środku dostępnych minimalnych granic, które zostały mu przekazane. Rozmiar, który przekazuje elementowi nadrzędnemu, jest więc równy minimalnym granicom, które zostały mu przekazane.
Łącząc tylko 3 modyfikatory, możesz określić rozmiar funkcji kompozycyjnej i wyśrodkować ją w jej 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
paddingobniża maksymalne ograniczenia. - Modyfikator
sizeustawia wszystkie ograniczenia na100dp. Imagespełnia te ograniczenia i podaje rozmiar100dp×100dp.- Modyfikator
paddingdodaje10dpze wszystkich stron do rozmiaru podanego przezImage, więc układ z dopełnieniem zgłasza szerokość i wysokość równe120dp. - Teraz w fazie rysowania modyfikator
clipdziała na obszarze o wymiarach120dp×120dp. Utworzy maskę w kształcie koła o takim rozmiarze. - Modyfikator
paddingwstawia następnie treść o wartość10dpze wszystkich stron, co zmniejsza rozmiar obszaru roboczego dla elementuImagedo100dpo wartość100dp. Imagejest rysowany na mniejszym obszarze. Obraz jest przycinany na podstawie pierwotnego okręgu120dp, więc wynik nie jest okrągły.