Einschränkungen und Modifikatorreihenfolge

In Compose können Sie mehrere Modifikatoren miteinander verketten, um das Erscheinungsbild einer zusammensetzbaren Funktion zu ändern. Diese Modifikatorketten können die Einschränkungen beeinflussen, die an zusammensetzbare Funktionen übergeben werden und die Grenzen für Breite und Höhe definieren.

Auf dieser Seite wird beschrieben, wie verkettete Modifikatoren Einschränkungen und damit die Messung und Platzierung von zusammensetzbaren Funktionen beeinflussen.

Modifikatoren in der Struktur der Benutzeroberfläche

Damit Sie nachvollziehen können, wie sich Modifikatoren gegenseitig beeinflussen, sollten Sie sich ansehen, wie sie in der UI-Struktur angezeigt werden, die während der Erstellungsphase generiert wird. Weitere Informationen findest du im Abschnitt Komposition.

In der UI-Struktur können Sie Modifikatoren als Wrapper-Knoten für die Layoutknoten visualisieren:

Code für zusammensetzbare Funktionen und Modifikatoren sowie deren visuelle Darstellung als UI-Baum
Abbildung 1. Modifikatoren, die Layoutknoten in der Baumstruktur der Benutzeroberfläche zusammenfassen.

Wenn Sie einer zusammensetzbaren Funktion mehr als einen Modifikator hinzufügen, entsteht eine Kette von Modifikatoren. Wenn Sie mehrere Modifikatoren verketten, umschließt jeder Modifikatorknoten den Rest der Kette und den Layoutknoten darin. Wenn Sie beispielsweise einen clip- und einen size-Modifikator verketten, umschließt der clip-Modifikatorknoten den size-Modifikatorknoten, der dann den Image-Layoutknoten umschließt.

In der Layoutphase bleibt der Algorithmus, der den Baum durchsucht, gleich, aber jeder Modifikatorknoten wird ebenfalls besucht. Auf diese Weise kann ein Modifikator die Größenanforderungen und die Platzierung des Modifikator- oder Layoutknotens ändern, den er umschließt.

Wie in Abbildung 2 gezeigt, besteht die Implementierung der zusammensetzbaren Funktionen Image und Text selbst aus einer Kette von Modifikatoren, die einen einzelnen Layoutknoten umschließen. Die Implementierungen von Row und Column sind einfache Layoutknoten, die beschreiben, wie ihre untergeordneten Elemente angeordnet werden.

Die Baumstruktur von vorher, aber jetzt ist jeder Knoten nur ein einfaches Layout mit vielen Modifikator-Wrapping-Knoten darum.
Abbildung 2: Dieselbe Baumstruktur wie in Abbildung 1, aber mit den zusammensetzbaren Funktionen im UI-Baum, dargestellt als Ketten von Modifikatoren.

Zusammenfassung:

  • Modifikatoren schließen einen einzelnen Modifikator oder Layoutknoten ein.
  • Layoutknoten können aus mehreren untergeordneten Knoten bestehen.

In den folgenden Abschnitten wird beschrieben, wie Sie mit diesem mentalen Modell die Modifikatorverkettung beurteilen und die Größe von zusammensetzbaren Funktionen beeinflussen.

Einschränkungen in der Layoutphase

Die Layoutphase folgt einem dreistufigen Algorithmus, um die Breite, Höhe und x- und y-Koordinaten jedes Layoutknotens zu ermitteln:

  1. Untergeordnete Elemente messen: Ein Knoten misst seine untergeordneten Elemente, falls vorhanden.
  2. Eigene Größe festlegen: Ein Knoten entscheidet anhand dieser Messungen über seine eigene Größe.
  3. Untergeordnete Knoten platzieren: Jeder untergeordnete Knoten wird relativ zur eigenen Position des Knotens platziert.

Constraints helfen Ihnen, in den ersten beiden Schritten des Algorithmus die richtigen Größen für die Knoten zu finden. Einschränkungen definieren die Mindest- und Höchstgrenzen für die Breite und Höhe eines Knotens. Wenn der Knoten über seine Größe entscheidet, sollte seine 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.
Begrenzte Einschränkungen verschiedener Größen innerhalb eines Containers.
Abbildung 3. Begrenzte Einschränkungen.
  • Unbegrenzt: Der Knoten ist auf keine Größe beschränkt. Die Grenzen für die maximale Breite und Höhe sind auf unendlich festgelegt.
Unbegrenzte Einschränkungen, bei denen die Breite und Höhe auf unendlich gesetzt ist. Die Einschränkungen gehen über den Container hinaus.
Abbildung 4. Unbegrenzte Einschränkungen.
  • Exakt: Der Knoten muss eine genaue Größenanforderung erfüllen. Die Mindest- und Höchstgrenzen sind auf denselben Wert festgelegt.
Genaue Einschränkungen, die einer genauen Größenanforderung innerhalb des Containers entsprechen.
Abbildung 5. Exakte Einschränkungen.
  • Kombination: Der Knoten folgt einer Kombination der oben genannten Einschränkungstypen. Eine Einschränkung könnte beispielsweise die Breite begrenzen und gleichzeitig eine unbegrenzte maximale Höhe zulassen oder eine genaue Breite festlegen, aber eine begrenzte Höhe angeben.
Zwei Container, die Kombinationen aus begrenzten und unbegrenzten Einschränkungen sowie exakter Breite und Höhe anzeigen.
Abbildung 6. Kombinationen von begrenzten und unbegrenzten Einschränkungen sowie exakter Breite und Höhe.

Im nächsten Abschnitt wird beschrieben, wie diese Einschränkungen von einem übergeordneten Element an ein untergeordnetes Element übergeben werden.

So werden Einschränkungen von übergeordneten und untergeordneten Elementen übergeben

Im ersten Schritt des unter Einschränkungen in der Layoutphase beschriebenen Algorithmus werden Einschränkungen im UI-Baum vom übergeordneten zum untergeordneten Element übergeben.

Wenn ein übergeordneter Knoten seine untergeordneten Knoten misst, stellt er diese Einschränkungen für jedes untergeordnete Element bereit, um es darüber zu informieren, wie groß oder klein sie sein dürfen. Wenn es dann seine eigene Größe entscheidet, hält es auch die Einschränkungen ein, die von seinen eigenen übergeordneten Elementen übergeben wurden.

Auf übergeordneter Ebene funktioniert der Algorithmus so:

  1. Um zu entscheiden, welche Größe er tatsächlich belegen möchte, misst der Stammknoten im UI-Baum seine untergeordneten Elemente und leitet dieselben Einschränkungen an das erste untergeordnete Element weiter.
  2. 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 an die Modifikatorkette übergeben, es sei denn, ein Modifikator, der sich auf die Messung auswirkt, wird erreicht. Die Größe der Einschränkungen wird dann entsprechend angepasst.
  3. Wenn ein Knoten erreicht ist, der keine untergeordneten Knoten hat (als „Blattknoten“ bezeichnet), wird seine Größe anhand der übergebenen Einschränkungen festgelegt und diese aufgelöste Größe an das übergeordnete Element zurückgegeben.
  4. 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.
  5. Sobald alle untergeordneten Elemente eines übergeordneten Knotens gemessen wurden, entscheidet der übergeordnete Knoten über seine eigene Größe und sendet dies an sein eigenes übergeordnetes Element.
  6. Auf diese Weise wird der gesamte Baum zuerst tief durchquert. Schließlich haben sich alle Knoten über ihre Größe entschieden und der Schritt zur Messung ist abgeschlossen.

Ein detailliertes Beispiel finden Sie im Video Einschränkungen und Modifikatorreihenfolge.

Modifikatoren, die Einschränkungen beeinflussen

Im vorherigen Abschnitt haben Sie gelernt, dass sich einige Modifikatoren auf die Größe der Einschränkung auswirken können. In den folgenden Abschnitten werden bestimmte Modifikatoren beschrieben, die sich auf Einschränkungen auswirken.

size-Modifikator

Der size-Modifikator gibt die bevorzugte Größe des Inhalts an.

Die folgende UI-Struktur sollte beispielsweise in einem Container mit 300dp von 200dp gerendert werden. Die Einschränkungen sind begrenzt, sodass Breiten zwischen 100dp und 300dp und Höhen zwischen 100dp und 200dp möglich sind:

Ein Teil einer UI-Struktur, in dem der Größenmodifikator einen Layoutknoten einschließt und die durch den Größenmodifikator in einem Container festgelegten begrenzten Einschränkungen dargestellt sind.
Abbildung 7. Begrenzte Einschränkungen im UI-Baum und dessen Darstellung in einem Container

Der size-Modifikator passt eingehende Einschränkungen an den an ihn übergebenen Wert an. In diesem Beispiel ist der Wert 150dp:

Wie in Abbildung 7 dargestellt, mit dem Unterschied, dass der Größenmodifikator eingehende Einschränkungen an den übergebenen Wert anpasst.
Abbildung 8. Der size-Modifikator zum Anpassen der Beschränkungen auf 150dp.

Wenn Breite und Höhe kleiner als die kleinste Einschränkung oder größer als die größte Einschränkungsgrenze sind, entspricht der Modifikator den übergebenen Einschränkungen so genau wie möglich, während die übergebenen Einschränkungen weiterhin eingehalten werden:

Zwei UI-Baumstrukturen und ihre entsprechenden Darstellungen in Containern. In der ersten Option akzeptiert der Größenmodifikator die zunehmenden Einschränkungen. In der zweiten passt sich der Größenmodifikator so genau wie möglich an die zu großen Einschränkungen an, was zu Einschränkungen führt, die den Container füllen.
Abbildung 9. Der size-Modifikator, der der übergebenen Einschränkung so genau wie möglich entspricht.

Die Verkettung mehrerer size-Modifikatoren funktioniert nicht. Der erste size-Modifikator legt sowohl die minimale als auch die maximale Einschränkung auf einen festen Wert fest. Auch wenn der zweite Größenmodifikator eine kleinere oder größere Größe anfordert, muss er dennoch exakt die übergebenen Grenzen einhalten, sodass diese Werte nicht überschrieben werden:

Eine Kette von zwei Größenmodifikatoren im UI-Baum und dessen Darstellung in einem Container, die das Ergebnis des ersten übergebenen Werts und nicht des zweiten Werts ist.
Abbildung 10. Eine Kette aus zwei size-Modifikatoren, in der der zweite Wert (50dp) den ersten Wert (100dp) nicht überschreibt.

requiredSize-Modifikator

Verwenden Sie den Modifikator requiredSize anstelle von size, wenn Ihr Knoten die eingehenden Einschränkungen überschreiben soll. Der requiredSize-Modifikator ersetzt die eingehenden Einschränkungen und übergibt die von Ihnen angegebene Größe als exakte Grenzen.

Wenn die Größe wieder an den Baum übergeben wird, wird der untergeordnete Knoten im verfügbaren Bereich zentriert:

Die in einem UI-Baum verkettete Modifikatorgröße für Größe und requiredSize sowie die entsprechende Darstellung in einem Container. Die Einschränkungen für den Wert erforderlicher Modifikatoren überschreiben die Einschränkungen des Größenmodifikators.
Abbildung 11. Der requiredSize-Modifikator, der eingehende Einschränkungen aus dem size-Modifikator überschreibt.

Modifizierer für width und height

Der size-Modifikator passt sowohl die Breite als auch die Höhe der Einschränkungen an. Mit dem width-Modifikator können Sie eine feste Breite festlegen, die Höhe aber unentschlossen lassen. Ebenso können Sie mit dem height-Modifikator eine feste Höhe festlegen, die Breite jedoch unentschlossen lassen:

Zwei UI-Strukturen, eine mit dem Breitenmodifikator und seine Containerdarstellung und die andere mit dem Höhenmodifikator und dessen Darstellung.
Abbildung 12. Der width-Modifikator und der height-Modifikator legen eine feste Breite bzw. Höhe fest.

sizeIn-Modifikator

Mit dem sizeIn-Modifikator können Sie exakte minimale und maximale Einschränkungen für Breite und Höhe festlegen. Verwenden Sie den Modifikator sizeIn, wenn Sie die Einschränkungen genau steuern möchten.

Einen UI-Baum mit dem Modifikator sizeIn mit minimaler und maximaler Breite und Höhe sowie dessen Darstellung in einem Container.
Abbildung 13. Den sizeIn-Modifikator, wobei minWidth, maxWidth, minHeight und maxHeight festgelegt sind.

Beispiele

In diesem Abschnitt wird die Ausgabe mehrerer Code-Snippets mit verketteten Modifikatoren erläutert.

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

Dieses Snippet erzeugt die folgende Ausgabe:

  • Der Modifikator fillMaxSize ändert die Einschränkungen, um sowohl die minimale Breite als auch die minimale Höhe auf den Maximalwert zu setzen: 300dp in der Breite und 200dp in der Höhe.
  • Auch wenn der size-Modifikator die Größe 50dp verwenden möchte, muss er die eingehenden Mindesteinschränkungen einhalten. Der size-Modifikator gibt also auch die exakten Einschränkungsgrenzen von 300 durch 200 aus und ignoriert dabei den Wert, der im size-Modifikator angegeben ist.
  • Image folgt diesen Grenzen und meldet eine Größe von 300 nach 200, die bis zum Ende der Baumstruktur übergeben wird.

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

Dieses Snippet erzeugt die folgende Ausgabe:

  • Der fillMaxSize-Modifikator passt die Einschränkungen an, um sowohl die Mindestbreite als auch die minimale Höhe auf den Maximalwert zu setzen: 300dp in der Breite und 200dp in der Höhe.
  • Der wrapContentSize-Modifikator setzt die Mindestbeschränkungen zurück. Während fillMaxSize zu festen Einschränkungen führte, setzt wrapContentSize den Parameter wieder auf die begrenzten Einschränkungen zurück. Der folgende Knoten kann jetzt wieder den gesamten Speicherplatz einnehmen oder kleiner als den gesamten Bereich sein.
  • Der size-Modifikator legt die Einschränkungen auf die Mindest- und Höchstwerte von 50 fest.
  • Image wird in eine Größe von 50 mal 50 aufgelöst und der Modifikator size leitet diese weiter.
  • Der wrapContentSize-Modifikator hat eine spezielle Eigenschaft. Sie stellt es in die Mitte der verfügbaren Mindestgrenzen, die an das untergeordnete Element übergeben wurden. Die Größe, die er mit seinen übergeordneten Elementen kommuniziert, entspricht somit den Mindestgrenzen, die an die Ebene übergeben wurden.

Indem Sie nur drei Modifikatoren kombinieren, können Sie eine Größe für die zusammensetzbare Funktion definieren und sie auf das übergeordnete 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 clip-Modifikator ändert die Einschränkungen nicht.
    • Der padding-Modifikator senkt die maximalen Beschränkungen.
    • Der size-Modifikator setzt alle Einschränkungen auf 100dp.
    • Image berücksichtigt diese Einschränkungen und meldet eine Größe von 100 zu 100dp.
    • Mit dem Modifikator padding wird 10dp für alle Größen hinzugefügt, sodass Breite und Höhe im Bericht um 20dp erhöht werden.
    • In der Zeichenphase wird der clip-Modifikator jetzt auf einem Canvas von 120 nach 120dp angewendet. Daher wird eine Kreismaske dieser Größe erstellt.
    • Der padding-Modifikator setzt dann den Inhalt für alle Größen um 10dp ein, sodass die Canvasgröße um 100dp auf 100 verringert wird.
    • In diesem Canvas wird Image gezeichnet. Das Bild wird basierend auf dem ursprünglichen Kreis von 120dp abgeschnitten, sodass die Ausgabe ein nicht rundes Ergebnis ist.