6 September 2011
Over the past few months I have been working on a mobile application named Finicky. One of the points of the project was to create a mobile application that did not look like other mobile applications. Specifically, most mobile applications share a similar look and feel that tends to look minimalistic, futuristic and sleek. There is nothing wrong with that look, but I wanted to see if something different could work. For my project I wanted something organic, maybe a little grungy, and not polished to a high-gloss shine.
To accomplish this using my technology of choice, Adobe Flex, it meant a lot of skinning, CSS manipulation, and font selection. It also meant working with a designer, being clear in what I wanted, and dealing with variably sized screens. In short, it was very different then other projects I've worked on, and I wanted to share what I learned.
So what is Finicky? It's is a mobile journaling application to record and later search out locally available items. I travel a lot, I have specific tastes, and it's hard to track down some of them. When I do track them down, I'd like to be able to find them again. Case in point: I like Coke Zero, which isn't necessarily in every store. When I travel, and I find Coke Zero in a store, I mark it down. Next time I'm in town, I use Finicky to locate where I found it in the past.
The first thing I had to do to get this application looking the way I wanted was to enlist the aid of a design shop. This meant wireframing the application to ensure I knew what all of the screens should be. Additionally, I searched out some graphical elements that inspired me—not to handcuff the designer, but to make sure when I said "organic," he or she knew I meant textures like "aged paper, leather book covers, and handwriting" and not "green meadows, liquid water, and flowery script."
When you enlist a designer, you have to tell the designer what you want: what screens, what devices it will run on, what UI elements to expect, and what screen resolution to target. I made a few decisions here to affect my choices.
To those ends, I requested a design that was 960px high by 640px wide (iPhone 4's screen size) but that was designed to work without iOS's default UI, including navigation bars. The idea was that it would be easier to bolt on those default pieces after designing the Android version than it would be to build Android UI from scratch after designing it to be an iOS app. In retrospect, this worked great, once I had come to terms with two ideas:
As you can see by comparing Figures 1 and 2, the Android version has a custom header and requires you to use the hardware buttons to toggle between list views and map views of your data. The iOS version required me to use tabs to make that switch, and to use the iOS default navigation bar. Those two items took up the extra space my app filled with that custom banner, so I had to remove it.
One of the hardest parts of getting a multidevice application skinned was dealing with all of the screen sizes. In order to do so, I took a page from my web development skills. In short, I abandoned being pixel-perfect to the design composition. Instead, I focused on making the design composition resize and lay out slightly differently throughout the application. I took two strategies when skinning Flex components:
Fixed-size elements were usually things that were interactive parts of the UI. For my app, that meant buttons and text inputs; but I can see this applying to anything a user has to use or manipulate. Variable-size elements were, by and large, decorative or background elements.
The prevailing idea here seems to be that if a user is going to touch it, then you have to take steps to ensure that it isn't going to resize to something too small. Also, you have to ensure that a UI element doesn't expand to be comically obvious and draw all attention to itself. The most reliable way to do that is to set a fixed size. If you find that your UI element doesn't work in all conditions, then I recommend creating a couple of skins that can handle several specific sizes.
A case in point is shown in Figures 3 and 4. Both show a button on the same device. Both have the same hand-drawn design; however, one button has been designed to be a much different size than the other. Both have their own source images. Selecting a particular skin sets the size.
On the other hand, background graphics tend not to be as important. They are conveying look and feel, but you never have to worry about a user not being able to select an background image. Consequently, I used scaling on a few of my background graphics.
Figures 5 and 6 show the difference between a banner appearing on a Motorola Atrix and an HTC Insipre. They differ by 100 pixels in width. The buttons are hard-set in size; the banner scales by width, but height is hard-set. The resulting effect creates a banner that fills up exactly the whole screen. The less-wide version, while a little scrunched, doesn't show any visual distortion.
The biggest pitfalls I ran into in designing this application was not paying attention to published best practices for skinning mobile applications. Jason San Jose has a great series on these. Also, Evtim Georgiev and Steven Shongrunden have a great presentation about increasing the performance of your applications, which has impact on what components you choose. See the links under "Where to go from here."
You owe it to yourself to read what the others have said about performance, but to sum up through the filter of my application:
Read the source code of the mobile spark skins, and emulate what you see there. The great thing about Flex being open-source is that you can see every piece of code for the mobile skins. The Flex engineers that created these mobile skins spend a lot of time with the Framework. They know how to push it around. One of my favorite examples of their creative work comes in their skin for a button. The default button consists of a pressable shape with some text on it. That text has what appears to be a drop shadow on it; however, the drop shadow filter is a little expensive on mobile, so what it actually is is a copy of the text in a darker color, a pixel or two offset from the original. It's those sorts of tweaks that you can see by looking at the source.
Never use an <s:Image when an <s:BitmapImage will do. The Spark Image class does a lot for you. It can load images dynamically, dynamically size them, and much more. That functionality comes at a performance cost. The BitmapImage Primitive, on the other hand, cannot do all that—in fact, it is limited to loading images that are embedded in your application—but it is shockingly more efficient. It's likely that you will be embedding your skin graphics anyway, so using these is no burden. The only challenge is that they cannot be added to components as children. The solution is to create a Group that will hold the image, add that Group to the component, and then add the BitmapImage as an element of the Group.
Get it on hardware as soon as possible. The desktop preview in Flash Builder runs your application with all of the power of a desktop behind it. Mobile devices don't have that sort of horsepower. The sooner you preview it on real hardware, the sooner you'll see performance issues and be able to go after them.
If you aren't using it, don't hide it, rip it out. The iOS version of my application doesn't use some UI components that I had designed for Android. When I first started porting my Android version of the application to iOS, I set their visibility to false. They were all still there, but they were not visible. They were also terribly slow. I got very worried about this and started a new fork of the code base, ripping out all of the Android-only components. Performance shot up.
Several different technology solutions exist for creating applications for multiple mobile devices from one code base. One of the major advantages of Flex is that it is fairly easy to skin. That is an incredible advantage. It can also be the source of some headaches if you aren't mindful of performance. By following a few best practices, you can easily make highly-stylized, high-performing apps that people don't have to use, but that they want to use.
This work is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License. Permissions beyond the scope of this license, pertaining to the examples of code included within this work are available at Adobe.