Using Flex Containers – Tips and Reference

November 10, 2010By 24 Comments

This post is intended to give developers a quick reference guide to using Flex 4 containers and layouts. Though it’s not necessarily a complex issue, it does seem to be a source of frustration for many, and particularly those beginning Flex. Code often ends up with too many nested containers and extraneous properties that aren’t serving any purpose because the developer may not understand how to use them correctly.

Below is a summary of the Flex 4 containers and some general information, including if they are skinnable, how to make them scroll etc. The minimum and default sizes are also important to make note of since it makes a difference in aligning children. Note that Basic layout is equivalent to Flex 3′s absolute layout.

• By default, Flash Builder will create an Application with a minimum width and minimum height of 955 and 600 respectively. You can change this by going into the Flash Builder Preferences and removing the minSize variable from the File Template. Go to Flash Builder | Preferences | Flash Builder | File templates | MXML Web Application. Select ‘Edit…’ and remove this from the template → ${min_size} then press ‘Ok’.

• All Spark containers above support both GraphicElements (shapes, FXG etc) and VisualElements (UI controls) as direct children. This is not the case with all MX containers.

• Some containers support nested layout tags to override the default listed above (include the layout tag as a child). The containers that allow you to nest a layout are: Application, BorderContainer, Group, Panel and SkinnableContainer

Layouts
It’s often easier to grasp a concept more quickly when it’s presented visually (as they say a picture is worth a thousand words)! Below are a few images by Justin Shacklette and Gilles Guillemin who own FlexLayouts.org that really go a long way in explaining the different default layouts in Flex 4. They also show how the properties such as padding, horizontal/verticalAlign and gap would apply. You can download the reference PDF’s from here. Check out their cool custom Flex 4 layouts while you’re there!

Scrolling with Groups
Scrolling is much different in Flex 4 compared to Flex 3 since the scrolling is not built into the component. The best practice for scrolling a Group is to wrap that Group (or HGroup/VGroup etc) in a Spark Scroller object. The key with the Scroller is to set the width and height to the size of the contents you want to be viewable. You can also set a scroll position to display the contents at a current location within that range. If you don’t set width/height, or if you set it to values bigger than the contents, the scrollbars will never appear. For instance, consider the following code, and the result showing no scrollbars (since the width and height were equal to the size of the image). The same result would occur if the width/height were omitted from the Scroller object completely:

<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
			   xmlns:s="library://ns.adobe.com/flex/spark"
			   xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600">

	<s:Scroller width="300" height="300">
		<s:Group>
			<mx:Image width="300" height="300"
					  source="@Embed(source='logo.png')"/>
		</s:Group>
	</s:Scroller>
</s:Application>

Now in the following code, half of the image will appear vertically along with a vertical scrollbar allowing the other half of the image to scroll. No horizontal scrollbar will be added since the height will be sized to the content height by default:

<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
			   xmlns:s="library://ns.adobe.com/flex/spark"
			   xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600">

	<s:Scroller width="150">
		<s:Group>
			<mx:Image width="300" height="300"
					  source="@Embed(source='logo.png')"/>
		</s:Group>
	</s:Scroller>
</s:Application>


Scrolling a Skinnable Container
It’s recommended that skinnable containers (which includes the Spark Application, BorderContainer, NavigatorContent, Panel and Window) have the Scroller object added into the skin class around the contentGroup Group object. An example of how this can be done is shown in this code snippet taken from a custom SkinnableContainer MXML skin.

<s:Scroller width="100%" height="100%">
	<s:Group id="contentGroup"  minWidth="0" minHeight="0" />
</s:Scroller>

The alternative is to nest a Scroller and Group around your content within your code as the first child, however the preferred method is to keep it separated in the skin class. For more details about scrolling and containers, see this link.

Layout Guidelines
• If the container of the object has basic or absolute layout, use constraints such as left, right, top, bottom, horizontalCenter, verticalCenter to determine its placement.

• If the container of the object has a vertical or horizontal layout (either with the layout tag or using HGroup/VGroup), use the horizontalAlign, verticalAlign, gap, paddingTop, paddingBottom, paddingLeft, paddingRight attributes to control the children and the whitespace around them. These attributes cannot be used with a basic/absolute layout.

Note the following code and screenshot showing two containers each with a different layout and properties specified but displaying the same result:

<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
			   xmlns:s="library://ns.adobe.com/flex/spark"
			   xmlns:mx="library://ns.adobe.com/flex/mx">
	<s:layout>
		<s:VerticalLayout horizontalAlign="center" verticalAlign="middle"/>
	</s:layout>

	<!-- Container 1 has a BasicLayout (default) and uses constraints on the label itself placement -->
	<s:SkinnableContainer id="c1" backgroundColor="0x000000" color="0xFFFFFF" width="420" height="200">
		<s:Label horizontalCenter="0" top="30"
				 text="Basic Layout using constraints on the object itself for layout."/>
	</s:SkinnableContainer>

	<!-- Container 2 has a VerticalLayout with align and padding properties set on it for label placement -->
	<s:SkinnableContainer id="c2" backgroundColor="0x000000" color="0xFFFFFF" width="420" height="200" >
		<s:layout>
			<s:VerticalLayout horizontalAlign="center" paddingTop="30"/>
		</s:layout>
		<s:Label text="VerticalLayout that specifies where the label is placed with properties."/>
	</s:SkinnableContainer>
</s:Application>

• To center children within a container with a horizontal/vertical layout (or HGroup/VGroup), use horizontalAlign=”center” and verticalAlign=”middle”.

• To center a component within a container that has a basic or absolute layout, use horizontalCenter=”0″ and verticalCenter=”0″ on the component to be centered.

Note the next two code samples regarding centering showing the same exact result:

<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
			   xmlns:s="library://ns.adobe.com/flex/spark"
			   xmlns:mx="library://ns.adobe.com/flex/mx">
	<s:layout>
		<s:VerticalLayout horizontalAlign="center" verticalAlign="middle"/>
	</s:layout>
	<s:BorderContainer borderColor="red" borderWeight="5" width="300" height="300"/>
</s:Application>

The result:

<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
			   xmlns:s="library://ns.adobe.com/flex/spark"
			   xmlns:mx="library://ns.adobe.com/flex/mx">
	<s:BorderContainer borderColor="red" borderWeight="5" width="300" height="300" horizontalCenter="0" verticalCenter="0"/>
</s:Application>

The result (notice it’s the same as the above):

General Tips
• In general, opt to use constraints over absolute positioning using x,y values since constraints dynamically resize with the browser. This is even more important now when many are developing cross-platform applications for web, desktop, mobile, tablet devices etc where screen sizes vary greatly.
• Use left/right OR horizontalCenter property but not both or they compete and it’s just bad practice.
• Use top/bottom OR verticalCenter property for the same reasons as above.

IMPORTANT NOTE: When in doubt about which properties to use, switch to Design view to see what options are available in the properties panel. It will switch depending on the component selected and container layout, and it a great way to double check what you’re doing.

Quick Summary of Properties

Check out the following links for more information on this topic:

Filed in: Adobe FlexFlex 4Flex/AIR Tags:

About the Author ()

Comments (24)

Trackback URL | Comments RSS Feed

  1. Justin says:

    Holly, thanks for the shoutout. Alas, the TileLayout PDF is wrong. For some amazing and unknown reason, TileLayout does not include any of the paddings. So no paddingLeft, paddingTop, etc on TileLayout.

  2. Tom Chiverton says:

    I’d like a nice PDF of those images (and some of the test) so I can pin it to the wall…

  3. Holly, great post on this topic. The explanations you gave were great, and the diagrams are fantastic.

    Just a nit about: “Use left/right OR horizontalCenter property but not both or they compete and it’s just bad practice.”

    I wouldn’t necessarily say that’s true. There is a case (check out Spark’s ButtonSkin.mxml) where you do want to set all three. Basically left/right are used for sizing purposes, while horizontalCenter is used for positioning purposes. Most of the time, you don’t need horizontalCenter and could accomplish the positioning with the left/right, but sometimes when minimum sizes come in to play, you still may want it centered rather than positioned at left=”someVal”.

  4. Arthur Neves says:

    Hi, trying to use the s:Scroller in Air but not working! is there something else that should I do?

  5. Brian Davis says:

    What about having a Group in a scroller and centering the Group at verticalCenter = 0 and horizontalCenter = 0 so when the scale of the group changes the group in always dead center in the scroller? How can we achieve that?

  6. mitch says:

    Great blog. Really useful information. The black-red-white colors are a little extreme though and make it hard to concentrate on the good content.

    • devgirl says:

      Thanks for the feedback Mitch! I’m actually in the process of moving to a new theme. It should be updated soon and much easier to read. Thanks much! Holly

  7. mitch says:

    Hi, here is a question I asked in a forum and never got an answer. It’s related to this blog post.

    Suppose you have this hierarchy:

    How do you set the padding in a style sheet?

    Group accepts styleName but not padding. Same with BorderContainer, it accepts
    styleName but not padding. VerticalLayout accepts padding but not styleName.

    Thanks.

    • mitch says:

      It looks like the blog software doesn’t display mxml. The hierarchy was:

      Group contains BorderContainer contains layout contains VerticalLayout.

  8. daslicht says:

    Hello Holly,
    I am currently struggling with a horizontal layout which is horizontal centered.

    But once the Scrollbar is shown the Content does a ugly jump.

    How to create a jump free horizontal centered layout?

    http://ansolas.com/public/flex/layouttest/

  9. daslicht says:

    I solved it by creting a custom scroller skin :)

  10. daslicht says:

    Its actually very simple, I have just removed all visual things in the inactive state of the scrollbar and set the VerticalScrollbar policy of the Scroller to “on” Thats it , no jumps: try :
    ansolas.com/shr

    :)

  11. ragav says:

    This one may not related to the above article, how can i achieve DefaultTilListEffect in list with tilelayout?

  12. Chris Farrell says:

    Hi Holly,
    Thank you for you excellent posts!
    Is there any way to add paging to horizontal/vertical scrolling? What si the best way to implement the classic photo gallery where the user swipes from photo to photo, and each one snaps to a ‘page’?
    Chris

  13. fox says:

    How could I create a “sticky” footer ?

    That when I resize the browser window, my footer is always placed at the bottom of the page?

  14. fox says:

    found teh solution myself:

    http://pastebin.com/u90k1dva

    easier than i thought :)

  15. Judah says:

    @Brian
    You can set the scroll positions to center the contents inside the scroller using this code:

    if (scroller.height < scroller.viewport.contentHeight) {
    scroller.viewport.verticalScrollPosition = (scroller.viewport.contentHeight – scroller.height) / 2;
    }

    if (scroller.width < scroller.viewport.contentWidth) {
    scroller.viewport.horizontalScrollPosition = (scroller.viewport.contentWidth – scroller.width) / 2;
    }

    I have not tried to scale at the same time.

  16. Raj says:

    Hi! Holly:

    I am trying to create a datagrid with the first column locked in position in a mobile app. I have 2 datagrids side by side. The second datagrid is supposed to scroll and is inside a scroller however it scrolls only horizontally but *NOT* vertically. Height and width of the second datagrid is set when the app runs and loads its data. Any ideas?

    Relevant code is at the bottom.

    Thanks

Leave a Reply