Beautiful Material Design with the Android Support Design Library

James Montemagno

It was clear when Google introduced Material Design that it would shift the Android landscape even more than its Holo predecessor, and thus far the journey for developers to implement those new design principles in their apps has been a bit of a long and bumpy ride.

Material Design for Android Applications Introduction

In the beginning, Material Design was only available on devices running Android 5.0+ Lollipop, but over time the Support Library v7 AppCompat was updated to enable Material theming on older versions of Android.

Theming, though, is only a part of the equation. Material Design also comprised a lot of new UI components and interactions that were not present in AppCompat. This is where the new Android Support Design Library comes in, offering a wide range of implementations of several portions of the Material Design specification in a fully backwards compatible fashion when combined with Support Library v7 AppCompat.

Get The Support Design Library

If you haven’t gotten up to speed yet on switching your apps to use AppCompatActivity and AppCompat theming, be sure to first read through our entire blog post on how to get set up. Once your app has been AppCompat enabled, head over to the component store from inside of Visual Studio or Xamarin Studio and Search for “Android Support Design”.

Component Support Design for Android Applications

Add the component to your project and the Support Design Library NuGet, and samples will automatically be installed in your project. Be sure to browse the sample for an overview of everything that Support Design Library has to offer.

Now that you’re set up, let’s take a look at a few of my favorite new widgets that are built into this awesome library.

Floating Labels with TextInputLayout

The EditText widget offers a wide range of customizations, including my favorite, the Hint property, but there is one small issue with it. While the Hint property displays an indication of what your users should enter when in its unfocused state, it vanishes when the user taps the control or if anything is entered in the EditText field. This usually means you have to add a separate label to your fields to add context.

Not anymore! The TextInputLayout can now wrap any EditText and will automatically animate the Hint to be displayed right above the EditText widget.

<android.support.design.widget.TextInputLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
    <EditText
        android:id="@+id/username"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:hint="Username" />
</android.support.design.widget.TextInputLayout>

Here it is in action: Android Application - Floating Label

Snackbar: Powerful & Enhanced Toast

Toasts on Android are normally used to display short lived information that has no interaction.

The new Snackbar component on the other hand, provides a similar lightweight feedback mechanism but lets you specify extra actions available to users. If you’ve used toasts before, the core API will look familiar:

Snackbar
  .Make (parentLayout, "Message sent", Snackbar.LengthLong)
  .SetAction ("Undo", (view) => { /*Undo message sending here.*/ })
  .Show (); // Don’t forget to show!

Android Application Components - Toasts

You should note the use of a View as the first parameter to Make () — Snackbar will attempt to find an appropriate parent of the Snackbar’s view to ensure that it’s anchored to the bottom.

There are several instances where the Snackbar will come in handy. Take the example above of a login page: you may want to use the new Snackbar to display information when the user attempts to log in. Additionally, if your user enters an incorrect password, you could supply an optional action to clear the password field:

loginButton.Click += (sender, e) => {
  if (string.IsNullOrWhiteSpace (username.Text)) {
    Snackbar.Make (drawerLayout, "Fill in username.", Snackbar.LengthLong)
	    .SetAction ("OK", (v) => { })
	    .Show ();
  } else if (password.Text != "monkey") {
    Snackbar.Make (parentLayout, "Invalid Password", Snackbar.LengthLong)
            .SetAction ("Clear", (v) => { password.Text = string.Empty; })
            .Show (); 
  } else {
    Snackbar.Make (parentLayout, "You are now Logged in!", Snackbar.LengthLong)
            .Show ();
  }
};

Snackbar in Android Application

Effective Navigation in Android

Navigation Drawer using Material Design in Android ApplicationThere are several ways to handle navigation in your app, including dashboards, tabs, and even drop down spinners. My favorite, though, is the Navigation Drawer.

By providing a simple, yet highly customizable slide out menu, the Navigation Drawer is an ideal pattern for a lot of apps. Implementing the Navigation Drawer was always a bit of a pain, but this has been greatly simplified by combing the new NavigationView class with the standard DrawerLayout.

The NavigationView makes it easier to display menu items by leveraging the standard menu resource system that you’re already familiar with. It also provides a simplified way of adding a header layout to the top of your NavigationView. You can easily have a beautiful and functional Navigation Drawer up and running with just a few lines of code.

Setup

The root of your app will be a standard Android XML that will house three important items:

  • DrawerLayout: Top-level container for an interactive drawer
  • Your Content: What you want to display on your main activity (usually a fragment that is swapped out)
  • NavigationView: Easy way of implementing the navigation drawer and inflating menu items

Here is the standard code for your Android XML:

<android.support.v4.widget.DrawerLayout
        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"
        android:fitsSystemWindows="true">

    <!-- your content layout -->

    <android.support.design.widget.NavigationView
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_gravity="start"
            android:id="@+id/nav_view"
            app:headerLayout="@layout/drawer_header"
            app:menu="@menu/nav_menu"/>
</android.support.v4.widget.DrawerLayout>

Add the Menu

You should note two attributes for NavigationView: app:headerLayout controls the (optional) layout used for the header and app:menu is the menu resource inflated for the navigation items. Create a new file named nav_menu.xml under Resources/menu.

A simple drawer will just contain a few items, but there’s nothing preventing you from having deeper menu hierarchies with sub-headers, like in the screenshot:

<menu xmlns:android="http://schemas.android.com/apk/res/android">
  <group android:checkableBehavior="single">
    <item
      android:id="@+id/nav_home"
      android:icon="@drawable/ic_dashboard"
      android:title="Home" />
    <item
      android:id="@+id/nav_messages"
      android:icon="@drawable/ic_event"
      android:title="Messages" />
    <item
      android:id="@+id/nav_friends"
      android:icon="@drawable/ic_headset"
      android:title="Friends" />
    <item
      android:id="@+id/nav_discussion"
      android:icon="@drawable/ic_forum"
      android:title="Discussion" />
  </group>
  <item android:title="Sub items">
    <menu>
      <item
        android:icon="@drawable/ic_dashboard"
        android:title="Sub item 1" />
      <item
        android:icon="@drawable/ic_forum"
        android:title="Sub item 2" />
     </menu>
  </item>
</menu>

Code Behind Setup

You’re nearly done! All you have to do now is fill in a little bit of code behind to cue click events to open and close the drawer and react when a menu item is selected. You’ll need to locate the DrawerLayout and NavigationView in OnCreate for your Activity, and then add an event handler to the NavigationView’s NavigationItemSelected event. This is triggered when an item is selected, and you will need to set it to “checked” and close the drawer.

DrawerLayout drawerLayout;
NavigationView navigationView;
protected override void OnCreate (Bundle bundle)
{
  base.OnCreate (bundle);

  // Set our view from the "main" layout resource
  SetContentView (Resource.Layout.main_layout);
  var toolbar = FindViewById<Android.Support.V7.Widget.Toolbar>(Resource.Id.toolbar);
  SetSupportActionBar (toolbar);

  //Enable support action bar to display hamburger
  SupportActionBar.SetHomeAsUpIndicator (Resource.Drawable.ic_menu);
  SupportActionBar.SetDisplayHomeAsUpEnabled (true);
			
  drawerLayout = FindViewById<DrawerLayout> (Resource.Id.drawer_layout);
  navigationView = FindViewById<NavigationView> (Resource.Id.nav_view);

  navigationView.NavigationItemSelected += (sender, e) => {
    e.MenuItem.SetChecked (true);
    //react to click here and swap fragments or navigate
    drawerLayout.CloseDrawers ();
  };
}

The only other thing to do now is to tell the drawer layout to open the drawer if the hamburger button is pressed:

public override bool OnOptionsItemSelected (IMenuItem item) 
{
  switch (item.ItemId) 
  {
    case Android.Resource.Id.Home:
      drawerLayout.OpenDrawer (Android.Support.V4.View.GravityCompat.Start);
      return true;
  }
  return base.OnOptionsItemSelected (item);
}

Navigation Drawer In Action in Android Application

So Much More Material

This is only the start of your Material Design adventure. Be sure to check out the Support Design Library’s Getting Started Guide on how to take advantage of native Floating Action Button, Material Tabs, Collapsing Toolbars, and complex animations with CoordinatorLayout.

0 comments

Discussion is closed.

Feedback usabilla icon