Scaling an Adobe AIR application to fit multiple resolutions and Netbooks

A few months ago, I blogged about a little side project I’m involved in called ChessJam, an online live chess application built with Flex that runs as a desktop application on Adobe AIR.  A few weeks ago, we had some users complain that ChessJam was basically unusable on Netbooks.  Further investigation confirmed that we had selected an application size that was too tall for the typical Netbook 1024×600 resolution.  Oops!

Our WindowedApplication tag was setup as follows:

<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" width="1019" height="680" applicationComplete="init()" ...>

Our first instinct was to rework the UI to eliminate some vertical space.  We also considered making a dramatic change to the artwork to make all backgrounds tileable. Unfortunately, both of these options are very time consuming and since we have “real day jobs”, time is scarce.

A few nights ago, I had a crazy idea….maybe I could simply scale everything.  As an experiment, I changed the WindowedApplication scaleX and scaleY to 80%:

<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" width="1019" height="680" scaleX="0.8" scaleY="0.8" applicationComplete="init()" ...>

Amazingly, everything looked fantastic and scaled nicely (with the exception of the HTML overlaid content which I discuss later in this post)!

I then decided to add a little code to determined how much to scale the app based on the user’s resolution. Here’s the code:

<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" width="1019" height="680" preinitialize="initScreenSize()" applicationComplete="init()" ...>
...
...
			private function initScreenSize():void{
				var thisScreen:Screen = Screen.mainScreen;
				var newScaleX:Number = thisScreen.visibleBounds.width / 1019 * 0.98;
				var newScaleY:Number = thisScreen.visibleBounds.height / 680 * 0.98;
				var newScale:Number = Math.min(newScaleX,newScaleY,1);
				this.scaleX = newScale;
				this.scaleY = newScale;
				this.height = this.height * newScale;
				this.width = this.width * newScale;
			}
...
...

Here’s a walkthrough of the code:

  • Line 1: All of this needs to happen before anything is displayed, so I use the preinitialize event to trigger my initScreenSize() method.
  • Line 5: Using the AIR screen API, I grab the main screen (Tour de Flex has some additional samples using the screen API)
  • Line 6 and 7: Using the visible width and height of the screen, determine what the new width and height should be proportionally. I added the “0.98” factor so that the app doesn’t fit too tightly. 98% gives it a nice tight margin.
  • Line 8: Because I need to maintain the aspect ratio, I need the lowest scale factor required to make it fit on the screen. If the user has a very large screen, the scale factor will be greater than 1.0. I don’t want to scale the app larger than the original size so I added “1” to the list of values to consider. This guarantees that I will never scale larger than the original size.
  • Line 9 and 10: Set the scaleX and scaleY to my new computed scale factor
  • Line 11 and 12: Set the new application height and width

To see the results, check out a full-resolution triple-screenshot by clicking the image below:

The largest image is the original 1019×680 app (scaleX/scaleY=1.0). The other two images are scaled for smaller resolutions. Notice that the graphics, fonts, etc. scaled nicely.

There is a catch to this if you are using any HTML in your application with the mx:HTML component:
All of the Flash content scales nicely, especially since we used embedded scalable fonts. However, our app also utilizes HTML overlays for some of the dynamic content. Notice the signs hanging on the doors in the screenshot above. Those signs are actually loaded into a transparent mx:HTML control (I blogged about this a few months ago here). The HTML content looked horrible because the HTML is rendered first, then it’s scaled, so I was seeing the results of image scaling of my text. At first I thought this might be the end of my brainstorm, but, later that night, I had a crazy idea… the kind of idea you only get after 2am: 🙂

This sounds nuts, but, I scaled the HTML control to the inverse of the application scaling which basically puts it back to full-scale. For example, if my app is scaled to 0.8 (80%), I scale the HTML control to 1/0.8 = 1.25. I then took advantage of a new CSS3 zoom property and set it to 80% in my CSS:

<style>
body {
   zoom: 80%;
}
</style>

Confused?   Basically, I let AIR scale the Flash content and I let CSS scale the HTML content. The results are not perfect, but it’s darn close.

IMPORTANT:  The CSS zoom property is part of CSS3 which requires AIR 2.0.  It will NOT work with AIR 1.5.x.  Our app has a version check of AIR before it does the scaling.  Since AIR 2.0 is going to be available very soon, it’s a short-term issue.

Our latest release is now “netbook friendly” without changing any artwork. I even tested it at 640×480 and it looks great!

Our next challenge is to make sure that everything is touch-friendly so it will run nicely on a tablet.  I don’t expect this to be much of a challenge.  The real challenge is getting my hands on a nice test tablet!

~ by gregorywilson on May 6, 2010.

7 Responses to “Scaling an Adobe AIR application to fit multiple resolutions and Netbooks”

  1. […] Scaling an Adobe AIR application to fit multiple resolutions and Netbooks « Greg Wilson's… […]

  2. […] Direct Link […]

  3. […] http://gregsramblings.com/2010/05/06/scaling-an-adobe-air-application-to-fit-multiple-resolutions-an… « « Previous Post: Dow falls almost 1000, recovers 600 […]

  4. Hi,

    1) Do you think that this will work also in the opposite way (to auto-scale everything up including fonts)?.

    2) What can you recommend to do with bitmaps in case of rescaling to a higher resolution?.

    Thanks

    • Yeah – it should scale up the same way. Increasing font size will not be as bad as decreasing, but it will probably look better to have the CSS scale the fonts instead of doing bitmap scaling.

      Thanks!

      Greg

  5. i get double the shrinking
    one with the scaleX and scaleY and again with the width/height change

    dont you?

  6. Hi Greg,

    Can’t Thank you enough for this post. Came in real handy. 🙂

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
%d bloggers like this: