Tuesday, October 18, 2011

Focus Flex App on start up


When a flex application loads it doesn't actually have focus until the user clicks on it.

So even though you can call setFocus() on a TextInput or Button and visually it appears that your control has focus (blue border), if you try to type you'll notice that nothing happens. This can be quite frustrating for a user.

One way to solve this is to edit the html file that loads your application (e.g. the index.template.html), and call the JavaScript focus() function on the flash element. I found this website explains it quite nicely:
http://www.appfoundation.com/blogs/giametta/2007/07/09/internet-explorer-setting-focus-on-flex-apps-flash-player/.

If for prefer to keep all your code in ActionScript you can accomplish the same thing by doing this:
 ExternalInterface.call("function() { var app = document.getElementById('"+id+"'); app.tabIndex = 0; app.focus(); }");

I usually put that line of code inside my applicationComplete event handler.

One other thing to note is that if you call setFocus on a component that isn't finished being initialized it won't always work. For best results call setFocus() in a creationComplete event handler.

I added the app.tabIndex = 0 after finding that the focus didn't work on Safari. This came from stackoverflow.

Tuesday, October 11, 2011

FXG Scale Grid

When working with FXG an important concept to understand is the Scale Grid. The scale grid determines how your FXG graphic scales. If your FXG element is used without an explicit width or height (e.g. <fxg:rounded_box/>) then the scale grid is not used. But if for example you define your FXG to have a width of 200 pixels and then in your MXML you use the FXG element and set its width to "100%" (e.g. <fxg:rounded_box width="100%"/>) or something other than 200 you'll see the graphic get scaled. The scale grid becomes important when you want to preserve aspect ratios (e.g. on rounded corners).

Here is the typical example used to illustrate the problem:

Here is the FXG source code (rounded_box_scale9.fxg) used to create this graphic. Notice the scaleGridLeft, scaleGridTop, scaleGridRight, and scaleGridBottom properties, these are what control the scaling.
<s:Graphic xmlns:s="http://ns.adobe.com/fxg/2008" version="2.0" 
	scaleGridTop="20" scaleGridLeft="20" scaleGridRight="130" scaleGridBottom="21">
	
	<s:Rect height="41" width="150" radiusX="20">
		<s:fill>
			<s:LinearGradient rotation="90">
				<s:GradientEntry color="#FFFFFF"/>
				<s:GradientEntry color="#C0C0C0"/>
				<s:GradientEntry color="#FFFFFF"/>
			</s:LinearGradient>
		</s:fill>
		<s:stroke>
			<s:SolidColorStroke color="#AAAAAA" weight="2"/>
		</s:stroke>
	</s:Rect>
	
</s:Graphic>

And here is the associated MXML (the rounded_box fxg doesn't have the scaleGrid properties):
<s:VGroup x="10" y="10" gap="10">
	<fxg:rounded_box/>
	<fxg:rounded_box width="100"/>
	<fxg:rounded_box width="200"/>
	<fxg:rounded_box_scale9 width="100"/>
	<fxg:rounded_box_scale9 width="200"/>
</s:VGroup>

I found this website quite useful in illustrating some of the scale grid limitations: http://www.adobe.com/devnet/flex/articles/mobile-skinning-part1.html.

And here is Adobe's page on FXG:
http://help.adobe.com/en_US/flex/using/WSda78ed3a750d6b8f26c150d412357de3591-8000.html.

But to summarize, here are the limitations I've found with scale grids:
  • Scale grid values must be inside the boundaries of the graphic and must not overlap
    (that is, left boundary < scaleGridLeft < scaleGridRight < right boundary).
  • Scale grids will not work if the graphic contains any Group elements.
  • Scale grids will not work if elements have alpha applied. Instead, apply alpha to the stroke and fill elements.
  • Scale grids will not work with filters (e.g. DropShadow, GlowFilter, etc). Instead add the filters inside the MXML.
I'm sure there are more restrictions, but these are what I've found so far.