A designer developing for Android

Eric Bailey

We are working with a client who tasked us with helping them create an Android app that replicates a subset of features on their iOS app. It’s an interesting challenge: not every interaction on iOS can directly translate to Android. The client was cognizant of this, and asked for our help making this new app feel like a natural part of the Android ecosystem.

Like most other people who use the web a lot, I’ve interacted with Material Design. As a studious designer, I’ve also made sure to read up on Material Design’s thorough design and development guidelines. However, this was my first time actually making an Android app. It was an exciting prospect and I was eager to dive in!

Following are some learnings that can hopefully help you out if you ever find yourself in a similar position:

Design tools

The client uses a Sketch file as a source of truth for how things should look and operate. This is great! It means that there’s a centralized reference for anything app-related.

Symbols

Other people have discussed the importance of using Sketch’s Symbols feature to improve your design workflow, so I won’t cover it here.

What I will say is that spending a little upfront time converting your Sketch document to use Symbols is well worth it. It will codify your user interface components, allowing you to more easily discuss and update interface elements. It will also save dramatically on effort when it comes time to start prototyping, which allows you to spend more time on the important part: creating an effective solution to your problem.”

Limitations

That being said, design tools like Sketch will only take you so far. The client had a do-or-die launch date; one based on a hard-and-fast deadline dictated to them by an external vendor. Because of this, I made the decision to take as much of my design work into code as possible.

Considering this non-negotiable due date, I wanted to free up as much time as possible for the project’s developer, my co-worker Alex. He’s an absolutely brilliant mobile developer, and I was lucky to be paired with him.

Android Studio

My thinking was that the less time Alex had to spend worrying about how things looked, the more time he could devote to the quality of the app logic he’d have to write. Ideally, it would also give him more time to react to any unforeseen complications, should they pop up.

Screenshot of the Android Stuido app, displaying a new project's source code.

To start coding an Android App, you need an Android development environment. Android Studio is an IDE dedicated to creating and maintaining Android apps. It’s… not the prettiest program, nor is it the easiest to use. Fortunately, Alex did a great job explaining the ins and outs of how it works.

As a designer, you’re going to want to get comfortable working in the following files:

colors.xml

Much like Sass variables or CSS Custom Properties, you’re going to want to abstract as much of your code as possible. Regardless of coding language or medium, this kind of practice helps keep your code consistent, flexible, and easy to maintain.

In Android, colors.xml is used to specify all your app’s color values. For example, a color called sunset would described like this: <color name="sunset">#FA5A41</color>.

I personally like tying color names to function (i.e. “background”, “text”, “warning”, “error”, etc.), but the client’s design system preferred descriptive names. It’s best to honor this, so that our deliverable works for how their development and design teams communicate internally.

After turning their palette into something Android-friendly, we can now use it in the various pieces that make up the app. Access the contents of colors.xml by first typing @color/, then the color’s name:

<View
  android:id="@+id/background"
  android:background="@color/grayLight"
  <!-- Other view code -->
/>

You’re going to want to be diligent about working from colors.xml. If you find yourself declaring a color value inline, do yourself and your future coworkers a favor and abstract it instead.

dimens.xml

We want to abstract our measurements, much like with our color values. In Android, dimens.xml is where we place that code.

Density-independent pixels

Android has a unit called density-independent pixels (dp). It’s a technical solution that plays to the strengths of their many devices having different display sizes and densities. Unlike declaring a regular static pixel value, a device pixel declaration tells the Android operating system to draw the pixels making up a UI proportionately based on a device’s reported display properties.

This might take a bit to wrap your head around—I kind of think about them like CSS’ viewport units. You’ll want to rely on density-independent pixels for your measurements as much as possible, to allow your design to gracefully adapt to different Android devices.

Scale-independent pixels

Scale-independent pixels (sp) are much like density-independent pixels, only they are used for type. The main difference is that they scale along with a user’s font size preference. This is great for helping to make your app accessible for those who benefit from a larger type size.

Abstraction

The client’s design system used a suite of standardized spacing values (10px, 20px, 30px, etc.). Since Sketch pixels don’t directly translate to Android density-independent pixels, the trick is to abstract these Sketch measurements and codify them as a series of distances:

<dimen name="spacing_tiny">2dp</dimen>
<dimen name="spacing_smallest">4dp</dimen>
<dimen name="spacing_smaller">8dp</dimen>
<dimen name="spacing_small">10dp</dimen>
<dimen name="spacing_medium">12dp</dimen>
<!-- etc. -->

You’ll also want to codify other repeated spacing values, such as things like corner radii, elevation, outer screen margins, etc.

When abstracting your measurements, the other important thing to keep in mind is sometimes you don’t want to use generic spacing. Certain distances, especially ones used across many different screens, should be semantically described in dimens.xml to more easily determine why that spacing value was chosen. For us, it was things like the distance between a UI component and a divider, the padding of a sticky footer, etc. You’ll want to use a human-friendly name for these values, to clearly describe intent: <dimen name="sticky_footer_spacing">10dp</dimen>.

Start from the top

There’s a trick in web design where you consistently apply spacing to only the top or bottom of all your interface elements. The idea is it makes a consistent appearance easier, as you don’t have to constantly undo and redo your margin declarations and wreck the cascade. Personally, I prefer applying spacing from the top, as an infinite vertically-scrolling canvas means there’s always going to be more room below.

styles.xml

Styling components in Android is a highly declarative process. There isn’t a real cascade, like what you’d get with CSS, meaning that you’re going to spend a lot of time re-describing things like color and fonts between different interface components.

This is where our abstraction work starts to pay off. You can invoke things like color in your styles.xml file, then apply those styles to an interface component. For example, an input label style could be constructed like this

<style name="InputLabel" parent="Label">
  <item name="android:fontFamily">@font/lato_bold</item>
  <item name="android:textColor">@color/sunset</item>
  <item name="android:textAllCaps">true</item>
  <item name="android:textSize">18sp</item>
</style>

This collection of styling instructions can then be via a declaration of style:

<TextView
  android:id="@+id/labelName"
  android:layout_marginTop="@dimen/spacing_small"
  style="@style/InputLabel"
  <!-- Other view code -->
/>

If you’re observant, you might have also noticed the use the spacing_small variable from our dimens.xml file. Note that style is different than a declaration of android:textStyle, which is used to control rendering type as regular, bold, or italic (this is better controlled in styles.xml, ideally using a typeface that includes intentionally-designed bold and italic fonts).

strings.xml

strings.xml is used to contain the content of your app. If you’re picking up on a pattern here, it’s that this is yet another centralizing file that controls things. Strings are declared in a fashion similar to colors and measurement: <string name="login_as_admin">Login as an admin</string>.

In addition to being helpful for localization, strings.xml makes it easy to review your app content to make sure it’s adhering to your writing styleguide (consistent terminology, capitalization, reading level, etc.).

They are declared by typing android:text="", then @string/ inside the double quotes, then the string’s name:

<Button
  android:id="@+id/button_login_as_admin"
  android:layout_marginTop="@dimen/spacing_largest"
  android:text="@string/login_as_admin"
  style="@style/ButtonPrimary"
  <!-- Other view code -->
/>

In this example, all our abstraction work comes together to keep our components flexible and efficient. If the style or content of this kind of button ever updates—say with updated brand standards—it will be that much easier to update.

Commenting and prefixing

Keeping your app code organized helps you quickly locate things and avoid writing duplicate code. This is especially important as the scope of your app grows.

As more code is added to the repo, what we can do is liberally apply comments to help break up the walls of code. I personally like to use multiline comments to separate the larger sections, to more quickly identify what’s what when scrolling through the page.

The other thing we can do is prefix similar kinds of things. All spacing abstraction gets a prefix of spacing_, all button abstraction gets a prefix of button_, and so and and so forth. This helps with searching and regexes, IDE autocompletion, code readability/scannability, and ease of understanding for developers newly assigned to the project.

Get a phone

Sketch and Android Studio can’t directly communicate, meaning that there’s the opportunity for drift to occur between your design files and the actual implementation. Android studio has two tools to help combat this: a Design view and a virtual device emulator.

Design view and emulated Android devices

The Design view gives you an in-pane preview of the code you’re writing for a specific view. It’s good for a quick check, to see if the layout you coded appears properly. However, I’ve found that when it comes to reviewing fine details, Android Studio simply can’t hack it. They’ll often be misrepresented, or worse, not rendered at all.

To get around this, Android will also let you emulate Android devices, simulating hardware as software. At first, I found myself editing my view code, quickly checking design view to see if it worked, then building the app and reviewing it in the emulator to see how it functioned.

Physical hardware

As the saying goes, nothing beats the real thing. On a decent computer, the build time for compiling to an emulator or a physical device was basically the same.

Because of this, I eventually wound up ignoring the emulator in favor of building the app on a physical Android phone. Seeing the app rendered on a real screen, using real pixels, gave me a better feel for how well my attempts to describe the interface using code worked.

Wrapping up

The client met their deadline, and thanks to Alex’s help, I got to learn some new skills. Excellent all around! If you’re a designer finding yourself undertaking a similar challenge, hopefully this advice can help you out as well.