Tuesday, June 27, 2006

Flex 2 Layout: Beyond the Standard Container

This is also posted on my other blog, but I might as well put it here too!

Traditionally, Flex layouts are based upon a hierarchy of containers. For example, Lets take the screen in Figure 1:

Figure 1
Figure 1: Flex 1.5 Style Layout

In the traditional Flex 1.5 container-based layout, this type of screen will require a mx:Panel, a mx:VBox, and a series of mx:HBox elements (each mx:HBox contains a mx:Label and mx:TextInput element). Take a look at the code:


<mx:Panel title="Flex Demo - 1.5 Style Layout"
   paddingBottom="10" paddingLeft="10" paddingTop="10" paddingRight="10">

   <mx:VBox width="100%" height="100%">
      <mx:HBox width="100%" >
         <mx:Label text="Field 1" width="50" />
         <mx:TextInput width="100%" />
      </mx:HBox>

      <mx:HBox width="100%" >
         <mx:Label text="Field 2" width="50" />
         <mx:TextInput width="100%" />
      </mx:HBox>

      <mx:HBox width="100%" >
         <mx:Label text="Field 3" width="50" />
         <mx:TextInput width="100%" />
      </mx:HBox>

      <mx:HBox width="100%" >
         <mx:Label text="Field 4" width="50" />
         <mx:TextInput width="100%" />
      </mx:HBox>

      <mx:HBox width="100%" >
         <mx:Label text="Field 5" width="50" />
         <mx:TextInput width="100%" />
      </mx:HBox>

      <mx:HBox width="100%" horizontalAlign="center">
         <mx:Button width="30" label="OK" />
         <mx:Button width="60" label="Cancel" />
      </mx:HBox>

      </mx:VBox>
</mx:Panel>


You will see exactly as I just described. What's wrong with this layout? … absolutely nothing, but there is a better way to do it.

Flex 2 provides us with the capability to position elements relative to their parent containers. Basically, this means that Flex 2 can allow us to build a similar component, but without the nested containers. If you compare Figure 1 and Figure 2, you will see that these screens are nearly identical. On the code level, things are very different.

UIComponent objects now support the "left", "right", "top" and "bottom" properties. These properties allow you to position your component relative to the parent container. So, If I have a mx:Label element that has top="10", that Label will be bound so that it is always 10 pixels away from the top of the parent container.

Lets take a look at Figure 2: You easily see how similar the layout is, but now take a look at the code.

Figure 2
Figure 2: Flex 2.0 Style Layout


<mx:Panel title="Flex Demo - 2 Style Layout"
   paddingBottom="10" paddingLeft="10" paddingTop="10" paddingRight="10"
   layout="absolute" height="233">

   <mx:Label text="Field 1" width="50" top="10" left="10"/>
   <mx:TextInput right="10" left="65" top="8"/>

   <mx:Label text="Field 2" width="50" top="40" left="10"/>
   <mx:TextInput right="10" left="65" top="38"/>

   <mx:Label text="Field 3" width="50" top="70" left="10"/>
   <mx:TextInput right="10" left="65" top="68"/>

   <mx:Label text="Field 4" width="50" top="100" left="10"/>
   <mx:TextInput right="10" left="65" top="98"/>

   <mx:Label text="Field 5" width="50" top="130" left="10"/>
   <mx:TextInput right="10" left="65" top="128"/>

   <mx:Button width="30" label="OK" bottom="10" right="80"/>
   <mx:Button width="60" label="Cancel" right="10" bottom="10"/>

</mx:Panel>



You can clearly see that this is much simpler and cleaner code. That's only one of the advantages of Flex 2.0 position bound layouts. Another advantage is that this does not require containers within containers, as the Flex 1.5 style layout does. This is a huge advantage. Each container resolves to be an additional movieclip object when the Flex is compiled into a swf and rendered within your browser. Since there are less components, there are less movie clip objects in the runtime, thus there are less resources being used to render the nearly identical screen! This improves the overall speed, initialization, and rendering time of your entire application. In my example, you won't notice much of a difference, but imagine if you had a huge application with hundreds of different components. There would be an enormous difference.

Another advantage of the Flex 2 style layout is that all of the position binding can be done using Flex's CSS styling engine. Take a look at Figure 3. It looks exactly like Figure 2, doesn't it? Now, take a look at the code.

Figure 3
Figure 3: Flex 2.0 CSS Style Layout


<mx:Style>
   .label1{ width:10; top:10; left:10; }
   .textInput1{ right:10; left:65; top:8; }

   .label2{ width:10; top:40; left:10; }
   .textInput2{ right:10; left:65; top:38; }

   .label3{ width:10; top:70; left:10; }
   .textInput3{ right:10; left:65; top:68; }

   .label4{ width:10; top:100; left:10; }
   .textInput4{ right:10; left:65; top:98; }

   .label5{ width:10; top:130; left:10; }
   .textInput5{ right:10; left:65; top:128; }

   .button1{ width:30; bottom:10; right: 80; }
   .button2{ width:60; bottom:10; right: 10; }

</mx:Style>

<mx:Panel title="Flex Demo - 2 CSS Style Layout"
   paddingBottom="10" paddingLeft="10" paddingTop="10" paddingRight="10"
   layout="absolute" height="233">

   <mx:Label text="Field 1" styleName="label1" />
   <mx:TextInput styleName="textInput1" />

   <mx:Label text="Field 2" styleName="label2" />
   <mx:TextInput styleName="textInput2" />

   <mx:Label text="Field 3" styleName="label3" />
   <mx:TextInput styleName="textInput3" />

   <mx:Label text="Field 4" styleName="label4" />
   <mx:TextInput styleName="textInput4" />

   <mx:Label text="Field 5" styleName="label5" />
   <mx:TextInput styleName="textInput5" />

   <mx:Button label="OK" styleName="button1" />
   <mx:Button label="Cancel" styleName="button2" />

</mx:Panel>


Yes, this is more code than Figure 3. Why would you want to do this? … CSS positioning allows you to separate the display/positioning logic from your actual application logic. It enables UI designers to work independently from engineers. Engineers can put an actual application together, while UI designers develop the styles separately. Neither is waiting on the other. When the UI design is ready, the styles can be simply "dropped" into the engineer's code, and now application is fully styled, with little additional work for the engineer.

This is not only beneficial for the separation of designer and engineering roles… An application can be "re-skinned" very easily. Take a look at Figure 4. you will see that the application looks different. The best part is that NONE of the application logic has changed from Figure 3. The only thing that has changed is the CSS style definitions.

Figure 4
Figure 4: Flex 2.0 CSS Style Alternate Layout


<mx:Style>

   .label1{ width:10; top:10; right:10; }
   .textInput1{ left:10; right:65; top:8; }

   .label2{ width:10; top:40; right:10; }
   .textInput2{ left:10; right:65; top:38; }

   .label3{ width:10; top:70; right:10; }
   .textInput3{ left:10; right:65; top:68; }

   .label4{ width:10; top:100; right:10; }
   .textInput4{ left:10; right:65; top:98; }

   .label5{ width:10; top:130; right:10; }
   .textInput5{ left:10; right:65; top:128; }

   .button1{ width:30; bottom:10; left: 80; }
   .button2{ width:60; bottom:10; left: 10; }

</mx:Style>

<mx:Panel title="Flex Demo - 2 CSS Style Layout (alternate)"
   paddingBottom="10" paddingLeft="10" paddingTop="10" paddingRight="10"
   layout="absolute" height="233">

   <mx:Label text="Field 1" styleName="label1" />
   <mx:TextInput styleName="textInput1" />

   <mx:Label text="Field 2" styleName="label2" />
   <mx:TextInput styleName="textInput2" />

   <mx:Label text="Field 3" styleName="label3" />
   <mx:TextInput styleName="textInput3" />

   <mx:Label text="Field 4" styleName="label4" />
   <mx:TextInput styleName="textInput4" />

   <mx:Label text="Field 5" styleName="label5" />
   <mx:TextInput styleName="textInput5" />

   <mx:Button label="OK" styleName="button1" />
   <mx:Button label="Cancel" styleName="button2" />

</mx:Panel>


Another key benefit of position binding is that the bindings are relative to the parent container… if the parent container resizes, then so do you child containers. Figure 5 shows an example of this. The only thing that has changed between Figure 4 and Figure 5 is that the width of the mx:Panel container has been increased.

Figure 5
Figure 5: Resizing Elements with Bound Positions

Download All Examples For This Post Here

0 Comments:

Post a Comment

<< Home