Creating View Layouts

Common Mobile Screen Types

In mobile application development, mobile apps tend to adhere to a set of standard screen “archetypes” that appear again and again. There are over a dozen screen archetypes but there are six core archetypes that appear in nearly every app:

  • Login / Register - User signs up or logs into their account
  • Stream - User can scroll through important resources in a list
  • Detail - User can view the specifics of a particular resource
  • Creation - User can create a new resource
  • Profile - User can view their identity and stats
  • Settings - User can configure app options

In addition to these six, there’s other “extended” archetypes often encountered, including:

  • Splash Pages - Displayed while app is loading (and generally discouraged)
  • Onboarding - First-time user visual tutorial for how the app works
  • Map View - Often visualizing location-based information
  • Messaging - Real-time chat and group conversations
  • Calendar - Visualize dates or events into calendar form
  • Media Players - Allowing the control of media playback

A large part of building mobile apps is about understanding how to build the UI and data back-end to power these common screen types above. Therefore when learning about Android development, you must ensure you have built at least all six of these core types when working on early projects.

Archetypes

The six archetypes are provided in more detail below.

1. Login

This archetype is focused on the “signed out” view. This is where the user signs in or registers for a new account. This can usually take the form of username / password although commonly includes third-party authentication such as facebook or twitter connect for easy access.

Login screens usually require the following components:

Examples:

First, sign in pages:

Sign In  Sign In 2  Sign In 3

And of course, signup:

Sign Up  Sign Up 2  Sign Up 3

Check out more examples of login screens on mobile app patterns.

2. Stream

This archetype is focused on the primary content or data that a user consumes within the application. This is typically time-based displaying activities from other users that might be of interest. This is usually a list of discrete items which contain different data properties. The primary data is usually text or media content while secondary data includes the timestamp and the author.

Streams usually require the following components:

  • Sending network requests to retrieve lists of content data to display
    • See: [[sending requests|Sending and Managing Network Requests]]
  • Creating a list of items based on that source data including displaying text and media
    • See: [[listview|Using an ArrayAdapter with ListView]]
  • Endless scrolling which paginates as user consumes content
    • See: [[endless scrolling|Endless-Scrolling-with-AdapterViews-and-RecyclerView]]
  • Handling cases where the user wants to view more information on a piece of content
    • See: [[events|Basic-Event-Listeners]]
  • Allowing the user to take primary actions on this content such as deleting or editing
  • Optimizing the display of items such that scrolling the stream is smooth
    • See: [[viewholder|Using-an-ArrayAdapter-with-ListView#improving-performance-with-the-viewholder-pattern]]

Examples:

Stream  Stream  Stream

Check out more examples of streams on mobile app patterns.

3. Detail

This archetype is focused on displaying all relevant information about a single discrete item within the application. This usually is a view that is reached when a user is consuming content in a stream that they would like to view in more detail or interact with. Typically this view contains additional data not displayed on the stream as well as actions a user can perform such as editing their items, liking or commenting on other user’s content.

Detail views usually require the following components:

  • Sending network request to retrieve additional details or media for the data item
    • See: [[sending requests|Sending and Managing Network Requests]]
  • Action buttons that allow user to interact with the item
    • See: [[events|Basic-Event-Listeners]]
  • Option for user to share the content out to other apps
    • See: [[sharing|Sharing Content with Intents]]
  • Scrollable text or media content to read about the item
    • See: [[scrollview|Working with the ScrollView]]

Examples:

Detail  Detail  Detail

Check out more examples of detail screens on mobile app patterns.

4. Creation

This archetype is focused on allowing the user to create a new item by filling in all the properties for the item using a creation flow. This typically involves presenting the user with a series of input fields and allowing them to attach media such as a photo from the camera or metadata such as their location. Usually this is broken up into discrete steps and/or a great deal of fields are optional.

Creation screens usually require the following tasks:

  • Input fields of various types to collect information
    • See: [[input fields|Working with Input Views]]
  • Ability to validate fields for correctness before creation
  • Sending network request to create new valid content item
    • See: [[sending requests|Sending and Managing Network Requests]]
  • Option to capture a photo or select from photo gallery
    • See: [[camera and media|Accessing the Camera and Stored Media]]
  • Option to capture current location of device
    • See: [[location|Retrieving Location with LocationServices API]]
  • Option to share or include friends related to the item
    • See: [[parse sdk|Building Data driven Apps with Parse]]

Examples:

Creation  Creation  Creation

Check out more examples of creation screens on mobile app patterns.

5. Profile

This archetype is focused on allowing the user to view information about their own account, view their own content, and provide them account related action items. Typically, the profile contains important statistics about the user (i.e number of followers), displays recent content, and provides access to actions such as editing their profile, changing their picture, logging out, etc.

Profile screens usually require the following components:

  • Grid or list of recent content items for user
    • See: [[listview|Using an ArrayAdapter with ListView]]
  • Images associated with the user’s identity
    • See: [[picasso|Sending-and-Managing-Network-Requests#displaying-remote-images-the-easy-way]]
  • List of related users (followers, following)
  • Action items when on another user’s account
    • See: [[events|Basic-Event-Listeners]]

Examples:

Profile  Profile  Profile

Check out more examples of profile screens on mobile app patterns.

6. Settings

This archetype is focused on giving the user the ability to tune preferences associated with their account and/or the behavior of the app. The settings available range from notification and privacy settings, to profile settings such as username or email and to preferences affecting the behavior of the app.

Settings screens usually require the following components:

  • Persisting settings after they are saved
    • See: [[preferences|Storing-and-Accessing-SharedPreferences]]
  • Input fields and labels for modifying settings
    • See: [[input fields|Working with Input Views]]
  • Validating new input from the user
  • Connecting with third-party accounts
  • Affecting behavior of push notifications
    • See: [[push messaging|Push Messaging]], [[notifications|Notifications]]

Examples:

Profile  Profile  Profile

Check out more examples of settings screens on mobile app patterns.

Overview

View Layouts are a type of View class whose primary purpose is to organize and position other view controls. These layout classes (LinearLayout, RelativeLayout, etc.) are used to display child controls, such as text controls or buttons on the screen.

Android activities (screens) use layouts as a container for view controls, and layouts can actually contain other nested layouts as well. Nearly all Android activities have layout containers similar to the way that most HTML documents use “divs” to contain other content.

There are a few very commonly used layouts and then many more specialized layouts that are used in only very particular cases. The bread and butter layouts are LinearLayout, RelativeLayout, and FrameLayout.

It’s important to note the class hierarchy of these View Layouts. Each of them subclass ViewGroup, which itself subclasses View. That means it is perfectly legal to pass a layout such as LinearLayout as an argument for something that takes View as a parameter. ViewGroup also contains the nested static class LayoutParams which is used for creating or editing layouts in code. Keep in mind that each subclass of ViewGroup, such as LinearLayout, has its own nested static class LayoutParams that’s a subclass of ViewGroup.LayoutParams. When creating View Layouts in code, beginners will often confuse the many different available LayoutParams classes and run into hard to catch problems.

LinearLayout

In a linear layout, like the name suggests, all the elements are displayed in a single direction either horizontally or vertically and this behavior is specified in android:orientation which is an attribute of the node LinearLayout.

All children of a LinearLayout are displayed sequentially based on the order they are defined within the layout. A LinearLayout respects margins between children and the gravity (right, center, or left alignment) of each child.

Common view attributes you might see used in a LinearLayout:

  • android:gravity - Controls the alignment of the view content (akin to text-align in CSS)
  • android:layout_gravity - Controls the alignment of the view within it’s parent container (akin to float in CSS)
  • android:layout_weight - Specifies how much of the extra space in the layout to be allocated to a view.

Example of LinearLayout snippet:

<?xml version="1.0" encoding="utf-8"?>
<!-- Parent linear layout with vertical orientation -->
<LinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:orientation="vertical"
  android:layout_width="match_parent"
  android:layout_height="match_parent">
   
  <TextView android:layout_width="match_parent" android:layout_height="wrap_content"
            android:text="Email:" android:padding="5dp"/>
             
  <EditText android:layout_width="match_parent" android:layout_height="wrap_content"
            android:layout_marginBottom="10dp"/>            
</LinearLayout>

Distribute Widths with Layout Weight

If you want to setup a part of your layout, such that, for instance, 3 buttons appear in a row, occupying equal space (or if, for instance, you want to give 45 space to a map and 15 to another component below it), LinearLayout can be used to do the trick by leveraging android:layout_weight. This works by setting the android:weightSum to a total value and then setting the android:layout_weight value for each subview to determine width distribution.

...
<LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:weightSum="5"
        android:layout_alignParentBottom="true">
    <ImageButton
        android:id="@+id/btnLocEnable"
        android:src="@drawable/ic_location"
        android:layout_width="0dp"
        android:layout_weight="2"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:background="@color/twitter_light_blue"
        />
    <ImageButton
        android:id="@+id/btnUploadPhoto"
        android:src="@drawable/ic_addimage"
        android:layout_width="0dp"
        android:layout_weight="3"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:background="@color/twitter_light_blue"/>
</LinearLayout>

Using the above XML, btnLocEnable will have 25 of total container width and btnUploadPhoto will have 35 of parent width because we set the total android:weightSum to 5 and the buttons android:layout_weight property to 2 and 3 respectively.

Use caution in utilizing multiple nested LinearLayouts and/or layout_weight from a performance standpoint!

RelativeLayout

In a relative layout every element arranges itself relative to other elements or a parent element. RelativeLayout positions views based on a number of directional attributes:

  • Position based on siblings: layout_above, layout_below, layout_toLeftOf, layout_toRightOf
  • Position based on parent: android:layout_centerHorizontal, android:layout_centerVertical
  • Alignment based on siblings: layout_alignTop, layout_alignBottom, layout_alignLeft, layout_alignRight, layout_alignBaseline
  • Alignment based on parent: layout_alignParentTop, layout_alignParentBottom, layout_alignParentLeft, layout_alignParentRight

An example of a RelativeLayout:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:layout_width="match_parent"
                android:layout_height="wrap_content">
 
    <TextView android:id="@+id/label" android:layout_width="match_parent"
              android:layout_height="wrap_content" android:text="Email" />
 
    <EditText android:id="@+id/inputEmail" android:layout_width="match_parent"
              android:layout_height="wrap_content" android:layout_below="@id/label" />
   
    <Button android:id="@+id/btnLogin" android:layout_width="wrap_content"
            android:layout_height="wrap_content" android:layout_below="@id/inputEmail"
            android:layout_alignParentLeft="true" android:layout_marginRight="5dp"
            android:text="Login" />
</RelativeLayout>

Read this RelativeLayout tutorial for a more detailed overview. You can also see more about this layout by inspecting the RelativeLayout.LayoutParams docs and the official RelativeLayout guide.

Using Alignment to Control Width or Height

A less understood aspect of RelativeLayout is how the use of alignment can determine width or height. It may seem counterintuitive at first about how this works, so we’ll walkthrough a few examples in this section. Using this approach is especially useful in matching the widths or heights relative to other elements.

Example 1: How alignment can determine width

Suppose we have two buttons of varying widths:

The corresponding XML would be:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
    android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="1245678901234567890"
        android:id="@+id/button1"/>

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="CANCEL IT"
        android:id="@+id/button2"
        android:layout_below="@id/button1"
        android:layout_alignLeft="@id/button1" />
</RelativeLayout>

Suppose we also specify that the second button should be aligned left and right to the first button. If we add android:layout_alignRight="@id/button1" to the second button’s XML style, the change causes the second button to expand the width to match that of the first button. In other words, the only way to meet the requirements of specifying alignment on both sides is to expand the width of the second button.

In this way, when two elements are vertically positioned above or below the other, left and right alignments will control the width. When two elements are positioned horizontally next to each other, top and bottom alignments will control the height. We’ll show how height can be impacted by specifying top and bottom alignments in the next example.

Example 2: How alignment can determine height

Suppose we have this layout definition:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
    android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:height="200dp"
        android:text="1245678901234567890"
        android:id="@+id/button1"/>

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="CANCEL IT"
        android:id="@+id/button2"
        android:layout_toRightOf="@id/button1" />
</RelativeLayout>

The corresponding preview looks like:

If we wish to match the height of the first button, we can specify layout_alignTop and layout_alignBottom on the second button.

  <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignTop="@id/button1"
        android:layout_alignBottom="@id/button1"
        android:text="CANCEL IT"
        android:id="@+id/button2"
        android:layout_toRightOf="@id/button1" />

The only way to fulfill this requirement is to expand the height of the second button as shown below:

PercentRelativeLayout

PercentRelativeLayout, a recent addition to the [[Design Support Library]], enables the ability to specify not only elements relative to each other but also the total percentage of available space. In the past, in order to position two elements next to each other with equal height, you would normally have to create a LinearLayout within a RelativeLayout. PercentRelativeLayout helps solves this issue.

To use, follow the setup guide, and addd the PercentRelativeLayout from Nuget.

The layout_width and layout_height of the PercentRelativeLayout should determine the total width and height that can be used. Any elements contained within it should specify the width and height possible using layout_heightPercent and/or layout_widthPercent. Because this library is not part of the standard Android library, note that a custom attribute app namespace being used.

An example of a layout used to describe the image above is shown below (taken from this sample code):

<android.support.percent.PercentRelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <View
        android:id="@+id/top_left"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_alignParentTop="true"
        android:background="#ff44aacc"
        app:layout_heightPercent="20%"
        app:layout_widthPercent="70%" />

    <View
        android:id="@+id/top_right"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_alignParentTop="true"
        android:layout_toRightOf="@+id/top_left"
        android:background="#ffe40000"
        app:layout_heightPercent="20%"
        app:layout_widthPercent="30%" />

    <View
        android:id="@+id/bottom"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_below="@+id/top_left"
        android:background="#ff00ff22"
        app:layout_heightPercent="80%" />
</android.support.percent.PercentRelativeLayout>

Further samples include:

Margin Percentages

The margins can also be set to a percentage of the total widths as well:

  • app:layout_marginStartPercent
  • app:layout_marginEndPercent
  • app:layout_marginTopPercent
  • app:layout_marginBottomPercent

We can also define app:layout_marginPercent that will be to all four values above.

Aspect Ratio

Similar to how [[ImageView|Working-with-the-ImageView#sizing-imageview-controls|]]’s adjustViewBounds:true can be used to scale the image according to its aspect ratio, we can also use PercentRelativeLayout to define an aspect ratio for a layout. If one dimension is set to 0dp and no percent scaling is associated with it, setting a percentage on the app:layout_aspectRatio attribute can scale the other to meet the ratio:

<android.support.percent.PercentRelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:background="#ff00ff22"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <!-- not using aspectRatio here -->
    <View
        android:id="@+id/view1"
        android:background="#ff44aacc"
        android:layout_width="300dp"
        android:layout_height="wrap_content"
        app:layout_heightPercent="50%"/>

    <!-- using aspectRatio here -->
    <View
        android:layout_below="@id/view1"
        android:background="#ffe40000"
        android:layout_width="300dp"
        android:layout_height="0dp"
        app:layout_aspectRatio="160%"/>

</android.support.percent.PercentRelativeLayout>

The resulting layout appears as follows:

FrameLayout

In a frame layout, the children are displayed with a z-index in the order of how they appear. Put simply, the last child added to a FrameLayout will be drawn on top of all the previous children. Think of it like a stack of items, the item last put on the stack will be drawn on top of the items below it. This layout makes it very easy to draw on top of other layouts, especially for tasks such as button placement.

To arrange the children inside of a FrameLayout use the android:layout_gravity attribute along with whatever android:padding and android:margin you need.

Example of FrameLayout snippet:

<FrameLayout
    android:id="@+id/frame_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <!-- Child1 is drawn first -->
    <ImageView
        android:id="@+id/child1"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:contentDescription="Image"
        android:src="@drawable/icon" />
    <!-- Child2 is drawn over Child1 -->
    <TextView
        android:id="@+id/child2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Child 2"
        android:layout_gravity="top|left" />
    <!-- Child3 is drawn over Child1 and Child2 -->
    <TextView
        android:id="@+id/child3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Child 3"
        android:layout_gravity="top|right" />
</FrameLayout>

In this example, an ImageView is set to the full size of the FrameLayout. We then draw two TextView’s over it.

Understanding View Layers

Layering Introduction

You may notice that when two views overlap on screen, that one view will become hidden behind the other. Views are drawn in layers by default based on the order they appear in the XML. In other words, the view at the bottom of a container is drawn on screen last covering all previously drawn views.

This is described in the official view docs and in the How Android Draws guide with:

The tree is largely recorded and drawn in order, with parents drawn before (i.e., behind) their children, with siblings drawn in the order they appear in the tree. If you set a background drawable for a View, then the View will draw it before calling back to its onDraw() method. The child drawing order can be overridden with custom child drawing order in a ViewGroup, and with setZ(float) custom Z values} set on Views.

In other words, the easiest way to layer is to pay close attention to the order in which the Views are added to your XML file within their container. Lower down in the file means higher up in the Z-axis.

Elevation

In Android starting from API level 21, items in the layout file get their Z-order both from how they are ordered within the file as well as from their “elevation” with a higher elevation value meaning the item gets a higher Z order. The value of android:elevation must be a dimension value such as 10dp. We can also use the translationZ property to provide the same effect. Read more about elevation here on the official guide.

Overlapping Two Views

If we want to overlap two views on top of each other, we can do so using either a RelativeLayout or a FrameLayout. Suppose we have two images: a background image and a foreground image and we want to place them on top of one another. The code for this can be achieved with a RelativeLayout such as shown below:

<RelativeLayout
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">

    <!-- Back view should be first to be drawn first! -->
    <ImageView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:adjustViewBounds="true"
        android:scaleType="fitXY"
        android:src="@drawable/back_image_beach"
        />

    <!-- Front view should be last to be drawn on top! -->
    <!-- Use `centerInParent` to center the image in the container -->
    <!-- Use `elevation` to ensure placement on top (not required) -->
    <ImageView
        android:layout_width="250dp"
        android:layout_height="wrap_content"
        android:adjustViewBounds="true"
        android:elevation="10dp"
        android:layout_centerInParent="true"
        android:scaleType="fitXY"
        android:src="@drawable/airbnb_logo_front"
        />
</RelativeLayout>

This results in the following:

Forcing View to the Front

We can force a view to the front of the stack to become visible using:

myView.BringToFront();
myView.Invalidate(); 

Note: You must be sure to call bringToFront() and invalidate() method on the highest-level view under your root view. See a more detailed example here.

With these methods outlined above, we can easily control the draw order of our views.

Optimizing Layout Performance

To optimize layout performance, minimize the number of instantiated layouts and especially minimize deep nested layouts whenever possible. This is why you should generally use a RelativeLayout whenever possible instead of nested LinearLayout. A few layout tips are included below:

  • Using nested instances of LinearLayout can lead to an excessively deep view hierarchy and can be quite expensive especially expensive as each child needs to be measured twice. This is particularly important when the layout is inflated repeatedly such as in a list.
  • Layout performance slows down due to a nested LinearLayout and the performance can be improved by flattening the layout, making the layout shallow and wide rather than narrow and deep. A RelativeLayout as the root node allows for such layouts. So, when this design is converted to use RelativeLayout, the view hierarchy can be flattened significantly.
  • Sometimes your layout might require complex views that are rarely used. Whether they are item details, progress indicators, or undo messages, you can reduce memory usage and speed up rendering by loading the views only when they are needed.

Review the following references for more detail on optimizing your view hierarchy:

Cloning a Loging Screen Exercise

This guide is going to walk us through the step-by-step process of recreating this screenshot in an Android app:

Note: Jump to the [[Styling Screens Q&A|Styling-UI-Screens-FAQ]] for more general answers to common questions.

Cutting Assets

First, I will make the downloadable assets available. Keep in mind these were stolen right out of the screenshot and therefore their quality is pretty poor. But it demonstrates the concepts nonetheless. To create the mockup, we need the following assets:

Download those and import the images one by one into the drawable folder as shown below:

Note that in production applications you would multiple sizes of these images for different image densities.

Create Project

Generate a new Android project that uses the highlight icon as the launcher icon:

Generate the project with minimum SDK of 15 and no additional changes.

Start Basic Layout

There are seven views that will be placed within the layout:

  • TextView (To use highlight…)
  • ImageButton (Facebook)
  • ImageButton (LinkedIn)
  • TextView (Why not email?)
  • TextView (Highlight is based…)
  • TextView (Please let us know…)
  • TextView (We won’t post things without…)

Step 1: Layout Background

Let’s start by setting the layout background to white:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#ffffff"
    ...>
</RelativeLayout>

Now the entire background for the screen appears white like the mockup.

Step 2: ImageButtons

Let’s start with the ImageButtons. Drag the two image buttons to the screen and select facebook and linkedin as sources respectively. Now go into the XML and tweak the background property of each to “@null” to remove the button borders.

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    ...>

    <ImageButton
        android:id="@+id/btnFacebook"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:background="@null"
        android:contentDescription="@string/facebook_desc"
        android:src="@drawable/facebook_connect" />

    <ImageButton
        android:id="@+id/btnLinkedIn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/btnFacebook"
        android:layout_below="@+id/btnFacebook"
        android:layout_marginTop="5dp"
        android:background="@null"
        android:contentDescription="@string/linkedin_desc"
        android:src="@drawable/linkedin_connect" />

</RelativeLayout>

Here we’ve aligned the first button to the top of the parent, used layout_centerHorizontal, set android:background to null to avoid the button border, set text descriptions for android:contentDescription and assigned the android:src to the respective buttons. Now our screen looks like:

Step 3: Basic TextViews

Now, let’s drag in the TextViews for the screen. (There’s five of these). First, let’s store the strings for each of these TextView controls in the res/values/strings.xml file for use in our TextViews later:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="highlight_preamble">To use Highlight, please sign in with one of the services below:</string>
    <string name="why_not_email_title">Why not email?</string>
    <string name="why_not_email_body">Highlight is based on real identity and mutual friends.
        Using these services allows us to show you how you\\'re connected to the people around you.
        It also makes it super easy to create a Highlight profile.
    </string>
    <string name="feedback_label">Please <a href="http://highlight.com">let us know</a> if you have feedback
        on this or if you would like to log in with another identity service. Thanks!
    </string>
    <string name="permission_label">We won\\'t post things without your permission.</string>
</resources>

Now let’s drag on the different TextView and set the appropriate text values. Without any styling or proper positioning it might look like this screen:

TextView Styling

Let’s add basic styling:

  • TextView should be set to “14sp” and textColor of “#7e7e7e”
  • “To use Highlight” view should be set to textColor of “#575757”
  • “Why not email?” view textStyle should be set to bold
  • “We won’t post things” should be set to textColor of “#bbbbbb” and textSize of 12sp, and use layout_centerHorizontal to center the text.
  • Estimate margin between elements based on mockup

The screen now looks like:

The resulting XML layout might look like:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#ffffff"
    ... >

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:text="@string/highlight_preamble"
        android:textColor="#575757"
        android:textSize="14sp" />

    <ImageButton
        android:id="@+id/btnFacebook"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/textView1"
        android:layout_below="@+id/textView1"
        android:layout_marginTop="10dp"
        android:background="@null"
        android:contentDescription="@string/facebook_desc"
        android:src="@drawable/facebook_connect" />

    <ImageButton
        android:id="@+id/btnLinkedIn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/btnFacebook"
        android:layout_below="@+id/btnFacebook"
        android:layout_marginTop="10dp"
        android:background="@null"
        android:contentDescription="@string/linkedin_desc"
        android:src="@drawable/linkedin_connect" />

    <TextView
        android:id="@+id/textView2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/btnLinkedIn"
        android:layout_below="@+id/btnLinkedIn"
        android:layout_marginTop="23dp"
        android:text="@string/why_not_email_title"
        android:textColor="#7e7e7e"
        android:textStyle="bold" />

    <TextView
        android:id="@+id/textView3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/textView2"
        android:layout_below="@+id/textView2"
        android:layout_marginTop="10dp"
        android:text="@string/why_not_email_body"
        android:textColor="#7e7e7e" />

    <TextView
        android:id="@+id/textView4"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/textView3"
        android:layout_below="@+id/textView3"
        android:layout_marginTop="10dp"
        android:text="@string/feedback_label"
        android:textColor="#7e7e7e" />

    <TextView
        android:id="@+id/textView5"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/textView4"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="10dp"
        android:text="@string/permission_label"
        android:textColor="#bbbbbb"
        android:textSize="12sp" />

</RelativeLayout>

ActionBar Styling

Biggest missing style now is the top ActionBar that is displayed on the screen. In the mockup, this has a blue background and smaller text. Let’s fix that now. First, let’s change the copy to say “Sign in”:

<?xml version="1.0" encoding="utf-8"?>
<resources>
  <string name="sign_in">Sign in</string>
</resources>

and then actually go into the AndroidManifest.xml and change the label:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    .... >

    <application
        ... >
        <activity
            ...
            android:label="@string/sign_in" >
        </activity>
    </application>
</manifest>

Next, we need to change the background color by tweaking the Theme’s style. Let’s tweak the theme by adding the following to res/values/styles.xml:

<resources xmlns:android="http://schemas.android.com/apk/res/android">
    <style name="Theme.HighlightCopy" parent="@android:style/Theme.Holo">
       <item name="android:actionBarStyle">@style/Theme.HighlightCopy.ActionBar</item>
    </style>

    <style name="Theme.HighlightCopy.ActionBar" parent="@android:style/Widget.Holo.ActionBar">
       <item name="android:background">#33b5fa</item>
    </style>
</resources>

and then apply that theme to the Activity in the AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    .... >

    <application
        ... >
        <activity
            ...
            android:label="@string/sign_in"
            android:theme="@style/Theme.HighlightCopy" >
        </activity>
    </application>
</manifest>

Now the screen looks like:

Switch TextView to use HTML

The final tweak is let’s programmatically cause the TextView to display the “let us know” link as HTML. In the Java activity:

public class MainActivity extends Activity {
	TextView tvFeedback;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		base.OnCreate(savedInstanceState);
		SetContentView(R.layout.activity_main);
		tvFeedback = (TextView) FindViewById(Resource.Id.textView4);
		tvFeedback.SetText(Html.FromHtml(getString(Resource.String.feedback_label)));
	}
}

This applies the text to the TextView as HTML and displays a clickable link in the body.

Conclusion

Here’s the “final” result:

In comparison to the original mockup:

While this is by no means a perfect clone, this guide shows the process of taking a mockup and rebuilding that step by step into a useable activity view.

Design Support Library

At their I/O 2015 conference, Google announced a new design support library, which helps bring a lot of [[material design components|Material-Design-Primer]] including a navigation drawer view, floating labels, floating action buttons, snackbars, and a new framework to tie motion and scroll events. The library is supported for Android version 2.3 and higher.

Features

The support design library has the following key features:

  1. FloatingActionButton - A round button at the bottom right denoting a primary action on your interface. Promoting key actions within a modern material design app.
  2. TabLayout - An easier way to put tabs around a ViewPager which acts as sliding tabs between fragments within an app.
  3. NavigationView - An easier way to provide a modern navigation drawer from the left with a header and a series of navigation items.
  4. SnackBar - Shown on the bottom of the screen and contains text with an optional single action. They automatically time out after the given time length by animating off the screen.
  5. [TextInputLayout]]() - Float the hint above any text field as the user is entering information and/or add a character counter.
  6. CoordinatorLayout - Provides an additional level of control over scroll and touch events between child views.
    • AppBarLayout allows your toolbar and other views to react to scroll events.
    • CollapsingToolbarLayout extend this to allow the toolbar to collapse as the user scrolls through a view.
    • [[Bottom Sheets|Handling-Scrolls-with-CoordinatorLayout#bottom-sheets]] to expose a sheet of material that slides up from the bottom of the screen.
  7. [[PercentRelativeLayout|Constructing-View-Layouts#percentrelativelayout]] and PercentFrameLayout to enable views to occupy percentage-based dimensions.
  8. Vector Drawables to reduce the need to include images for every density size.
    • Vector drawables are compatible back to Android 2.1 (API 7), but animated vector drawables are only back-ported to Android 3.0 (API 11).
  9. Animating view hierarchies using the Transitions framework down to Android 4.0 (API 14) . Currently, there is no backported support for activity/fragment transitions used in this API.

Setup

Make sure that you have at least the Android Gradle plugin v2.1.0 supported. Use Nuget and search for the Support Design Library.

There is a new support design library that must be included. This library also depends on updated versions of the AppCompat library to be included. If you are not currently using this library, check out this [[migration guide|Migrating-to-the-AppCompat-Library]]. In addition, make sure these versions have been updated.

If you are using the RecyclerView, [CardView, or any other support v7 related libraries you should also upgrade the versions. The RecyclerView for instance has features that are used with this new design support library.

Adding Percent Support Library

To add the percent support library, you need to add it as a Nuget package. Search for Percent Support Library

Adding Vector Drawable Library

Android Studio v1.4 provides backwards support for vector drawables to pre-Lollipop devices by creating the PNG assets automatically at compile time. The support library eliminates this necessity by providing vector drawable support for older Android versions.

Finally, the libraries need to be added from Nuget, VectorCompat

Adding Transitions Library

The Transitions API was first introduced in Android 4.4 (KitKat) but now includes back ported support for animating view hierarchies down to Android 4.0. However, there is no support for activity/fragment transitions currently. To use this library, you need to add the library explicitly from Nuget.

Adding Annotations Library

To leverage the annotations library, you can also explicitly add it to your Gradle file. Adding the [[AppCompat|Migrating-to-the-AppCompat-Library]] or support design library implicitly adds it:

Installing the Library

You normally need to open the SDK Manager and make sure to download the Android Support Repository as well as the latest Android Support Library. However, Android Studio will also show at the bottom any missing libraries and you can click on the Install repository and sync project. The process will only succeed if you specify a valid library and version, but it enables you to upgrade without needing to open the SDK Manager.

If you are using any type of continuous build system and need to help automate downloading of updates to the support library, you can use [[Jake Wharton’s SDK Manager|Installing-Android-SDK-Tools#installing-the-android-sdk-automated-way]] to download the packages for you.

Sample Code

If you want to see how to use the various components, check out this sample code. For an example of the percent support library, see this sample code.

Official Source Code

The Android Open Source Project (AOSP) hosts the major release versions for this library, which can be found here. For instance, if you are curious about what styles can be overridden for the different components, see this link.

The latest source code updates for the support library are now always included since v23.1.0 in your SDK directory (i.e. Library/Android/sdk/extras/android/m2repository/com/android/support/design for Mac OS X).

Change Log

Changes in Support Library v23

Changes in Support Library v23.1

  • TextInputLayout and EditText now includes the ability to add a character counter. ([[view guide |Working-with-the-EditText#adding-character-counting]])

  • A snap flag can also be added to the list of scrolling effects declared in AppBarLayout. ([[view guide|Handling-Scrolls-with-CoordinatorLayout#responding-to-scroll-events]])

  • A setOnDragListener() method has been added to AppBarLayout. ([[view guide|Handling-Scrolls-with-CoordinatorLayout#embedding-google-maps-in-appbarlayout]])

  • An aspectRatio attribute is now supported in PercentRelativeLayout. ([[view guide|Constructing-View-Layouts#aspect-ratio]])

  • A new item animation interface for the RecyclerView. ([[view guide|Using-the-RecyclerView#new-itemanimator-interface]])

  • Custom views can be provided for NavigationView rows. ([[view guide|Fragment-Navigation-Drawer#adding-custom-views-to-navigation-drawer]])

Changes in Support Library v23.1.1

  • NavigationView now contains a getHeaderView() method ([[view guide|Fragment-Navigation-Drawer#getting-references-to-the-header]])

Changes in Support Library v23.2

  • Added support for bottom sheets. ([[view guide|Handling-Scrolls-with-CoordinatorLayout#bottom-sheets]])
  • Added setup instructions for vector drawables. ([[view guide|Drawables#vector-drawables]])

Changes in Support Library v24.2.0

  • TextInputLayout and EditText now includes the ability to add password visibility toggles. ([[view guide |Working-with-the-EditText#adding-password-visibility-toggles]])

  • Added DiffUtil class for RecyclerView. ([[view guide|Using-the-RecyclerView#diffing-larger-changes]])

  • Support v4 library modules have been broken apart but cannot be used to reduce APK size because the fragment library still depends on all other related modules. ([[view guide|Migrating-to-the-AppCompat-Library#overview]])

  • Transitions API backported to Android 4.0 but does not include support for activity/fragment transitions. ([[view guide|View-Hierarchy-Animations]])

Addendum

While this guide gets us pretty close, keep in mind that in a production app you would of course want to consider things like:

  • Images for all drawable density sizes
  • Click states for the buttons (so the graphic changes when I press)
  • Testing across multiple device sizes (might use a nine-patch for scalable buttons)

References