Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Hinweis
Dieses Buch wurde im Frühjahr 2016 veröffentlicht und seitdem nicht aktualisiert. Wenngleich ein großer Teil des Buchs weiterhin relevante Informationen liefert, sind einige Abschnitte veraltet, und einige Themen sind nicht mehr korrekt oder vollständig.
Xamarin.Forms umfasst eine Reihe von Klassen, die von Layout<View> abgeleitet sind:
StackLayout,Grid,AbsoluteLayoutundRelativeLayout.
In diesem Kapitel wird beschrieben, wie Sie eigene Klassen erstellen, die von Layout<View> abgeleitet werden.
Das Layout im Überblick
Es gibt kein zentralisiertes System zur Verarbeitung des Xamarin.Forms-Layouts. Jedes Element bestimmt die eigene Größe selbst und ermittelt, wie es innerhalb eines bestimmten Bereichs gerendert wird.
Über- und untergeordnete Elemente
Jedes Element, das über untergeordnete Elemente verfügt, ist für die Positionierung dieser untergeordneten Elemente verantwortlich. Die Größe der untergeordneten Elemente wird dabei vom übergeordneten Element basierend auf der verfügbaren Größe und der vom untergeordneten Element angestrebten Größe bestimmt.
Festlegung der Größe und Positionierung
Für das Layout wird im oberen Bereich der visuellen Struktur mit der Seite begonnen, auf die alle Branches folgen. Die wichtigste öffentliche Methode innerhalb des Layouts ist Layout, die durch VisualElement definiert wird. Jedes übergeordnete Element ruft für jedes seiner untergeordneten Elemente Layout auf, um die Größe des Elements festzulegen und seine Position zu bestimmen (relativ zum übergeordneten Element). Zu diesem Zweck wird ein Rectangle-Wert angegeben. Diese Aufrufe von Layout werden innerhalb der visuellen Struktur propagiert.
Damit ein Element auf dem Bildschirm angezeigt wird, muss Layout aufgerufen werden. Dadurch werden die folgenden schreibgeschützten Eigenschaften festgelegt. Diese Eigenschaften stimmen mit dem Rectangle-Wert überein, der an die Methode übergeben wird:
Boundsvom TypRectangleXvom TypdoubleYvom TypdoubleWidthvom TypdoubleHeightvom Typdouble
Vor dem Layout Aufruf Height und Width haben Simulierte Werte von –1.
Durch den Aufruf von Layout wird zudem der Aufruf der folgenden geschützten Methoden ausgelöst:
SizeAllocated, die wiederum zum Aufruf vonOnSizeAllocatedführt, die außer Kraft gesetzt werden kann.
Schließlich wird das folgende Ereignis ausgelöst:
Die Methode OnSizeAllocated wird durch Page und Layout überschrieben, den einzigen beiden Klassen in Xamarin.Forms, die über untergeordnete Elemente verfügen können. Die außer Kraft gesetzten Methodenaufrufe
UpdateChildrenLayoutfürPage-Ableitungen undUpdateChildrenLayoutfürLayout-Ableitungen. Dadurch wird folgender Aufruf ausgelöst:LayoutChildrenfürPage-Ableitungen undLayoutChildrenfürLayout-Ableitungen.
LayoutChildren ruft dann für jedes untergeordnete Element des Elements Layout auf. Wenn mindestens ein untergeordnetes Element über eine neue Bounds-Einstellung verfügt, wird das folgende Ereignis ausgelöst:
LayoutChangedfürPage-Ableitungen undLayoutChangedfürLayout-Ableitungen
Constraints und Größenanforderungen
Damit LayoutChildren einen intelligenten Aufruf von Layout für alle seine untergeordneten Elemente durchführen kann, muss eine bevorzugte oder gewünschte Größe der untergeordneten Elemente bekannt sein. Aus diesem Grund wird den Aufrufen von Layout für die einzelnen untergeordneten Element in der Regel folgender Aufruf vorangestellt:
Nach der Veröffentlichung dieses Buchs wurde die Methode GetSizeRequest durch folgende Methode ersetzt:
Die Methode Measure umfasst die Margin-Eigenschaft sowie ein Argument vom Typ MeasureFlag, das über zwei Member verfügt:
IncludeMarginsNone, um Ränder auszuschließen
Bei vielen Elementen ruft GetSizeRequest oder Measure die native Größe des Elements von seinem Renderer ab. Beide Methoden verfügen über Constraints für Breite und Höhe. Label verwendet z.B. die Breitenbeschränkung, um zu ermitteln, wie mehrere Textzeilen umbrochen werden.
Sowohl GetSizeRequest als auch Measure geben einen Wert vom Typ SizeRequestzurück, der über zwei Eigenschaften verfügt:
Diese beiden Werte sind häufig identisch, und der Minimum-Wert kann üblicherweise ignoriert werden.
VisualElement definiert zudem eine geschützte Methode, die GetSizeRequest ähnelt und von GetSizeRequest aufgerufen wird:
OnSizeRequestgibt einenSizeRequest-Wert zurück
Diese Methode ist inzwischen veraltet und wurde wie folgt ersetzt:
Jede Klasse, die von Layout oder Layout<T> abgeleitet wird, muss OnSizeRequest oder OnMeasure außer Kraft setzen. An dieser Stelle bestimmt eine Layoutklasse ihre eigene Größe, die im Allgemeinen auf der Größe ihrer untergeordneten Elemente basiert, die sie durch einen Aufruf von GetSizeRequest oder Measure für die untergeordneten Elemente erhält. Vor und nach dem Aufruf von OnSizeRequest oder OnMeasure nimmt GetSizeRequest oder Measure basierend auf den folgenden Eigenschaften Anpassungen vor:
WidthRequestvom Typdouble, wirkt sich auf dieRequest-Eigenschaft vonSizeRequestausHeightRequestvom Typdouble, wirkt sich auf dieRequest-Eigenschaft vonSizeRequestausMinimumWidthRequestvom Typdouble, wirkt sich auf dieMinimum-Eigenschaft vonSizeRequestausMinimumHeightRequestvom Typdouble, wirkt sich auf dieMinimum-Eigenschaft vonSizeRequestaus
Unbegrenzte Constraints
Die an GetSizeRequest (oder Measure) und OnSizeRequest (oder OnMeasure) übergebenen Argumente können unbegrenzt sein (d.h. Werte von Double.PositiveInfinity). Der von diesen Methoden zurückgegebene SizeRequest-Wert kann jedoch keine unbegrenzten Dimensionen enthalten.
Unbegrenzte Constraints geben an, dass die angeforderte Größe der natürlichen Größe des Elements entsprechen soll. Ein vertikales StackLayout ruft GetSizeRequest (oder Measure) für seine untergeordneten Elemente mit einer unbegrenzten Höheneinschränkung auf. Ein horizontales Stapellayout ruft GetSizeRequest (oder Measure) für seine untergeordneten Elemente mit einer unbegrenzten Breiteneinschränkung auf. Ein AbsoluteLayout ruft GetSizeRequest (oder Measure) für seine untergeordneten Elemente mit einer unbegrenzten Breiten- und Höheneinschränkung auf.
Der Prozess im Detail
ExploreChildSize zeigt Informationen zu Constraints und Größenanforderungen für ein einfaches Layout.
Ableiten aus der Layoutansicht<>
Eine benutzerdefinierte Layoutklasse wird von Layout<View> abgeleitet. Sie hat zwei Aufgaben:
- Außerkraftsetzen von
OnMeasure, umMeasurefür alle untergeordneten Elemente im Layout aufzurufen Zurückgeben einer angeforderten Größe für das Layout selbst - Außerkraftsetzen von
LayoutChildren, umLayoutfür alle untergeordneten Elemente im Layout aufzurufen
Die for- oder foreach-Schleife dieser Außerkraftsetzungen sollte alle untergeordneten Elemente überspringen, deren IsVisible-Eigenschaft auf false festgelegt ist.
OnMeasure wird nicht in jedem Fall aufgerufen. Wenn das übergeordnete Element des Layouts die Größe des Layouts bestimmt (z.B. ein Layout, das eine Seite füllt), wird OnMeasure nicht aufgerufen. Aus diesem Grund kann sich LayoutChildren nicht darauf verlassen, dass die Größe der untergeordneten Elemente beim Aufruf von OnMeasure bestimmt wird. Häufig muss LayoutChildren den Aufruf von Measure selbst für die untergeordneten Elemente des Layouts durchführen. Alternativ können Sie eine Logik zum Zwischenspeichern der Größe implementieren (dieses Thema wird später näher besprochen).
Ein einfaches Beispiel
Das Beispiel VerticalStackDemo enthält eine vereinfachte VerticalStack-Klasse und zeigt, wie diese Klasse verwendet wird.
Vereinfachte vertikale und horizontale Positionierung
Eine der Aufgaben, die VerticalStack ausführen muss, findet während der Außerkraftsetzung von LayoutChildren statt. Die Methode ermittelt anhand der Eigenschaft HorizontalOptions des untergeordneten Elements, wie das untergeordnete Element innerhalb von VerticalStack positioniert werden soll. Sie können stattdessen die statische Methode Layout.LayoutChildIntoBoundingRect aufrufen. Diese Methode ruft Measure für das untergeordnete Element auf und positioniert das untergeordnete Element basierend auf den Eigenschaften HorizontalOptions und VerticalOptions innerhalb des angegebenen Rechtecks.
Invalidierung
Häufig wirkt sich eine Änderung der Eigenschaft eines Elements darauf aus, wie das Element im Layout angezeigt wird. Das Layout muss ungültig gemacht werden, um ein neues Layout zu starten.
VisualElement definiert die geschützte Methode InvalidateMeasure, die üblicherweise vom Handler für geänderte Eigenschaften einer bindbaren Eigenschaft aufgerufen wird, deren Änderung sich auf die Größe des Elements auswirkt. Die Methode InvalidateMeasure löst ein MeasureInvalidated-Ereignis aus.
Die Klasse Layout definiert eine ähnliche geschützte Methode InvalidateLayout, die von einer Layout-Ableitung für jede Änderung aufgerufen werden sollte, die sich auf die Position und Größe ihrer untergeordneten Elemente auswirkt.
Regeln für die Layoutprogrammierung
Eigenschaften, die durch
Layout<T>-Ableitungen definiert werden, sollten durch bindbare Eigenschaften gestützt werden, und die Handler für geänderte Eigenschaften solltenInvalidateLayoutaufrufen.Eine
Layout<T>-Ableitung, die angefügte bindbare Eigenschaften definiert, sollteOnAddedaußer Kraft setzen, um einen Handler für geänderte Eigenschaften zu ihren untergeordneten Elementen hinzuzufügen, undOnRemovedaußer Kraft setzen, um diesen Handler zu entfernen. Der Handler sollte diese angefügten bindbaren Eigenschaften auf Änderungen überprüfen und ggf. mit einem Aufruf vonInvalidateLayoutreagieren.Ein
Layout<T>Abgeleiteter, der einen Cache mit untergeordneten Größen implementiert, sollte den Cache überschreibenInvalidateLayoutundOnChildMeasureInvalidatedlöschen, wenn diese Methoden aufgerufen werden.
Ein Layout mit Eigenschaften
Die Klasse WrapLayout in der Bibliothek Xamarin.FormsBook.Toolkit setzt voraus, dass alle untergeordneten Elemente dieselbe Größe aufweisen, und führt für die untergeordneten Elemente einen Zeilen- oder Spaltenumbruch durch. Die Klasse definiert eine Orientation-Eigenschaft wie StackLayoutsowie ColumnSpacing- und RowSpacing-Eigenschaften wie Grid. Darüber hinaus wird mit dieser Klasse die Größe von untergeordneten Elementen zwischengespeichert.
Im Beispiel PhotoWrap wird ein WrapLayout mit einer ScrollView kombiniert, um Fotos anzuzeigen.
Dimensionen ohne Einschränkungen sind nicht zulässig!
UniformGridLayout in der Bibliothek Xamarin.FormsBook.Toolkit ist so ausgelegt, dass alle untergeordneten Elemente innerhalb des Layouts angezeigt werden. Aus diesem Grund können keine Dimensionen ohne Einschränkungen verarbeitet werden. Wird eine solche Dimension erkannt, wird eine Ausnahme ausgelöst.
Das UniformGridLayout wird im Beispiel PhotoGrid veranschaulicht:
Überlappende untergeordnete Elemente
Bei einer Layout<T>-Ableitung ist eine Überlappung von untergeordneten Elementen möglich. Die untergeordneten Elemente werden jedoch in ihrer Reihenfolge in der Children-Auflistung gerendert, nicht in der Reihenfolge, in der ihre Layout-Methoden aufgerufen werden.
Die Klasse Layout definiert zwei Methoden, mit denen Sie ein untergeordnetes Element innerhalb der Auflistung verschieben können:
LowerChild, um ein untergeordnetes Element an den Anfang der Auflistung zu verschiebenRaiseChild, um ein untergeordnetes Element ans Ende der Auflistung zu verschieben
Bei überlappenden untergeordneten Elementen werden untergeordnete Elemente am Ende der Auflistung oberhalb von untergeordneten Elementen am Anfang der Auflistung angezeigt.
Die Klasse OverlapLayout in der Bibliothek Xamarin.FormsBook.Toolkit definiert eine angefügte Eigenschaft zur Angabe der Renderreihenfolge. Auf diese Weise kann eins der zugehörigen untergeordneten Elemente oberhalb von anderen Elementen angezeigt werden. Dies wird im Beispiel StudentCardFile veranschaulicht:
Weitere angefügte bindbare Eigenschaften
Die Klasse CartesianLayout in der Bibliothek Xamarin.FormsBook.Toolkitdefiniert angefügte bindbare Eigenschaften, mit denen zwei Point-Werte und ein Wert für die Dicke angegeben werden können. Außerdem werden BoxView-Elemente so bearbeitet, dass sie Zeilen ähneln.
Im Beispiel UnitCube wird diese Klasse für einen 3D-Würfel verwendet.
Layout und LayoutTo
Eine Layout<T>-Ableitung kann LayoutTo anstelle von Layout aufrufen, um das Layout zu animieren. Für diesen Vorgang wird die Klasse AnimatedCartesianLayout verwendet, wie im Beispiel AnimatedUnitCube gezeigt.

