Unexpected scroll results with HBox/VBox/Containers using percent height/width

The objective:

The screen grab below is taken from a Flex application I’m building. This page of the app comprises of 2 VBoxes inside an HBox. The 2 VBoxes need to size to 100% of the height of the HBox container. The user can edit any of the text fields. When the user edits the body text of the left column, if they use up all the vertical space of that left VBox then I’d like the VBox containing the title and the boy text to create scroll bars, not to resize it’s parent VBox. Simple right?

Not so simple… Here’s a snippet of the code:

<mx:VBox width=”50%” height=”100%” styleName=”whiteContainer”>

<mx:Box direction=”vertical” width=”100%” height=”100%” styleName=”scrollableContentWithText” >
<mx:HBox width=”100%” verticalAlign=”middle”>
<mx:Image source=”assets/images/book74x42.png” width=”74″ height=”42″ />
<controls:AdvancedTextArea id=”title1″ multiline=”false” textModify=”captialize” styleName=”whiteContainerHeader” condenseWhite=”true” width=”100%” prompt=”{resourceManager.getString(‘resources’,’ENTER_TEXT_PROMPT’).toUpperCase()}” />
</mx:HBox>
<controls:AdvancedTextArea id=”body1″ styleName=”blueOnWhiteText” condenseWhite=”true” width=”100%” prompt=”{resourceManager.getString(‘resources’,’ENTER_TEXT_PROMPT’)}” />
</mx:Box>
</mx:VBox>

And here are the results when that body text gets too deep for the VBox:

So the whole parent HBox ended up getting stretched. Not the results I expected.

The solution as it turns out is pretty straight forward. The VBox containing the left column needs it’s minHeight and minWidth properties set to 0! The reason is that with containers using percentage based sizing flex sets the min height and min width properties to the cumulative width and height of the container’s children components. So in my example as the editable text component gets deeper/taller this automatically increases the minHeight property of it’s parent container.

So by explicitly setting the parent container’s minHeight and minWidth to 0:

<mx:VBox width=”50%” height=”100%” styleName=”whiteContainer”>
<mx:Box direction=”vertical” width=”100%” height=”100%” minHeight=”0″ minWidth=”0″ styleName=”scrollableContentWithText” >
<mx:HBox width=”100%” verticalAlign=”middle”>
<mx:Image source=”assets/images/book74x42.png” width=”74″ height=”42″ />
<controls:AdvancedTextArea id=”title1″ multiline=”false” textModify=”captialize” styleName=”whiteContainerHeader” condenseWhite=”true” width=”100%” prompt=”{resourceManager.getString(‘resources’,’ENTER_TEXT_PROMPT’).toUpperCase()}” />
</mx:HBox>
<controls:AdvancedTextArea id=”body1″ styleName=”blueOnWhiteText” condenseWhite=”true” width=”100%” prompt=”{resourceManager.getString(‘resources’,’ENTER_TEXT_PROMPT’)}” />
</mx:Box>
</mx:VBox>

… I ended up with the desired result:

How to make a custom Flash Preloader for a Flex Application

There are a number of useful Flex techniques I use in the Flex Apps I develop all the time and I thought that some of these might be useful for others. So here’s the first… How to replace that nasty default Flex preloader with your own Flash animated version. Here’s the result (I just downloaded a free preloader animation from the web and applied it to this tutorial:

https://www.nickkuh.com/demos/custom_preloader/

Flex source files can be downloaded from here:

https://www.nickkuh.com/demos/custom_preloader/srcview/CustomPreloader.zip

How it works:

Inside the main application MXML you can specify a custom preloader class for your application to use:

<mx:Application xmlns:mx=”http://www.adobe.com/2006/mxml”
layout=”vertical”
backgroundColor=”#000000″
backgroundGradientAlphas=”[0.0,0.0]”
paddingTop=”30″
applicationComplete=”init()”
preloader=”com.nickkuh.preload.Preloader”  viewSourceURL=”srcview/index.html”>

So you’ll see I’m pointing the preloader to my com.nickkuh.preload.Preloader class. This class extends the default Flex DownloadProgressBar class: mx.preloaders.DownloadProgressBar. The Flex Framework passes the application it’s loading to preloader setter method which I’m overriding:

override public function set preloader(value:Sprite):void{
value.addEventListener(ProgressEvent.PROGRESS, progressEventHandler, false, 0, true);
value.addEventListener(Event.COMPLETE, completeEventHandler, false, 0, true);
value.addEventListener(FlexEvent.INIT_PROGRESS, initProgressEventHandler, false, 0, true);
value.addEventListener(FlexEvent.INIT_COMPLETE, initCompleteEventHandler, false, 0, true);
}

So my custom Preloader class is now able to listen to the application preloading events – halfway there…

In the constructor for the Preloader class I’m creating an instance of another custom class which deals with displaying the Flash loading animation and adding this instance to the stage:

progressBar = new ProgressBar;
this.addChild(progressBar);

The Preloader class listens to the instance of the com.nickkuh.preload.ProgressBar class for the custom event ProgressBar.FADE_OUT_COMPLETE. Only when that event is fired will the Preloader class in turn fire an Event.COMPLETE event which the Flex app listens for before it displays the loaded application and fires the applicationComplete event. So this set-up enables the custom ProgressBar to control when the Flex app changes the view from preloader to application.

The custom ProgressBar class extends Flex’s Loader class and loads in the flash loading animation. I’ve set this up so that the ProgressBar checks for the path to the preloader.swf via FlashVars:

var url:String;
if (this.stage.loaderInfo.parameters.hasOwnProperty(“preloaderURL”))
{
url = this.stage.loaderInfo.parameters.preloaderURL;
}
else
{
url = “preloader.swf”;
}
var urlRequest:URLRequest = new URLRequest(url)
this.load(urlRequest);

You’ll find the fla for the preloader in the source files in a folder called ‘design’. The fla actually includes a couple of methods on frame one:

stop();

function setProgress(n:Number)
{

}

function set ready(b:Boolean)
{
if (b) gotoAndPlay(2);
}

The custom ProgressBar class calls these methods with progress updates and sets the ready setter to true when the Flex App has finished loading. If you’re loading animation is a progress bar or needs to give percentage feedback then you can customise the setProgress(n:Number) function – n will be between 0 and 1 – 1 for fully loaded.

In my fla once the preload completes it then plays a few more frames before fading out. This animation could be changed to you requirements.

Once the internal fade out complete the fla fires off an “animationComplete” event which the ProgressBar is listening out for. At this point the closeScreen method of ProgressBar handles the event and ProgressBar fades itself out. Once complete it in turn fires the FADE_OUT_COMPLETE event which causes the main Flex app to close the preloader and display your Flex App.

Yes, it’s a bit time consuming to make a simple preloader but I now use this set-up over and over again. Feel free to do the same!

Regular Expressions in Flex and AS3

I’ve needed to user Regular Expressions a couple of times since they were introduced in ActionScript 3 and invariably find myself trawling the Regular Expression tutorial/example websites out there which in general I find very confusing! I don’t think Regular Expressions are that difficult to grasp (the basic anyway) but none of the example sites I’ve found have clear explanations of the syntax.

I’m currently developing a Crossword Application in Flex for a client which is pretty much complete. However, one of the bugs I had to resolve today was being caused by some unforseen incompatibility issues with the solution text node coming from the client’s huge database of crosswords xml files. If a solution for example had a space, apostrophe, hypen or various other punctionation it needed to be stripped out of the node by my code to ensure that the correct number of cells were generated on my crossword app grid. So here’s an example of using a regular expression to do just that:

var notCharOrNum:RegExp = /[^A-Za-z0-9]/gi;
var myText:String = "The bee’s knees";
myText = myText.replace(notCharOrNum,""); //outputs “Thebeesknees”
trace(myText);

In summary the reg expression means match everything that isn’t either a letter or a number. The ^ bit is the special character than means except these characters. The g means global – I think that just means the match continues searching throughout the string until it reaches the end. The i means case insensitive search so I guess this would do the same thing:

var notCharOrNum:RegExp = /[^a-z0-9]/gi;
var myText:String = "The bee’s knees";
myText = myText.replace(notCharOrNum,""); //outputs “Thebeesknees”
trace(myText);

Yep – just checked and it does!

Flex RIAs can’t call Google APIs

I’ve been looking into ways to access the Google APIs from Flex recently for an Air Project I’m planning to build in my spare time.

I managed to get the following process working fairly easily in AIR:

Step 1: User enters their Google login details which then get passed to google’s https://www.google.com/accounts/ClientLogin API login script which returns a string of variables including the google session authorization variable.

Step 2: Using the Auth variable passed back from a successful google login you can then call the many Google data APIs available – in the example I built after a successful login the app simply retrieves the user’s google contact list.

This all seemed to be working fine in Adobe AIR.

It was when I tried to port this to a web based RIA that I started running into obstacles.

Most of the problems are down to google’s lack of / restictions in their crossdomain.xml

There’s a crossdomain file here:

http://www.google.com/crossdomain.xml

But it doesn’t include the <allow-access-from domain=”*” /> tag  🙁

Plus there’s no crossdomain.xml file on google secure domain https://www.google.com domain which needs to be called to get the authorization variable to access the various APIs.

Even when you run a Flex app locally in a browser you run into further problems if you ever get past the login stage you then need to send the ‘Authorization’ head with “auth=[the_key]” with every API call in the header of you HTTP request.

But guess what? As of flash player 9.0.115 the “Authorization” header was been blacklisted! So it just gets ripped out of the request and the call to google fails!

From reading other posts I understand that you can now use the Authroization header with more recent versions of Flash Player but…

The site you’re calling requires this to be added to the crossdomain file:

<allow-http-request-headers-from domain="*" headers="Authorization"/>

More info from Adobe here:

http://kb.adobe.com/selfservice/viewContent.do?externalId=kb403184&sliceId=2

No – that node doesn’t not exist in Google’s crossdomain file! Lol.

So, my next attempt to get round this obstacle involved downloading Abdul Qabiz’s as3httpclient library for adding headers to your http requests from Flex.

This actually gets round the header issue very well and did allow me to call Google Contacts API request url and include the required Authorization header. Locally that is…

As soon as I then tried to run the working files on my remote web server I saw that for socket calls too (this is how the as3httpclient make requests) also requires a crossdomain.xml for socket calls 🙁

I give up – am just going to stick to building an AIR app where it all just works…