views:

250

answers:

7

Just wondering if anyone knows of an example out there, or class I can add to my app that would perform like a VBox but with 2 or more columns?

I'm adding items to a VBox from a loop, and that works fine, but I want to have it split into two columns:

 _________________
|        |        |
| Item 1 | Item 2 |
| Item 3 | Item 4 |
| Item 5 |        |
|________|________|

For now I'm just going to set 2 VBoxes side by side and assign odd items to one, and even to the other, but it would be nice to have a control do this automatically.

EDIT
Please stop giving me work arounds. I already have a functional work around. But if you have already written a class that does this, or know where I can find one online I would really appreciate it. Thanks

A: 

put them in an HBox?

kajyr
see my little diagram, I don't want them laid out all horizontal, I want two vertical columns
invertedSpear
I thought you wanted to lay horizontal two vertical columns.
kajyr
A: 

You could use a VBox containing an HBox for each row and simply populate each HBox with 2 items, something like:

var vb:VBox;
var array_of_items:Array;

for(var i:int = 0; i < array_of_items.length; i+=2)
{
var hb:Hbox = new HBox();
hb.addChild(array_of_items[i]);
hb.addChild(array_of_items[i+1]);
vb.addChild(hb);
}

DTJon
That's similar to what I'm already doing, but a great code example of how to do it :-) I was just hoping to do it in one component. Problem with your example is that my items will vary in length, and using that layout, they will not be in nicely formatted columns without specifically setting some widths.
invertedSpear
A: 

I did something similar to this with an HBox and 2 forms, which lines things up nicely. Dynamically, you could alternate adding children to each form.

adamcodes
Thanks for your input, but as I said I'm already doing that. What I want to know is if anyone has already built a class that does it automatically. I.E. if I do an addChild(item); the class handles the rest.
invertedSpear
A: 

Why not just use the Tile Container, and set the direction property to your required flow direction?

Zaren
Because I don't want tiles, I want a 2 column list that has 3 radios and a label, which I am able to make with 2 VBoxes, side by side, that are fed children in parody. I just want a class that does this for me, so I can just feed one container the children and it handles putting them into 2 columns.
invertedSpear
I'm currently using the Tile container to render a collection of HBoxes in the exact layout type you describe. Which is why I suggested it.
Zaren
A: 

I had a similar problem myself. This is what I ended up using:

package {
    import mx.containers.HBox;
    import mx.containers.VBox;
    import mx.events.FlexEvent;

    public class MultiColumnVBox extends HBox {
        // public properties
        public var columnWidth:int;
        public var verticalGap:int;
        public var adjustForScrollbar:Boolean;

        public function MultiColumnVBox() {
            super();
            this.addEventListener(FlexEvent.CREATION_COMPLETE, rearrangeChildren);
        }

        private function rearrangeChildren(evtObj:FlexEvent):void {
            // height will change whilst rearranging children, as will the Children Array
            // we store them once at the start
            var myHeight:int = this.height;
            var children:Array = this.getChildren();

            var lastIndex:int = 0;
            var vBoxIndex:int = 0;
            var vBox:VBox;
            var totalHeight:int = -this.verticalGap + (this.adjustForScrollbar ? 16 : 0);

            for(var i:int=0; i<children.length; i++) {
                // resize each child and measure the height
                // if you don't want it resized to the columnWidth, set the maxWidth property
                children[i].width = this.columnWidth;
                children[i].validateSize();
                totalHeight += children[i].measuredHeight + this.verticalGap;
                // if we're too tall, or we've reached the last element, move them into a VBox
                if(totalHeight > myHeight || i == children.length-1) {
                    vBox = new VBox();
                    vBox.setStyle("verticalGap", this.verticalGap);
                    vBox.width = this.columnWidth;
                    // include last child if there is room
                    for(var j:int=lastIndex; j<(totalHeight > myHeight ? i : i+1); j++) {
                        vBox.addChild(children[j]);
                    }
                    this.addChildAt(vBox, vBoxIndex);
                    vBoxIndex += 1;
                    lastIndex = i;
                    totalHeight = -this.verticalGap + (this.adjustForScrollbar ? 16 : 0);
                }
            }
        }
    }
}

The end result is slightly different, however. Instead of moving children to alternating columns, it fills the height of the first column, then the second, then the third, etc. indefinitely.

If you plan on making your our Class, as you said, a similar approach should work: waiting for the CREATION_COMPLETE event, and then rearranging the children into two VBox controls.

Mike Tryczak
I brought in your class and tried to run it with this but it didn't work, any idea? "<?xml version="1.0" encoding="utf-8"?><mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" xmlns:myComponents="myComponents.*"> <myComponents:MultiColumnVBox id="testTwoColVB"> <mx:Label text="ABC" /> <mx:Label text="ABC" /> <mx:Label text="ABC" /> <mx:Label text="ABC" /> <mx:Label text="ABC" /> <mx:Label text="ABC" /> <mx:Label text="ABC" /> </myComponents:MultiColumnVBox> </mx:Application>"
invertedSpear
+1  A: 

flexlib (http://code.google.com/p/flexlib/) has a lovely FlowContainer container control that will do exactly what you need.

John McCann
From the website, however, it appears flexlib is no longer being supported. It's a great set of libraries, but I've seen problems when using it with the latest SDK (3.5).
bedwyr
A: 

I think Tile container with direction="horizontal" will do it

kike