Using the Container Classes to Lay Out PlayBook Applications

I just put together a tutorial on using the Container classes in the PlayBook SDK. Coming from a Flex background I found the Container classes kind of confusing at first but ultimately a nice elegant solution to the problem of laying objects out on the screen. The tutorial provides an introduction to the Container classes, shows some of the properties that you use to customize them, then walks through a basic example of a header and two sub containers and how to place and align components inside them. Finally it talks about resizing containers.

Here’s a link to the video. The code for the demo is below.

package
{
	import flash.display.Sprite;
	import flash.display.StageAlign;
	import flash.display.StageScaleMode;
	import flash.events.MouseEvent;
 
	import qnx.ui.buttons.LabelButton;
	import qnx.ui.core.Container;
	import qnx.ui.core.ContainerFlow;
	import qnx.ui.core.Containment;
	import qnx.ui.core.SizeMode;
	import qnx.ui.core.SizeUnit;
	import qnx.ui.core.Spacer;
	import qnx.ui.data.DataProvider;
	import qnx.ui.listClasses.List;
	import qnx.ui.text.Label;
 
	[SWF(height="600",width="1024")]
	public class ContainerDemo extends Sprite
	{
 
		private var base:Container;
 
		private var left:Container;
 
		private var right:Container;
 
		private var header:Container;
 
		public function ContainerDemo()
		{
			super();
 
			// support autoOrients
			stage.align = StageAlign.TOP_LEFT;
			stage.scaleMode = StageScaleMode.NO_SCALE;
 
			// Set up the base container with a horizontal flow
			base = new Container();
			base.debugColor = 0xff0000;
			base.margins = Vector.<Number>([10,10,10,10]);
			base.flow = ContainerFlow.HORIZONTAL;
 
			// Set up the left container with a size of
			// 50 percent
			left = new Container();
			left.debugColor = 0x00ff00;
			left.margins = Vector.<Number>([10,10,10,10]);
			left.size = 50;
			left.sizeUnit = SizeUnit.PERCENT;
 
			// Set up the right container with a size of 
			// 50 percent. By default the Container class
			// lays things out with a vertical flow.
			right = new Container();
			right.debugColor = 0x0000ff;
			right.margins = Vector.<Number>([10,10,10,10]);
			right.size = 50;
			right.sizeUnit = SizeUnit.PERCENT;
 
			// Create the header and dock it to the top 
			// of the screen
			header = new Container();
			header.debugColor = 0x00ffff;
			header.margins = Vector.<Number>([10,10,10,10]);
			header.size = 15;
			header.sizeUnit = SizeUnit.PERCENT;
			header.containment = Containment.DOCK_TOP;
			header.flow = ContainerFlow.HORIZONTAL;
 
 
			// Set up the array, data provider, and 
			// list component 
			var arr:Array = new Array({label:"Deschuttes The Abyss"},
				{label:"New Belgium Sahti"},{label:"Russian River Pliney The Elder"},
				{label:"Dogfish Head Bitches Brew"},{label:"Stone Double Bastard Ale"},
				{label:"Elysian Bifröst Winter Ale"},{label:"Odell 90 Shilling"},
				{label:"Lagunitas Undercover Investigation Shut-Down Ale"},
				{label:"Delirium Tremens"},{label:"Alaskan Double Black IPA"},
				{label:"John John Juniper"},{label:"Full Sail Wreck the Halls"},
				{label:"Samuel Adams Winter Lager"});
			var data:DataProvider = new DataProvider(arr);			
			var list:List = new List();
				list.dataProvider = data;
				list.containment = Containment.BACKGROUND;
 
			// Create the nav buttons with a width of 33.3 percent
			// and set the sizeMode to both so they take up 100% 
			// of the height of the parent container.
			var nav1:LabelButton = new LabelButton();
				nav1.label = "Home";
				nav1.size = 33.3;
				nav1.sizeUnit = SizeUnit.PERCENT;
				nav1.sizeMode = SizeMode.BOTH;
				nav1.addEventListener(MouseEvent.CLICK,onClick);
 
			var nav2:LabelButton = new LabelButton();
				nav2.label = "Recommended Beers";
				nav2.size = 33.3;
				nav2.sizeUnit = SizeUnit.PERCENT;
				nav2.sizeMode = SizeMode.BOTH;
 
			var nav3:LabelButton = new LabelButton();
				nav3.label = "Rated Beers";
				nav3.size = 33.3;
				nav3.sizeUnit = SizeUnit.PERCENT;
				nav3.sizeMode = SizeMode.BOTH;
 
			var spacer:Spacer = new Spacer();
				spacer.size = 50;
				spacer.sizeUnit = SizeUnit.PERCENT;
 
			var label:Label = new Label();
				label.text = "Pintley For PlayBook!";
 
 
			// The addChild calls
			header.addChild(nav1);
			header.addChild(nav2);
			header.addChild(nav3);				
 
			right.addChild(spacer);
			right.addChild(label);
 
			left.addChild(list);
 
			base.addChild(header);
 
			base.addChild(left);
			base.addChild(right);
 
 
			addChild(base);
 
			base.setSize(stage.stageWidth,stage.stageHeight);
		}
 
		protected function onClick(event:MouseEvent):void
		{
			// changes the size of the left/right containers
			// and then calls base.layout() so that all of
			// the base container's children are re-configured
			// and redrawn
			left.size = 25;
			right.size = 75;
			base.layout();
		}
 
	}
}
  • New Guy

    ouch my head still hurts … will it only work on playbooks, none other than that ? I know it may sounds stupid for most of the people, but honestly it still confuses me :D

  • http://blog.digitalbackcountry.com Ryan Stewart

    I should maybe have been clearer on that. This is specifically related to the QNX components that are part of the PlayBook SDK. So right now it only works on PlayBook but hopefully in the future they’ll port it to other RIM devices.

  • Tom

    Thanks Ryan, this video really helped me out. Still getting my head around flex and determined to get out a playbook app before launch.

  • http://twitter.com/_robfox Rob Fox

    This is pretty common in Java. Would you suggest any kind of an all-around AS3 layout library?

  • http://blog.digitalbackcountry.com Ryan Stewart

    Rob, I’ve always just used Flex so I’m not as up to speed on the AS3 layout libraries as I should be. I’ll do some checking though.