Creating a Custom Layout Class in Flex 4

So apparently I'm giving a week long series on getting started with Flex 4. I would have titled my content as such, but I guess I wasn't sure if I would have learned enough to provide a week's worth of content. Let's give it a shot anyway.

As I briefly touched upon in yesterday's post, layout is handled in new layout classes in Flex 4. Let's dive in to making a simple, custom layout manager.

I'm just going to go through a simple example. All layouts need to implement the flex.intf.ILayout interface, which only needs to implement a getter and setter called target and two functions: measure and updateDisplayList.

Here is a simple layout we'll call DumbDiagonalLayout:

com.smartlogicsolutions.flex.layout.DumbDiagonalLayout.as

package com.smartlogicsolutions.flex.layout {

    import flex.core.Group;
    import flex.intf.ILayout;
    import flex.intf.ILayoutItem;
    import flex.layout.LayoutItemFactory;

    public class DumbDiagonalLayout implements ILayout {

        /* --- Variables --- */

        private var _target:Group;
        private var _hGap:Number;
        private var _vGap:Number;

        /* === Variables === */

        /* --- Constructor --- */

        public function DumbDiagonalLayout() {
            _hGap = 20;
            _vGap = 30;
        }

        /* === Constructor === */

        /* --- Functions --- */

        public function measure():void {}

        public function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void {
            var layoutTarget:Group = target;
            if(!layoutTarget)
                return;

            var layoutItemArray:Array = new Array();
            var count:uint = layoutTarget.numLayoutItems;
            var nextX:Number = 0, nextY:Number = 0;
            for(var i:uint = 0; i < count; i++) {
                var layoutItem:ILayoutItem = LayoutItemFactory.getLayoutItemFor(layoutTarget.getLayoutItemAt(i));
                if(!layoutItem || !layoutItem.includeInLayout)
                    continue;
                layoutItem.setActualPosition(nextX, nextY);
                nextX += _hGap;
                nextY += _vGap;
            }
        }

        /* === Functions === */

        /* --- Public Accessors --- */

        public function get target():Group { return _target; }

        public function set target(value:Group):void { _target = value; }

        /* === Public Accessors === */

    }

}

This will simply layout subsequent children spaced _hGap in the horizontal direction and _vGap in the vertical direction. To use this layout we just need to set an attribute in our container class. Since our layout class is dumb, we also need to explicitly set the width and height on each component in the container.

DiagonalButtons.mxml

<?xml version="1.0" encoding="utf-8"?>
<Application xmlns="http://ns.adobe.com/mxml/2009"
             layout="com.smartlogicsolutions.flex.layout.DumbDiagonalLayout"
             backgroundColor="blue">

    <Button label="Button 1" width="80" height="20" />
    <Button label="Button 2" width="80" height="20" />
    <Button label="Button 3" width="80" height="20" />
    <Button label="Button 4" width="80" height="20" />
    <Button label="Button 5" width="80" height="20" />
    <Button label="Button 6" width="80" height="20" />
    <Button label="Button 7" width="80" height="20" />

</Application>

Compile this and you should see:

 

No promises whether I'll get to another example tomorrow, but we'll see...