Meet the Green Goblin, part 2

December 14th, 2010

Last Friday we announced a significant update to the Android Market client. A whole slew of features went into this update (and many more are to come), and this week the pixel geek in me will be talking about the new visual design of the application. After talking about custom layouts and overlapping non-rectangular components, it’s time to talk about organizing visual information on landscape orientation. It is rather unfortunate that the vast majority of application designers and developers do not spend time optimizing the user experience for wide screens and just port the “default” portrait layout. Let’s take a look at the old home screen of the Market client:

I’ll spare my actual thoughts on this screen, but it looks like ass. From top down:

  • Way too much vertical space for the header. The icon is unnecessarily large, the font looks a little dated and the search button just hangs in mid-air.
  • The Apps / Games / Downloads look like tabs, but are not actually tabs. Tapping one of these moves to a different screen that shows the relevant content.
  • The three-pane promo widget takes almost half the screen height and is a usability disaster. Not only the user cannot swipe to the previous / next triplet. The worst thing is that tapping on the specific thumbnail does not take you to the details of the app. Instead, it takes you to the category of the app, and then you need to “hunt down” the matching row.
  • With all this vertical space taken, the actual list of featured apps is not even visible – besides the header, that is.

And here how the landing page of the new Market client looks like in landscape mode:

Here, we’re putting the user in control. The screen has now two sections – the carousel + extra controls and the list of featured apps:

  • The main title bar (with the search button) does not extend the full screen width and leaves enough vertical space to show full four rows of featured apps.
  • The carousel allows swiping to both sides so that you can go to the previous app even after auto-advance animation kicks in and advances the carousel.
  • We have enough vertical space below the carousel to show the title, price and rating of the fronted app – leaving enough white space to separate the carousel from the navigation buttons below.
  • The navigation buttons now look like actual buttons. They support traversal with D-pad / trackball and show correct highlight outlines on focus and press.
  • The list of featured apps spans the full screen height and shows full four rows on the “common” hardware configuration (Nexus-type screen size / density). I personally thing that making each row more narrow is a usability improvement as the price / rating is closer to the app title / developer name.

Next, let’s look at the top-level category listing in the old client:

This one is a tad more usable, with two full rows of categories visible. Of course, the fat title bar is still there, and the promo switcher takes the whole screen width and has a whole bunch of unbalanced white space around it. In addition, there’s a whole lot of white space to the right of each category row. Let’s see how this screen looks in the new client:

Preserving the overall layout of the home screen, the promoted apps are now displayed in a carousel. The user is no longer at the mercy of promo switcher – swiping is fully supported, and if auto-advance animation is too fast, you can always swipe back (and we actually increase the auto-advance interval once the user starts interacting with the carousel). We also have enough vertical space to show not only the promo description, but also the title, rating and price for the fronted app. And since the category list spans the full screen height, we can fit full five rows, and a much taller scroll window.

Next up – the app listing of the specific category. Here is the old client in all its glory:

Tabs are actually tabs for a change, but all the rest is still ass. Let’s see how this screen looks in the new client:

As on the previous screen, the promoted apps are in an interactive carousel. The tabs are now much lighter and don’t command too much visual attention. Personally i also like that the tab texts are closer and don’t have too much space between them. And we have enough vertical space to show full four list rows, with a much taller scroll window.

Finally, let’s see the app details page in the old client:

What can i say? Fat title, fat tabs and fat button bar take so much vertical space that the actual content has less than half the screen height to view and scroll. This screen is by far the worst usability offender as far as the content perusal goes. Let’s see how this screen looks in the new client:

Preserving the same top-level organization, the top-level information on the app is displayed to the left – along with the action buttons to install, buy, update or uninstall the app. The rest of the information is displayed to the right, providing the full screen height for comfortable skimming and scrolling. There’s definitely room for improving the visual arrangement and balance of the app info in the left side – remember that we’re not done yet :)

Android devices come in all shapes and sizes, and we strongly encourage the application developers and designers to invest extra effort in addressing usability aspects of landscape orientation. This does not mean that you should fill every single white area with yet another control. But you shouldn’t be blindly forcing the portrait-optimized layout either. And of course, don’t forget the “small” details such as different screen sizes, resolutions or localization. Here is just a small example from the new Market client:

This is running under Korean which has rather long translations for “top paid”, “top free” and “just in”. At runtime, we dynamically find the largest font size that can fit at most two lines of text in the specific tab button. All buttons have exactly the same width and the layout enforces the middle button to be aligned with the horizontal center of the tab strip. Finally, the tab strip itself has custom left padding that pushes it “away” from the curved arc, while the light gray background extends all the way below the arc. You know, pushing pixels :)

That’s it for today’s installment. Tomorrow i’m going to talk about custom drawing and the green swooshes on the new title bars and carousels.

Meet the Green Goblin, part 1

December 13th, 2010

Last Friday we announced a significant update to the Android Market client. A whole slew of features went into this update (and many more are to come), and this week the pixel geek in me will be talking about the new visual design of the application.

To kick off this series, let’s talk about the layouts. Traditionally, the application design breaks the screens into separate sections – headers with basic navigation controls, main content area and perhaps the footer with context-sensitive action controls. This works especially well when each section occupies a rectangular portion of the screen – with the layout managers and the painting pipeline optimized for non-overlapping rectangular views. If you follow the recent visual trends in mobile, desktop and web design, you would notice that the designers are starting to push the bounds of the underlying UI toolkits to explore richer layouts with overlapping free-form controls. A few weeks ago our designers have come up with a new approach for browsing the main market content and a richer interaction model that puts more control into the hands of the users.

As noted in the announcement, we’re using an interactive carousel that enables a much more immersive interaction with the content in both portrait and landscape mode. In portrait mode, the list of featured applications “disappears” below the carousel, while in landscape mode the list is placed to the right of the carousel. Once the list starts scrolling, it goes below the carousel – with the row contents still partially visible in the left and right “ears”. If you were to open this activity in the hierarchy viewer, you would see two overlapping top-level views:

The carousel and the list overlap in the area that “contains” the curved bottom edge of the carousel. Without this overlap the topmost visible row in the list would be clipped at the bottom-most point of the arc with very noticeable white areas in the left and right ears of the carousel. While the core layout classes support a wide variety of cases, you’ll need to write a custom layout in case you have overlapping child views. Here is what you need to keep in mind:

  • You can extend an existing core class, such as LinearLayout. It depends on how much tweaking you need to do after the base class does its magic.
  • The LayoutParams defined in ViewGroup class supports a very rudimentary set of attributes (width and height). You can extend the LayoutParams class and add your own attributes (in much the same way the LinearLayout does, for instance). Add an attribute definition in your res/attrs.xml, enumerating all possible values and a declare-styleable entity with your custom atribute(s). Then, define a Java class with static ints that correspond to the attribute values. Then, extend one of the core LayoutParams classes (depends what exactly you need from the core) and get the values for your custom attributes. Finally, override the generateLayoutParams method in your container to return an instance of your layout params class. When you need the actual attribute value at runtime, cast the result of getLayoutParams of the specific child view to your custom class and you’re good to go.
  • In your custom layout, implement both onMeasure and onLayout. Make sure that the final width and height that you set in child.layout in onLayout match the measured width and height that you pass to child.measure in onMeasure. In case you see incorrect bounds of grand-child views, open the hierarchy viewer and compare the actual and measured values for width / height.
  • If child views overlap, you most probably want to have some kind of transparency or translucency in the overlapping area. The child views are painted in the order that is defined in the layout XML. In our case, we want the list view to be drawn before the carousel – otherwise the topmost visible row will be painted on top of the bottom curved edge of the carousel. This means that you will have some degree of coupling between the XML layout definition and the measure / layout code.

Let’s take another look at the overlapping area. As you can see, the list has a “Featured” header row. This is a simple text view with a light gray background. However, there is one very important usability setting on this header view – the top padding. As noted before, the top edge of the list is above the bottom-most point of the curved arc. If we don’t set any top padding on this list header, its text will be partially obscured by the carousel curve resulting in a very poor UI experience. The question is how do we compute the top padding?

The actual value depends on the pixel size of the screen. Remember that there’s a whole bunch of different devices out there, and you cannot make any assumptions about the screen hardware – physical size, pixel size or density. This is directly related to our curved carousel – the curvature radius and, by extension, the vertical size of the overlap area are only known at runtime.

If we were to define the overlap area height to be, say, 30 units (density-independent pixels), the arc would have different perceived curvature across devices such as G1, Nexus and Samsung Tab. If you target a “common” hardware such as Nexus / Droid / EVO, you will end up with an arc that looks too steep on a G1 and too shallow on a Tab. So, instead of hard-coding the overlap area height – and by extension the curvature radius – at design time, we compute it at runtime as the function of the actual pixel size of the screen.

This overlap area height is then used for two purposes. First, it defines the measured and actual height of the carousel and list view. If you were to add the two heights and subtract the overlap height, you would end up with the exact height of the screen. Second, we set it as the top padding on the list header view. This effectively pushes down the label so that it is fully visible (remember that you cannot rely that the text is short if your app is localized), with an extra bonus of extending the light gray background all the way to the carousel arc ears.

Up until now we talked about the portrait mode. What about the landscape?

Here, the design places the carousel and the list side by side in order to better reuse the available screen estate (more on this in tomorrow’s episode). All of the points mentioned for the portrait are relevant here, modulo the following:

  • The arc curvature and overlap amount are based on the screen width.
  • The overlap is along the X axis, with both views spanning the full height of the parent.
  • Each list row has a custom left padding that is based on the overlap area width. This prevents the app icons from being partially obscured by the right curved arc.
  • The same padding is set on the list header view.
  • If we were to set the padding on the list itself, we wouldn’t be able to have the header view background and list separators extending all the way to the left and below the carousel. The UI would be usable, but uglier.

This is it for today. The next entry talks about the landscape orientation and how the design aims to use the available screen estate without cramming too many visual elements.

Design, uninterrupted #111

December 9th, 2010

Today’s post highlights the design of BottlerocketCreative.com. An attractive single-page design features a strong balance around the center vertical axis, clean typography with a number of embedded fonts and noise textures that help break the monotonicity of large dark header and footer sections. Light sepia is used throughout the main section for background, decorative elements and text styling.

Note how the desaturated red from the main logo is used sparingly for the two contact links and the follow-me-on-Twitter link in the footer. Also note the simple yet effective drop-shadow rollover effects on the portfolio thumbnails and the off-by-one translucent text shadow around the text sections to improve readability.

Food for thought

December 9th, 2010

Engineers who insist on doing everything themselves underestimate the talent and skill needed to succeed in other domains, and thus also shortchange their own ideas and ambitions. Designers who refuse to interface with the technical side of things, both in using and harnessing some amount of technical knowledge to understand the limits and possibilities of product, or in using engineers to design products (solutions) to fit needs (problems), miss out on opportunities to create the most effective products possible.

From “On designers in Silicon Valley” by Nina Khosla.