In Compose können Sie mehrere Modifier verketten, um das Erscheinungsbild eines Composables zu ändern. Diese Modifiziererketten können sich auf die Einschränkungen auswirken, die an Composables übergeben werden und die Breiten- und Höhenbegrenzungen definieren.
Auf dieser Seite wird beschrieben, wie sich verkettete Modifizierer auf Einschränkungen und damit auf die Messung und Platzierung von Composables auswirken.
Modifikatoren im UI-Baum
Um zu verstehen, wie sich Modifikatoren gegenseitig beeinflussen, ist es hilfreich, sich anzusehen, wie sie im UI-Baum dargestellt werden, der während der Kompositionsphase generiert wird. Weitere Informationen finden Sie im Abschnitt Zusammensetzung.
Im UI-Baum können Sie Modifizierer als Wrapper-Knoten für die Layoutknoten visualisieren:
Wenn Sie einem Composable mehrere Modifikatoren hinzufügen, entsteht eine Kette von Modifikatoren. Wenn Sie mehrere Modifikatoren verketten, umschließt jeder Modifikator-Knoten den Rest der Kette und den Layoutknoten. Wenn Sie beispielsweise einen clip- und einen size-Modifikator verketten, umschließt der clip-Modifikator-Knoten den size-Modifikator-Knoten, der wiederum den Image-Layoutknoten umschließt.
In der Layoutphase bleibt der Algorithmus, der den Baum durchläuft, gleich, aber jeder Modifikator-Knoten wird ebenfalls besucht. So kann ein Modifikator die Größenanforderungen und die Platzierung des Modifikators oder des Layoutknotens ändern, den er umschließt.
Wie in Abbildung 2 zu sehen ist, besteht die Implementierung der Composables Image und Text selbst aus einer Kette von Modifikatoren, die einen einzelnen Layoutknoten umschließen.
Die Implementierungen von Row und Column sind Layoutknoten, die beschreiben, wie ihre untergeordneten Elemente angeordnet werden sollen.
Zusammenfassend lässt sich sagen:
- Modifikatoren umschließen einen einzelnen Modifikator oder Layoutknoten.
- Layoutknoten können mehrere untergeordnete Knoten anordnen.
In den folgenden Abschnitten wird beschrieben, wie Sie dieses mentale Modell verwenden können, um über die Verkettung von Modifikatoren nachzudenken und wie sie sich auf die Größe von Composables auswirkt.
Einschränkungen in der Layoutphase
In der Layoutphase wird ein dreistufiger Algorithmus verwendet, um die Breite, Höhe und x- und y-Koordinaten jedes Layoutknotens zu ermitteln:
- Kinder messen: Ein Knoten misst seine untergeordneten Elemente, sofern vorhanden.
- Eigene Größe festlegen: Anhand dieser Messungen legt ein Knoten seine eigene Größe fest.
- Untergeordnete Elemente platzieren: Jeder untergeordnete Knoten wird relativ zur Position eines Knotens platziert.
Constraints helfen dabei, in den ersten beiden Schritten des Algorithmus die richtigen Größen für die Knoten zu finden. Mit Einschränkungen werden die minimalen und maximalen Grenzen für die Breite und Höhe eines Knotens definiert. Wenn der Knoten seine Größe bestimmt, sollte die gemessene Größe in diesen Größenbereich fallen.
Arten von Einschränkungen
Eine Einschränkung kann Folgendes sein:
- Begrenzt: Der Knoten hat eine maximale und eine minimale Breite und Höhe.
- Unbegrenzt: Die Größe des Knotens ist nicht begrenzt. Die maximalen Breiten- und Höhenbegrenzungen sind auf unendlich festgelegt.
- Genau: Der Knoten wird aufgefordert, eine genaue Größenanforderung zu erfüllen. Die Mindest- und Höchstgrenzen sind auf denselben Wert festgelegt.
- Kombination: Der Knoten folgt einer Kombination der oben genannten Einschränkungstypen. Eine Einschränkung könnte beispielsweise die Breite begrenzen, während eine unbegrenzte maximale Höhe zulässig ist, oder eine genaue Breite festlegen, aber eine begrenzte Höhe vorsehen.
Im nächsten Abschnitt wird beschrieben, wie diese Einschränkungen von einem übergeordneten an ein untergeordnetes Element übergeben werden.
So werden Einschränkungen von übergeordneten an untergeordnete Elemente weitergegeben
Im ersten Schritt des im Abschnitt Einschränkungen in der Layoutphase beschriebenen Algorithmus werden Einschränkungen im UI-Baum von übergeordneten zu untergeordneten Elementen weitergegeben.
Wenn ein übergeordneter Knoten seine untergeordneten Knoten rendert, gibt er diese Einschränkungen an jeden untergeordneten Knoten weiter, um ihm mitzuteilen, wie groß oder klein er sein darf. Wenn es dann seine eigene Größe festlegt, hält es sich auch an die Einschränkungen, die von seinen eigenen Eltern übergeben wurden.
Auf übergeordneter Ebene funktioniert der Algorithmus so:
- Um die Größe zu bestimmen, die sie tatsächlich einnehmen soll, misst der Stammknoten im UI-Baum seine untergeordneten Elemente und leitet dieselben Einschränkungen an sein erstes untergeordnetes Element weiter.
- Wenn das untergeordnete Element ein Modifikator ist, der sich nicht auf die Messung auswirkt, werden die Einschränkungen an den nächsten Modifikator weitergeleitet. Die Einschränkungen werden unverändert in der Modifikatorfolge weitergegeben, bis ein Modifikator erreicht wird, der sich auf die Analyse auswirkt. Die Einschränkungen werden dann entsprechend angepasst.
- Sobald ein Knoten erreicht wird, der keine untergeordneten Elemente hat (als „Blattknoten“ bezeichnet), wird seine Größe anhand der übergebenen Einschränkungen festgelegt und an das übergeordnete Element zurückgegeben.
- Das übergeordnete Element passt seine Einschränkungen basierend auf den Messungen dieses untergeordneten Elements an und ruft das nächste untergeordnete Element mit diesen angepassten Einschränkungen auf.
- Sobald alle untergeordneten Elemente eines übergeordneten Elements gemessen wurden, bestimmt das übergeordnete Element seine eigene Größe und teilt sie seinem übergeordneten Element mit.
- Auf diese Weise wird der gesamte Baum in der Tiefe durchlaufen. Schließlich haben alle Knoten ihre Größen festgelegt und der Messschritt ist abgeschlossen.
Ein ausführliches Beispiel finden Sie im Video Constraints and modifier order.
Modifikatoren, die sich auf Einschränkungen auswirken
Im vorherigen Abschnitt haben Sie erfahren, dass sich einige Modifikatoren auf die Größe von Einschränkungen auswirken können. In den folgenden Abschnitten werden bestimmte Modifikatoren beschrieben, die sich auf Einschränkungen auswirken.
Der size-Modifikator
Mit dem Modifikator size wird die bevorzugte Größe des Inhalts deklariert.
Der folgende UI-Baum sollte beispielsweise in einem Container mit 300dp × 200dp gerendert werden. Die Einschränkungen sind begrenzt. Die Breite darf zwischen 100dp und 300dp liegen, die Höhe zwischen 100dp und 200dp:
Mit dem Modifikator size werden eingehende Einschränkungen so angepasst, dass sie dem übergebenen Wert entsprechen.
In diesem Beispiel ist der Wert 150dp:
size-Modifikator, mit dem Einschränkungen an 150dp angepasst werden.Wenn die Breite und Höhe kleiner als die kleinste oder größer als die größte Einschränkungsgrenze sind, entspricht der Modifikator den übergebenen Einschränkungen so genau wie möglich, während er die übergebenen Einschränkungen weiterhin einhält:
size-Modifikator, der die übergebene Einschränkung so genau wie möglich einhält.Das Verketten mehrerer size-Modifikatoren funktioniert nicht. Mit dem ersten size-Modifikator werden sowohl die Mindest- als auch die Höchstbeschränkung auf einen festen Wert festgelegt. Auch wenn mit dem zweiten Größenmodifikator eine kleinere oder größere Größe angefordert wird, muss er sich an die übergebenen genauen Grenzen halten. Er überschreibt diese Werte also nicht:
size-Modifikatoren, in der der zweite übergebene Wert (50dp) den ersten Wert (100dp) nicht überschreibt.Der requiredSize-Modifikator
Verwenden Sie den Modifikator requiredSize anstelle von size, wenn Ihr Knoten die eingehenden Einschränkungen überschreiben soll. Mit dem Modifikator requiredSize werden die eingehenden Einschränkungen ersetzt und die von Ihnen angegebene Größe als genaue Grenzen übergeben.
Wenn die Größe im Baum nach oben weitergegeben wird, wird der untergeordnete Knoten im verfügbaren Bereich zentriert:
requiredSize-Modifikator überschreibt eingehende Einschränkungen des size-Modifikators.Die Modifikatoren width und height
Mit dem Modifizierer size werden sowohl die Breite als auch die Höhe der Einschränkungen angepasst. Mit dem Modifikator width können Sie eine feste Breite festlegen, die Höhe jedoch offen lassen.
Mit dem Modifikator height können Sie eine feste Höhe festlegen, die Breite jedoch offen lassen:
width wird eine feste Breite und mit dem Modifizierer height eine feste Höhe festgelegt.Der sizeIn-Modifikator
Mit dem Modifikator sizeIn können Sie genaue Mindest- und Höchstwerte für Breite und Höhe festlegen. Verwenden Sie den Modifikator sizeIn, wenn Sie die Einschränkungen genau steuern möchten.
sizeIn mit minWidth, maxWidth, minHeight und maxHeight ist festgelegt.Beispiele
In diesem Abschnitt wird die Ausgabe von mehreren Code-Snippets mit verketteten Modifizierern gezeigt und erläutert.
Image( painterResource(R.drawable.hero), contentDescription = null, Modifier .fillMaxSize() .size(50.dp) )
Dieses Snippet erzeugt die folgende Ausgabe:
Image füllt die maximale Größe als Ergebnis der Modifier-Kette.- Mit dem Modifikator
fillMaxSizewerden die Einschränkungen so geändert, dass sowohl die Mindestbreite als auch die Mindesthöhe auf den Maximalwert festgelegt werden:300dpfür die Breite und200dpfür die Höhe. - Auch wenn mit dem Modifier
sizeeine Größe von50dpverwendet werden soll, müssen die eingehenden Mindestanforderungen eingehalten werden. Der Modifikatorsizegibt also auch die genauen Einschränkungsgrenzen von300nach200aus. Der im Modifikatorsizeangegebene Wert wird effektiv ignoriert. - Das
Imagefolgt diesen Grenzen und meldet eine Größe von300×200, die bis zum Stamm des Baums weitergegeben wird.
Image( painterResource(R.drawable.hero), contentDescription = null, Modifier .fillMaxSize() .wrapContentSize() .size(50.dp) )
Dieses Snippet erzeugt die folgende Ausgabe:
Image ist zentriert und hat die Größe 50dp.- Mit dem Modifikator
fillMaxSizewerden die Einschränkungen so angepasst, dass sowohl die Mindestbreite als auch die Mindesthöhe auf den Maximalwert festgelegt werden:300dpin der Breite und200dpin der Höhe. - Mit dem Modifikator
wrapContentSizewerden die Mindestanforderungen zurückgesetzt. WährendfillMaxSizezu festen Einschränkungen führte,wrapContentSizesetzt sie wieder auf begrenzte Einschränkungen zurück. Der folgende Knoten kann jetzt wieder den gesamten Bereich einnehmen oder kleiner als der gesamte Bereich sein. - Mit dem Modifikator
sizewerden die Beschränkungen auf die Mindest- und Höchstgrenzen von50festgelegt. Imagewird in eine Größe von50×50aufgelöst und der Modifikatorsizeleitet dies weiter.- Der Modifikator
wrapContentSizehat eine besondere Eigenschaft. Das untergeordnete Element wird in der Mitte der verfügbaren Mindestgrenzen platziert, die an das Element übergeben wurden. Die Größe, die an die übergeordneten Elemente übergeben wird, entspricht also den minimalen Grenzen, die an das untergeordnete Element übergeben wurden.
Durch die Kombination von nur drei Modifikatoren können Sie eine Größe für das Composable definieren und es im übergeordneten Element zentrieren.
Image( painterResource(R.drawable.hero), contentDescription = null, Modifier .clip(CircleShape) .padding(10.dp) .size(100.dp) )
Dieses Snippet erzeugt die folgende Ausgabe:
- Der Modifikator
clipändert die Einschränkungen nicht. - Der Modifikator
paddingsenkt die maximalen Einschränkungen. - Mit dem Modifikator
sizewerden alle Einschränkungen auf100dpfestgelegt. - Das
Imageentspricht diesen Einschränkungen und hat eine Größe von100dp×100dp. - Mit dem Modifizierer
paddingwird der Größe, die vonImagegemeldet wird, auf allen Seiten10dphinzugefügt. Das Layout mit Padding meldet also eine Breite und Höhe von120dp. - In der Zeichenphase wirkt sich der
clip-Modifikator auf eine Leinwand von120dp×120dpaus. Dadurch wird eine kreisförmige Maske mit dieser Größe erstellt. - Der Modifizierer
paddingsetzt den Inhalt dann auf allen Seiten um10dpein, wodurch die Canvas-Größe für dasImageauf100dp×100dpreduziert wird. - Die
Imagewird auf dieser kleineren Leinwand gezeichnet. Das Bild wird basierend auf dem ursprünglichen Kreis von120dpbeschnitten, sodass das Ergebnis nicht rund ist.