Programmatically resizing a Flex HDividedBox container

The following example shows how you can programmatically resize an HDividedBox container in Flex using the moveDivider() and getDividerAt() methods.

Full code after the jump.

View MXML

<?xml version="1.0" encoding="utf-8"?>
<!-- http://blog.flexexamples.com/2007/10/09/programmatically-resizing-a-flex-hdividedbox-container/ -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
        layout="vertical"
        verticalAlign="middle"
        backgroundColor="white">

    <mx:ApplicationControlBar dock="true">
        <!-- Move the divider 20 pixels to the left for as long as the
             Button control is pressed (autoRepeat=true). -->
        <mx:Button label="x-=20"
                autoRepeat="true"
                buttonDown="hdivbox.moveDivider(0, -20);" />
        <!-- Move the divider 20 pixels to the right for as long as the
             Button control is pressed (autoRepeat=true). -->
        <mx:Button label="x+=20"
                autoRepeat="true"
                buttonDown="hdivbox.moveDivider(0, 20);" />

        <mx:Spacer width="50" />

        <!-- Move the divider to 100 pixels from the left. -->
        <mx:Button label="x=100"
                click="hdivbox.getDividerAt(0).x = 100;" />
        <!-- Move the divider to 420 pixels from the left. -->
        <mx:Button label="x=420"
                click="hdivbox.getDividerAt(0).x = 420;" />
    </mx:ApplicationControlBar>

    <mx:HDividedBox id="hdivbox" width="100%" height="100%">
        <mx:VBox backgroundColor="haloGreen" width="100%" height="100%">
            <!-- children -->
        </mx:VBox>
        <mx:VBox backgroundColor="haloBlue" width="100%" height="100%">
            <!-- children -->
        </mx:VBox>
    </mx:HDividedBox>

</mx:Application>

View source is enabled in the following example.

In the previous example, the moveDivider() method is used to move the divider relative to its current position. So, calling moveDivider(0, 20) moves the first (and only) divider 20 pixels to the right. To move the divider 20 pixels to the right, you’d pass a negative value for the second parameter, like so:

moveDivider(0, -20)

To set the divider to a specific point, you can use the getDividerAt() method and set the divider’s x property (for a horizontal divided box, if you were using a vertical divided box you would set the y property instead). So again in the previous example, you would use the following code to set the first divider to 100 pixels from the left edge:

hdivbox.getDividerAt(0).x = 100;

If you wanted to force the nested VBox containers to have a minimum or maximum width, simply set the minWidth and/or maxWidth properties, as seen in the following snippet:

<mx:VBox backgroundColor="haloGreen"
        width="100%"
        height="100%"
        minWidth="50"
        maxWidth="250">
    <!-- children -->
</mx:VBox>

Now when you resize the HDividedBox container’s divider, the green VBox container will be at least 50 pixels wide and at most 250 pixels wide.

19 thoughts on “Programmatically resizing a Flex HDividedBox container

  1. rconceiver,

    Try something like this:

    <mx:Resize id="resizeEffect" />
    ...
    <mx:VBox backgroundColor="haloGreen" resizeEffect="{resizeEffect}" width="100%" height="100%">
    

    Seems to work OK for dragging, but it is a bit quirky if you hold down the “+20” or “-20” buttons (if that sort of thing matters to you).

    Peter

  2. Hhmm, there also seems to be a liveDragging property on the HDividedBox which works well for dragging, but seems to have conflicts with the resizeEffect trick/hack.

    Peter

  3. Is there any way to control make the drag snap-to an interval? I want to do something like the slider where I set up, say, 50px intervals that the divider can move to. The example you provide on the button…

    moveDivider(0, -20)

    …is exactly the kind of effect I am looking for. Only I would like this to happen onDrag instead of onButtonClick. I’ve played around with the Divider Events but haven’t gotten very far.

    Any idea? Many tahnks in advance!

    -Ted

  4. Sorry for the poor wording…

    >> “Is there any way to control make the drag snap-to an interval?”

    This should say — Is there any way to make the Divider snap-to an interval onDividerDrag?

    :-)

  5. I am running into an issue with programmatically setting the divider positions of an HDividerBox that has had children dynamically added to it. If you take the example above and add this method as a handler to creationComplete on the application you will see the issue:

    import mx.controls.Label;
    import mx.containers.VBox;
    
    private function init():void
    {
      var newChild:VBox = new VBox();
      newChild.percentHeight = 100;
      newChild.percentWidth = 100;
    
      var label:Label = new Label();
      label.text = "HELLO";
      newChild.addChild( label );
      hdivbox.addChild( newChild );
    
      hdivbox.getDividerAt(0).x = 50;
      hdivbox.getDividerAt(1).x = 400;
    }
    

    What you end up with is that the first divider get’s positioned correctly, but the second divider does not. If I don’t set the dividers at all, they are all layed out with equal sizes. The issue seems to be due to the fact that the container needs to finish updating due to the addition of the new child before we can move the second divider.

    I tried working around it by adding a listener that does the repositioning on the divider after the UPDATE_COMPLETE event on the dividedbox and then removes itself, but it doesn’t work consistently for multiple children.

    I am wondering if you have run into this issue before and come up with any solutions?

  6. Kelly Davis,

    Try changing your code to something like this:

    private function init():void {
        var newChild:VBox = new VBox();
        newChild.percentHeight = 100;
        newChild.percentWidth = 100;
        newChild.setStyle("backgroundColor", "red");
    
        var label:Label = new Label();
        label.text = "HELLO";
        newChild.addChild( label );
        hdivbox.addChild( newChild );
    
        callLater(resizer);
    }
    
    private function resizer():void {
        hdivbox.getDividerAt(0).x = 50;
        hdivbox.getDividerAt(1).x = 400;
    }
    

    Peter

  7. Interestingly, I added the resizer call to a button click. The first time I click the button and trigger resizer() I get the same behavior. If I click it again, then it works. So it looks like after adding the new child to the HDividedBox puts the container into a state that causes getDividerAt().x = ? to not work correctly.

  8. I think I resolved this issue (sort of). I was overlooking the simple fact that if you want to set the initial state of the dividers, all you have to do is set the widths or heights of the child containers to what you need them to be, instead of calling the moveDivider() method.

  9. Hi,
    I was wondering is there a way to change the width/height of the DividedBox’s Divider? The Divider is approx. 10 pixels thick and I’d like to make it thinner but it seems there is no style for that, except dividerThickness which only applies to the line when the user drags the Divider. Changing the skin doesn’t change anything either.

  10. @sascha/hdrs
    I was wondering is there a way to change the width/height of the DividedBox’s Divider?

    horizontalGap=”6″

  11. Peter,

    You code example got me started in solving my problem. Below is a code snippet solution to remember the previous Flex session’s HDividedBox location. I believe must users would want the location of the screen splitters remembered.

    public var _preferences:SharedObject;
    private var _currentSplitterLocation:int;
    
    // Get the location of the splitter when the Flex app first starts.
    private function creationHandler(event:Event):void {
        _userPreferences = SharedObject.getLocal(”preferences”);
    
       // Get the current location of the HDividedBox at startup
        _currentSplitterLocation = myDivider.getDividerAt(0).x;
    
    }
    
    // Called when a divider is moved. Add onRelease event to HDividedBox control
    public function dividerDragComplete(event:DividerEvent):void {
       // Update the current location of the splitter.
       _currentSplitterLocation += event.delta;
       // Save it to to the shared object.
       _userPreferences.data.divider = _currentSplitterLocation;
    }
    
    // Called to load the last sessions divider location from shared object
    public function loadDividers():void {
       if(_userPreferences.data.divider !=null) {
          myDivder.getDividerAt(0).x = _userPreferences.data.divider;
       }
    }
    

Comments are closed.