August 2009
Layout und States in Flex 4
Neues Applikationslayout und überarbeitetes State-Konzept
Während der vorangegangene, erste Teil unserer Kurztutorialreihe zu Flex 4 das neue Komponentenmodell Spark behandelte, geht es an dieser Stelle um die Neuerungen im Applikationslayout und dem überarbeiteten State-Konzept.
Text: Kai König
Ein RIA User Interface mit Flex 4 besteht in aller Regel (sowohl mit Halo als auch mit Spark) immer aus einem Mix von UI-Containern und UI-Komponenten. Technisch gesehen sind auch Container letztlich Flex-Komponenten, dennoch ist eine Trennung in zwei Hauptkategorien semantisch sehr wichtig. Eine der üblichen Herangehensweisen zum Erstellen eines Anwendungslayouts ist die Nutzung von Containern zur Platzierung von Komponenten wie Buttons, Select Controls oder Texteingabefeldern. Zur Feinsteuerung des Layouts wurden in Flex 3 auch oftmals ineinander geschachtelt Container verwendet – eine Alternative ist die absolute Positionierung von Komponenten mittels Angabe von x- und y-Koordinaten.
Mit dem neuen Spark-Komponentenframework hat sich die Herangehensweise beim Gestalten einer Anwendung nun geändert. In Flex 3 und den Halo-Komponenten war jeder Container für das Layout seiner zugeordneten Inhalte verantwortlich, und jeder Container stammte von mx.core.-Container ab (das selbst wiederum von der Klasse UIComponent erbt). Diese Vererbungshierarchie macht das Rendering und den Komponentenlebenszyklus unnötig komplex. Die Layoutregeln in Halo-Komponenten sind des Weiteren sehr stark an die funktionalen Elemente des Containers gekoppelt.
In Spark ist nun das Layout eines Containers flexibel und zur Laufzeit anpassbar geworden. Man kann einen Container sogar ähnlich wie Komponenten in Spark skinnen. Anstelle von Containern wie HBox oder VBox, deren einziger Zweck letztlich die Anordnung von Komponenten war, nutzt Spark in Flex 4 generische Container – Entwickler und Designer ordnen diesen Containern mittels Delegation-Layouts zu. Das folgende Beispiel zeigt einen Group-Container mit vier Buttons, dessen Inhalt horizontal angeordnet ist.
<?xml version="1.0" encoding="utf-8"?><s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"xmlns:mx="library://ns.adobe.com/flex/halo"xmlns:s="library://ns.adobe.com/flex/spark"><s:Group><s:layout><s:HorizontalLayout/></s:layout><s:Button label="Button 1"/><s:Button label="Button 2"/><s:Button label="Button 3"/><s:Button label="Button 4"/></s:Group></s:Application>
Beim Group-Container handelt es sich um den leichtgewichtigsten der Spark-Container. Er unterstützt, im Sinne von erlaubten Inhalten, Klassen die das Interface IVisualElement implementieren und erlaubt daher Objekte vom Typ UIComponent und GraphicElement. Der Hauptunterschied zwischen dem Group-Container und dem ebenfalls oftmals verwendeten Containter SkinnableContainer ist, dass letztgenannter geskinnt werden kann.
Wie bereits weiter oben erwähnt, werden Containern in Flex 4 Layouts per Delegation zugeordnet. Default-Layouts für Group und SkinnableContainer sind BasicLayout bzw. VerticalLayout. BasicLayout entspricht dem aus Flex 3 bekannten absoluten Layout und erzwingt explizite Positionierungsangaben vom Entwickler oder Designer. Das obige Beispiel ließe sich auch verkürzt mithilfe des HGroup-Containers darstellen:
<s:HGroup><s:Button label="Button 1"/><s:Button label="Button 2"/><s:Button label="Button 3"/><s:Button label="Button 4"/></s:HGroup>
Ein Beispiel für einen Container mit Custom Skin zeigt der folgende Codeschnipsel. In dieser Applikation wird eine Instanz des SkinnableContainers mit einem Skin versehen, der einen blauen Rahmen um die Gruppe zieht, den Hintergrund des Containers hellgrau färbt und die Inhalte des Containers als Default vertikal übereinander anordnet. Man sieht hier zudem, dass der SkinnableContainer in der Anwendung keinen <s:layout>-Block hat, also die vertikale Default-Anordnung nicht überschreibt.
<s:SkinnableContainer skinClass="nz.co.ventego.skins.container.GrayRectGroupSkin"><s:Button label="Button 1"/><s:Button label="Button 2"/><s:Button label="Button 3"/><s:Button label="Button 4"/></s:SkinnableContainer>
Im Skin sehen wir Verweise auf States, dabei handelt es sich um die verschiedenen Zustände einer Komponente oder eines Containers. Wie bereits im ersten Teil des Tutorials gezeigt, muss man beim Erzeugen eines Skins die vom entsprechenden Container oder der jeweiligen Komponente unterstützten States angeben. In diesem Fall ist der Container entweder im Zustand normal oder disabled.
<?xml version="1.0" encoding="utf-8"?><s:Skin xmlns:fx="http://ns.adobe.com/mxml/2009"xmlns:s="library://ns.adobe.com/flex/spark"alpha.disabled="0.5"><fx:Metadata>[HostComponent("spark.components.SkinnableContainer")]</fx:Metadata><s:states><s:State name="normal" /><s:State name="disabled" /></s:states><s:Rect x="0" y="0" radiusX="6" radiusY="6" height="100%" width="100%"><s:stroke><s:LinearGradientStroke weight="2"><s:entries><mx:GradientEntry color="0x0000FF"/></s:entries></s:LinearGradientStroke></s:stroke><s:fill><s:LinearGradient><s:entries><mx:GradientEntry color="0xDDDDDD"/></s:entries></s:LinearGradient></s:fill></s:Rect><s:Group id="contentGroup" left="10" right="10" top="10" bottom="10"><s:layout><s:VerticalLayout/></s:layout></s:Group></s:Skin>
Ähnliche Beispiele lassen sich mithilfe der Container DataGroup und SkinnableDataContainer erzeugen, diese ersetzen im weitesten Sinne die listenbasierten Container aus Flex 3. Bereits anhand dieser kurzen Einführung kann man sehen, dass die Limitierung und Überarbeitung der zur Verfügung stehenden Containerlayout, Inhalt und Skin sehr sauber trennen und die delegationsbasierten Layouts die Entwicklung eines Anwendungslayouts deutlich klarer macht. Ein sehr schön anzusehender Container, der seine Inhalte in einem Kreis anordnet, wurde von Andrew Trice bereitgestellt.

























