Posts tagged "scaling"

Using Bitmaps in Flex Mobile Projects

Bitmap image assets typically only render optimally at the resolution for which they are designed. This limitation can present challenges when you design applications for multiple resolutions. The solution is to create multiple bitmaps, each at a different resolution, and load the appropriate one depending on the value of the application’s runtimeDPI property.

The Spark BitmapImage and Image components have a source property of type Object. With this property, you can pass a class that defines which assets to use. In this case, you pass the MultiDPIBitmapSource class to map different sources, depending on the value of the runtimeDPI property.

The following example loads a different image, depending on the DPI:

<s:Image>
  <s:source>
    <s:MultiDPIBitmapSource
      source160dpi="@Embed('assets/160.png')"
      source240dpi="@Embed('assets/240.png')"
      source320dpi="@Embed('assets/320.png')"/>
  </s:source>
</s:Image>
<s:Label text="applicationDPI = {FlexGlobals.topLevelApplication.applicationDPI}"/>


Normally, you would take the same content and scale (and/or design) it for each DPI. For clarity, I’ve created 3 different images for each DPIClassification. The source images are shown together here at their full resolution:


When run on a device, the MultiDPIBitmapSource class selects the appropriate asset based on the runtimeDPI, not the applicationDPI. The bitmap itself is present unscaled, even though the application itself may be using application scaling. The 2 photos below show nearly identical applications. The only difference is that the second application labeled “Bitmap Demo Scaling” is using applicationDPI=”160″. You’ll see that in both cases, the correct bitmap is used. And because of the screen DPI of each device, the physical size of each bitmap is approximately the same.

The main point here is that regardless of which scaling strategy you choose, you should always use MultiDPIBitmapSource when displaying bitmaps in mobile Flex projects.

No Scaling. iPod Touch 4th gen, HTC EVO and BlackBerry PlayBook

 

Scaling with applicationDPI="160". iPod Touch 4th gen, HTC EVO and BlackBerry PlayBook

 

Share on Facebook

Comparing CSS Media Queries vs. Application Scaling

If you haven’t heard of either of these features in Flex 4.5, here’s a quick summary:

  • CSS Media Queries - Conditionally apply styles at runtime based on the DPI and/or OS of the target device
  • Application Scaling – When the application specifies an applicationDPI value, Flex applies a scale factor to the root application. The result is an application designed for one DPI value scales to look good on another device with a different DPI value.

The Flex 4.5 reference covers the differences in the two approaches to adapting a mobile application based on DPI. The documentation also spells out the steps it takes to implement each approach.

Testing both approaches is also straightforward. Flash Builder 4.5 can simulate screen resolution and DPI when you run your application in ADL on your PC. However, it’s not the same as seeing the results on an actual device at the real physical size.

I’ve put together some quick examples to demonstrate each approach and I’ve taken a few photos of actual devices to see the final result. I have 3 devices, going left to right:

  • Motorola Droid Pro, 320×480, DPI Classification = 160
  • HTC EVO, 480×800, DPI Classification = 240
  • iPod Touch 4th Gen, 640×960, DPI Classification = 320

The picture below shows 3 different applications:

  1. Application scaling is turned ON (applicationDPI=160) in the main Application tag. What this means is that I’ve designed my application with 160 DPI devices in mind. Flex will scale the entire application by a scale factor based on the runtimeDPI classification. From left to right you can see 1x, 1.5x and 2x scaling.
  2. Application scaling is turned OFF (applicationDPI is not set). At each DPI, I’ve adjusted my slider to a fontSize value that is readable based on the runtimeDPI of the device.
  3. Application scaling is turned OFF (applicationDPI is not set) but I’ve set single explicit fontSize value that is used for all 3 DPI classifications. Do not do this. As you can see, if you set an explicit fontSize for all 3 DPI classifications, you’ll run into issues at one end or the other. In this case, fontSize 16 is far too small on the iPod Touch.

 

What I should have done in the last scenario is define CSS style rules with media queries that select a proper fontSize based on the DPI of the device. I’ll use a simple label as my next example. The code below has scaling turned off, but this time I’ve defined a stylename with different fontSize values per-DPI classification.

In my ViewNavigatorApplication, I’ve turned off scaling:

<s:ViewNavigatorApplication> <!-- scaling is OFF when applicationDPI is not set-->
  ...
</s:ViewNavigatorApplication>

 

And in my View, I’ve defined a stylename with bold and italic styles that apply at all DPI classifications. After that, I’ve defined overrides using CSS media queries. Notice that I only supplied a new fontSize value for 240 and 320. The first rule is applied at all DPIs. I’m able to omit a 160 DPI-specific rule because it gets it’s fontSize style from the first rule.

<s:View>
<fx:Style>
@namespace s "library://ns.adobe.com/flex/spark";
/* applies to all DPIs */
.heading
{
  fontSize: 18;
  fontWeight: bold;
  fontStyle: italic;
}
@media (application-dpi: 240)
{
.heading
{
  fontSize: 28;
}
}
@media (application-dpi: 320)
{
.heading
{
  fontSize: 36;
}
}
</fx:Style>
...
<s:Label text="Heading Style, fontSize={fontSize}" styleName="heading"/>
</s:View>

 

The photo below shows my app running on all 3 devices. The Label with the “heading” stylename shows the correct DPI-specific fontSize on all 3 devices.

Share on Facebook