the screen size, the font looks good on the iPad on the left and looks way too
small on the. iPod on the ... classifications Flex has 2 strategies for developing for
screen density. The first .... check out my Adobe Developer Center articles. Next
up ...
An hour isn’t a lot of time to cover every topic on multi‐density and multi‐platform authoring. So, my goal for today is to cover the core principles that are built‐in to the Flex SDK and show some simple examples of how to apply these techniques.
1
The fundamental problem with different pixel densities is that they change the physical size of your UI elements. For a given pixel size, a UI element like a button displayed on devices with higher densities will become too small to accurately target with a finger. Let’s look at an example of a 150x40 pixel button. (step through each size)
2
Here’s just a small sampling of phones and tablets and the wide variety of screen sizes, resolutions and DPI values.
3
Especially when it comes to mobile devices, all pixels aren’t created equally. You shouldn’t take exactly the same content and visuals you have in your desktop apps and simply drop them into a mobile app. You can see a lot of bad examples of this, especially on an Android phone when running older, unoptimized Flash content in the browser that was intended for a desktop mouse and keyboard experience. What you have to start to think about is the position and size of any on‐screen element relative to the DPI of the screen. Failure to address screen density will result in applications that look either too big or too small on many mobile devices. (Reference bullets).
4
Here’s a really simple example of where sizing can go wrong quickly. All I’ve done here is set an explicit fontSize in my MXML and I’m running the same application on an iPad at approximately 160 DPI and an iPod 4 at approximately 320 DPI. You can see that relative to the screen size, the font looks good on the iPad on the left and looks way too small on the iPod on the right. So, how does Flex address these issues? (Next)
5
Essentially categorizes mobile devices into 3 different buckets. Think of them as low, medium and high density at 160, 240 and 320 DPI respectively. Based on the 3 classifications Flex has 2 strategies for developing for screen density. The first one is the easiest one: application scaling. You simply specify a target and design for a specific DPI, then Flex will scale your application up or down based on the device. The second option requires more work: density specific skins and styles. With this option, you create (as necessary) graphics and size‐related styles for each skin, and choose the appropriate the correct graphicsand styles based on the DPI.
6
Before we dig into the 2 screen DPI solutions, I want to introduce the tools that we’ll be working with. First is MultiDPIBitmapSource. This MXML component lets you explicitly design 3 different bitmaps to use, one at each DPI. You would use this instead of scaling a bitmap at runtime to avoid scaling artifacts. Next is the applicationDPI property. This is what switches application scaling on and off. It is at the center of all DPI‐based features in Flex mobile projects. And the last tool we’ll look at is CSS media queries. This new CSS syntax allows you to enabled and disable style rules, at runtime, based on the screen DPI and the device OS. The simplest feature
7
The main way we recommend, which should work for most cases, is to use automatic scaling. You turn this on by setting the applicationDPI attribute on your application tag (either Application, ViewNavigatorApplication, or TabbedViewNavigatorApplication). In this example, we’ve set it to 160. This doesn’t mean that our application will only work at 160 DPI. What it means is that the application will apply a scale factor on the X and Y axis and essentially change the screen resolution available to your application when the device does not match the targeted applicationDPI. For example, if you have a 160‐pixel‐wide button in your app (which would be 1” wide at 160 dpi), and you run your app on a 240 dpi device, Flex will scale the whole stage by 1.5x, so your button will now actually be 240 pixels wide on the device. This means that it will stay 1” in width. The net effect of scaling up is that while you have less resolution available, but your entire app is now scaled to look good on the higher DPI screen. Note that because this is applied by scaling the entire app, your code actually isn’t aware of any scaling. If you were to query the width of this button at runtime on a 240 dpi or 320 dpi device, Flex would still report the button’s width as 160. As far as you’re concerned, everything is at 160 dpi, no matter what actual density device you’re running on.
8
Here’s an example of an application with scaling turned off on the left, and on the right is the same application but with scaling turned on. The screen shot on the right is scaling from 160 DPI To 240 DPI. The most obvious way to think about scaling is that pixels grow in size based on the scale factor. When running an application targeted at 160 DPI on a 240 DPI screen, pixels are scaled up by a factor of 1.5. A less obvious way to think about scaling is that the screen dimensions shrink by the scale factor. (animate) You can see on the right that the width of the screen shrinks from 480 to 320. (animate) Also, note that you can still get the actual pixel size of the stage by accessing stageWidth and stageHeight.
9
In summary, to use scaling (talk to bullets) • When applicationDPI is missing, scaling is not enabled • We’ll talk about how bitmaps scale in a few slides
One potential drawback when using scaling is that there can be visual artifacts. When the scale factor is not an integer (for example, when scaling up 1.5 times from 160 to 240), this can cause visual artifacts (in some cases) with vector artwork. This is because Flash aligns strokes on their center. In FXG, a sharp 1px stroke line should start at a half pixel coordinate (0.5,0.5). When this line is scaled up 1.5x to 240 DPI, there will be some subtle blurring of the stroke above and/or below the center of the line.
10
The alternative to scaling is to explicitly tailor skins, graphics and/or styles for each DPI you support in your application. A good example of this technique is the mobile theme included in the SDK.
11
12
13
14
Text and Bitmaps are generally not a concern. Text should not exhibit any artifacts because text is scaled by scaling the font size value rather than scaling the actual vectors. For example, if you use fontSize=16 with a target DPI of 160 on a 240 device, internally, Flash player scales the font to 24. Bitmaps should not exhibit scaling artifacts when using MultiDPIBitmapSource to specify appropriate bitmaps for each DPI. We’ll talk about this feature next. In practice, the Flex team has found only minor visual differences between using 160 DPI skins scaled up to 240 DPI and using 240 DPI skins unscaled. For most applications, this approach should work well, and you can stop reading right here. However, if you find unacceptable visual artifacts form scaling, or have other reasons why you need more detailed control over the behavior of your application at different densities.
15
(A lot of this was covered already. Ok to gloss over this slide and notes and just emphasize bitmaps) Note that in our examples so far, we’ve been targeting 160 dpi and letting the application scale up. This may seem counterintuitive, since it’s usually better to scale down rather than scale up. What we’ve found is that vectors generally scale up better than they scale down. When you scale vectors down, you tend to get artifacts like misalignment. Scaling up generally works well, although you might get some slight blurring of strokes which we’ve covered already. Text scales well in either direction, because when Flash Player/AIR scales text, it doesn’t scale the actual vectors—instead, it just calculates a new font size, and then renders the text directly at that font size. So there’s no artifacting. Bitmaps, however, don’t scale up well, as you know. You might think scaling down would be a better solution, but that has two problems: it tends to blur the bitmap, and it also means that the runtime has to downsample the bitmap, which is an extra performance hit you don’t want on a mobile device.
16
To help with bitmaps, we’ve added a MultiDPIBitmapSource class that you can use anywhere you would ordinarily specify a bitmap source—for example, an Image or BitmapImage source, or the icon of a button as in this example. You simply create different bitmaps for the different densities, and Flex automatically uses the correct bitmap at runtime. It also takes care of transforming the bitmap appropriately while the rest of the application is being scaled so that the bitmap actually shows all its pixels, instead of being downsampled and re‐upsampled or something weird like that. Creating bitmaps for use in a MultiDPIBitmapSource is simple—just figure out how big your icon needs to be at 160 dpi, and then create 1.5x and 2x larger versions for the other densities.
17
Since we just talked about application scaling using applicationDPI, you might be asking: How application scaling interacts with MultiDPIBitmapSource? The answer is, it works exactly as it should. When scaling is in use, Flex selects the bitmap designed for the device’s DPI and applies the correct transforms such that the bitmap appears unscaled. Normally, you would have the same content in each bitmap, but adjusted for more or less detail based on the DPI. For the purposes of this next demo, I’m putting pre‐rendered text for 160, 240 and 320 in the bitmap to show exactly which bitmap is being displayed. It can be confusing to understand the combination of scaling (at the application and in the image).
18
Here are my original bitmaps at full size. I’ve sized the original bitmaps at 320px wide, 480px wide and 640px wide to make the math easier.
19
With scaling turned off, you can see that the MultiDPIBitmapSource selects the correct file. I’ve added some text below the image to show the applicationDPI to verify that scaling is off.
20
Now here’s the same application, but with scaling turned on. If you don’t see a difference from the previous slide, that’s because there’s effectively no difference. When scaling is turned on, the SDK knows how to select the correct bitmap from MultiDPIBitmapSource and also knows how to transform the bitmap to its natural size while the rest of the application is still scaling.
21
For apps that I’ve published personally, I’ve gone with the density‐specific approach as opposed to scaling. I want full control of my graphics and the sharpest edges on my strokes. That wraps up the density‐related features in Flex. There’s other topics that we could cover like a DPI specific splash screen and authoring DPI‐specific FXG graphics. For those topics, check out my Adobe Developer Center articles. Next up are a few tips for handling platform‐specific issues when authoring mobile applications.
22
There are still a lot of desktop users out that that groan when they run into a Flash application or an older Flex 3 web application that obviously doesn’t behave like HTML in a browser. On the other hand, there are a lot of successful, non‐native skinned applications out there like TweetDeck. Success with non‐native UI really depends on design and execution. Other reasons to tweak your design based on the platform are to optionally add a Back button to your UI when not running on Android. Also, as we saw on the last slide, device fonts across platforms have enough nuances that you might want to tweak some parameters for a more consistent look or size. If you choose to add some platform specific changes to your app, you have 2 basic options when coding.
23
Here’s a simple example of how facebook accommodates for Android vs. iOS. Style‐wise, iOS apps use center‐aligned titles, and they use pretty standard gradient parameters in the ActionBar as well. Also notice the style of the buttons in the ActionBar. Android has a flat‐look that’s flush with the edges of the ActionBar while iOS has beveled buttons that look like they’re slightly pushed into the surface. iOS applications typically have just one button in the right‐hand side of the ActionBar. Functionality‐wise, the Android app hides the account button in the menu when you press the menu button.
24
Here’s another example of platform‐specific styling. iOS apps have tabs on the bottom while Android apps typically have tabs on top. Also, notice that there’s a back button at the top of the iPhone app, but the Anrdoid app doesn’t have one since Android phones have a hardware back button.
25
Buttons • On Android, apps can use back, menu and search • On iOS, no hardware button access except volume. Most iOS apps add a back button in the ActionBar when there’s history to go back to. • On PlayBook, swipe down menu Typography • Device fonts at the same size and DPI classification may be less readable Text input • There are unique challenges when dealing with the player’s built‐in TextField on mobile. I don’t have enough time to cover them here, but I will cover them in my session on Friday about creating performant skins and item renderers for mobile applications at 11am pacific time. • One thing I will point out quickly is that on iOS, when editing text in a TextField, this is done completely in a native iOS control. In a demo later, you’ll see that text selection, cut/copy/paste, and the clear button are all present just like a native iOS app. Color depth: Android limited to 16‐bit
26
The screenshot here might not be obvious to everyone. But to be clear, each device has a different default sans serif font. When targeting multiple screen sizes and devices, you should be prepared for some truncation or overflow. This mindset is similar to working with localized strings of various lengths.
27
Now that we’ve discussed some platform specific issues, you might want to add some platform specific logic to your code. You can do this in CSS and in ActionScript. Here’s a CSS example using media queries to wrap a style rule that will only be effective on iOS. (discuss os‐platform values: ios, android, qnx (playbook))
28
In ActionScript, you can use flash.system.Capabilities.version to determine the platform at runtime. (discuss Capabilities.version “IOS” “AND” “QNX”) You can even get more clever and use this technique with MXML states to do platform‐ specific logic using MXML’s declarative markup. There’s a missing 3rd option that I haven’t mentioned yet. Basically, you could create a unique project for each platform you support. You can of course share code between projects, but in the end, each project produces a unique binary that’s only intended for one platform. This way, instead of checking the platform at runtime, you already know your target platform at compile time and when you package and distribute your application.
29
Here’s an example of using CSS media queries to set different styles based on the platform. In this case, for iOS I’m using the ActionBar beveled style to give me iOS‐like buttons. The second rule applies to all platforms. This rule specifies the light blue chrome color.
30
Here’s another example of a custom ViewMenu skin that’s made to look like iOS. Elsewhere in my app, I specified the skinClass for the ViewMenu to be iOS specific. The code I’m showing here adds some different colors on iOS only. Then on Android, I add icons to the ViewMenuItems.
31
The last 2 slides show how you can adapt your application per‐platform if you choose to. It’s not the right solution for everyone. Some customers might prefer a heavily branded experience that’s consistent across devices. Luckily, with Flex skins and CSS, you have the flexibility to do either approach. The last thing I want to show you before I wrap up is an example of how far you can take a native looking theme. Keep in mind this is all using 1 code base and essentially 1 project using CSS media queries and lots of custom skins. The main logic of my application is shared for all platforms.
32
33
34
I just want to point out a few good follow on topics to this skinning session. They’re both on Friday. The first is at 9am pacific. Evtim is the speaker and he’ll be talking about performance in general across mobile and desktop. The second one is at 11am pacific and will be my second session. I’ll talk specifically about performance optimizations that are implemented in the mobile theme skins. I’ll go through, step by step, how to create a mobile‐optimized skin based on the MobileSkin base class. And finally, I’ll talk briefly about performance considerations for item renderers and how to use the built‐in mobile‐optimized item renderers in Flex 4.5
35
36
37
38