Material Design Everywhere, Using the Android Support Libraries

Building a Grid Layout With RecyclerView and Realm

Building an app with RecyclerView? Realm Java is an easy way to power a list or grid, and supports any type of data you can design. See how simple it is!

The introduction of Material Design was one of the more exciting things to happen to Android in recent years. The specifications describe a beautiful UI, but it can be challenging for developers to implement, particularly if they must support backwards compatibility. It is now easy to support the “Material” with the release of the ‘Android Design Support Library’ (and the previously released ‘AppCompat Library’). Developers now have the tools that make it simple to create Material-compliant apps that will work and look great on almost all devices (even ones running Eclair or Froyo). In this presentation Mike Wolfson highlights some important components of these libraries and demonstrates how to use them effectively. It is just the beginning for Material design - come learn about the important tools that make it easy to be part of the revolution!


Introduction (00:00)

I’m Mike Wolfson (see my book). I’m a Google developer expert, which gives me internal views into how they pick apps to be featured in the Play store (they are very rigorous). If your app is not compliant to the Material Design spec, it will not be featured in the Play store. At a minimum your app has to be Material Design compliant, then they pick out all sorts of tiny little things to make sure your app is awesome, but if you don’t use Material Design, they will not even consider you.

Lazy development is the best development. Material Design, getting all this stuff to look right can be hard. However, using the Material Design support libraries allows us to be lazy and spend more time on the Internet. The last and probably the most critical reason you should use Material Design? Your app needs to look right on Android.

Material Design (01:39)

The Material Design specs are created to provide a cohesive design language for the entire phone. Your app needs to match that: it is important that your app looks like it is supposed to look and that it fits on Android.

Material Design is a specification for a design language. It defines criteria regarding layouts, fonts, colors and motion interaction patterns. It is a spec, it only describes the design language of what it is suppose to look like. It does not include any of the information on how you are supposed to accomplish that. At Google, they created a top-level domain for this, where you will find the Material Design spec, which includes more design language than you could ever hope to learn about.

Material Color Specification (03:02)

If you went to that website, you would see information about: colors, styles, metrics, interaction patterns, how navigations work, how different elements interact with each other; as well as definitions of various components that you are supposed to use, e.g. the featured action button, navigationView, some of the other main controls that define Material Design.

A good example is colors. If you go to the Material Design spec, they have created a palette of different colors. Main colors (indigo or pink) are defined, and a palette within that color allows you to specify different shades. I wrote this project to support this app. In that project I’ve abstracted each of the colors and created that palette, being able to reference these colors directly (e.g. indigo_600).

We know that they have defined these colors, but we do not know what those colors are used for. If you go to the Material Design spec, it defines this Material Design color palette that they have specified for an app. It has a primary, a primaryDark and an accent color. If you want to use these color palettes, you have to define those color palettes within your styles. Then the system will automatically color your app based on that branding. We have now universally branded both our app, and it brands the system colors on certain OS levels. In the old days we had to color each of our views independently, and style every view. Now it is universally styled by the system.

This is how I would color it if I wanted to have a primarily blue color palette. I use blue 500, blue 700, and an accent color of a yellow. It is automatically colored for me. If I wanted to change the color palette of my entire app, I would change the specifications of those colors in my style. We are now branding our app universally (instead of all this tedious stuff that does not allow us to be lazy).

Typography - Material Defined Styles (06:33)

Instead of creating manual font specifications for each of the different use cases within our app, we can now use these universal font styles (universal throughout the whole app). If app A is using title, we know that it is going to be a medium 20sp font for example. To reference one of these new font styles, you would add that as a style attribute to your text.

Start: Dependencies (07:25)

Support libraries: Android has multiple OSs that are developed and released to the public. However, due to a variety of factors (e.g. manufacturer or carrier resistance), it is difficult to get those phones that are out in the field updated. We know that there are barriers to get the latest version of Android on your phone. This can be a problem for Google because they are not able to push out their new hotness and new code features to all those old phones. To solve this issue, they created a library (not third-party because they are Google) that is a shim layer: it allows us to use all these features on older versions of the phone. If we could release the jar with our package, and if that feature we are showing does not exist natively, it will use the support lib to support those features. In sum, this is a shim layer that allows Google to backport functionality to be used on older versions of their OS.

If you want to get started using AppCompat, add the two dependencies (basic levels). Once you have added those dependencies, you will then add other dependencies based on the different products and features you need. You add the two base libraries and, if you want to use CardView or RecyclerView (something like that), you add those dependencies as secondary dependencies.

Once you have added the dependencies, you will need to add the name spaces to your XML. This allows the different attributes to be discovered in the XML.

AppCompatActivity (09:13)

You will also need to extend AppCompatActivity. This is new: we used to have to extend Action Bar activity, they have changed that to AppCompatActivity. You need to make those changes: Add the style colors to your style, add the dependencies, and extend AppCompatActivity. Then all the magic starts to happen for you.

public class MainActivity extends AppCompatActivity {

Tint Aware Widgets (10:04)

I want to dig into what the library provides, and some of the core functionality. AppCompat provides tint-aware widgets: when I specify that color in my style universally throughout the app, those will be automatically styled and colored appropriately for me. That is, universally styling each of my different widgets.

RecyclerView (10:43)

RecyclerView is similar to the ListView we are all used to… except not at all.

RecyclerView is a new ListView that has additional functionality built in to allow us to add values to our lists, and it will automatically animate those values when they are inserted, remove them, and reorder them.

RecyclerView is powerful and extensible, but it is harder to use. For instance, you can change how your list is laid out (e.g. from vertical to horizontal), or even multiple columns, by specifying a LayoutManager. You can’t do this in a ListView, you have a vertical ListView and that’s it. Now we have multiple styles of ListView with RecyclerView, but we have to do manual stuff to make that happen, which is more complicated, but more powerful. There is also ItemDecorators, which you would use to add decoration to each of the elements in your list items (e.g. adding a list divider).

Palette (12:17)

Palette is a cool library that allows us to send any image into the palette, and the palette will return a list of colors from that image that we can then use in our code. In my app, I have a title in white that would not show up on a majority of the different images because these are all primarily white background images. I send the image into Palette, and I then set the title to vibrant - now I know it is contrasting with that image and it will show up. Also, this works (including RecyclerView) all the way back to Gingerbread phones, 2.3 OS, a tiny percentage of the market. It is remarkable that Google is able to provide all this functionality and backport it to use it universally in all of our apps.

CardView (13:35)

An important part of Material Design is elevation. One of the key components of Material Design is there is an X-axis and a Y-axism abd we’re used to that. But they have also added a Z-axis where you can take views and “elevate” them off the screen. CardView is one great way to do that – you can now set elevations directly into CardView, which will allow you to then elevate that card off the screen.

I have this example from two different phones, a non-supported (S4) and a supported phone (MotoX). You can see how the shadows and the lighting effects are powerful, well done and works everywhere. I can’t tell the difference between the two, although there are some differences.

MediaRouter (14:33)

If you are writing a media app, it can be complicated when a phone call comes in to silence your media, or if another media app takes control. MediaRouter will take that hard work of routing the media into the support lib, so you don’t have to worry about silencing your app, or even taking priority. If you are using a media app, it’s something useful to work with.

Vector Graphics (15:10)

Vector graphics are a way to define a graphic element in XML using language. It has a bunch of points, and it says draw a line from 0.0 to 0.10, and then draw another line, etc. If you use a raster graphic like PNG, as Android developers, in order to provide image assets that look good everywhere, we have to provide multiple sizes of them, HDPI, XHDPI. That can be challenging, and also adds bloat to your app. We can now define these vector assets, include them in our code, and size them. If you want to add vector graphics to your code, you have to add this line and then you can just add those drawables by referencing them just as you would reference any other drawable with srcCompat attribute name. Once you have done that, you can specify multiple sizes and the images will be sized correctly without jaggedness. When they started to use vectors in the support libraries themselves, they cut out 9% of their app size by replacing raster graphics with vectors. There is opportunity to save app bloat, but also the hassle of organizing multiple PNGs, and getting those to look right. This is only available now in 23.01 however.

android {
    compileSdkVersion 23
    buildToolsVersion "23.0.1"

    defaultConfig {
        //...
        vectorDrawables.useSupportLibrary = true
}
<ImageView
    android:layout_width="36dp"
    android: layout_height="36dp"
    android:layout_gravity="center_horizontal"
    app:srcCompat="@drawable/bugdroid"
    tools:ignore="MissingPrefix"/>

Design

AppCompat is the core. Design library is the fancy UI that will make the Material Design pop.

navigationView is that sidebar that is used for navigation. It is also a good example to show how the support libraries work and how they take the hard work away from us. If you went to the design specifications, you would see there are intense definitions for how a navigation UI is supposed to look. They’re very specific about how the icons are supposed to be sized, how far away from the sides the margins are supposed to be, and your key line. To make that look right on your own would be difficult.

There is a control called the NavigationView Control in Android that allows you to specify your menu items in XML (like you did for an Action Bar or a menu). You have to specify the action, @drawable. Then, the OS itself generates the NavigationView for you (magically!). For instance, it adds the the gray highlight when I select an item. It colors both the icon and the text based on my system colors. And of course then it lays out everything exactly how it is supposed to be. For example I can be sure that an icon is exactly 16dp away from the side because I know that the Google guys have taken care of that. All I have to do is define some simple XML, and all the magic happens for me.

<menu xmlns:android="http://schemas.android.com/apk/res/android"

<group android:checkableBehavior="single">
    <item
        android:id="@+id/nav_home"
        android:icon="@drawable/ic_android"
        android:title="OS Versions" />
    <item
        android:id="@+id/nav_devices"
        android:icon="@drawable/ic_device"
        android:title="Devices" />
    <item
        android:id="@+id/nav_favorites"
        android:icon="@drawable/ic_favorite_on"
        android:title="Favorites" />
    <item
        android:id="@+id/nav_userinfo"
        android:icon="@drawable/ic_account"
        android:title="User Settings" />
</group>

A question I commonly hear about the NavigationView is, “How do I add a custom X to my navigation view?” The answer is, “You do not.” Several of these design controls are purposely non-extensible and fixed in their usage by design. You are not supposed to change the navigation. The side navigation is a pattern that Google is trying to enforce, and it needs to look the same on every app. This is a common navigation pattern; they make it purposely difficult for you to change it - when you come up against that, think twice about why you are changing it. The answer is “No!, you should not,” and if your designer is asking you to do something, send him to the design spec and say “Material Design does not support this. I think it’s a bad idea, and Mike Wolfson said so too.”

Widgets (20:53)

Some additional widgets that are created:

  • TextInputLayout provides nice animations when you click inside of a TextView. That visual feedback is useful. You only need to add this XML, a standard edit text.
  • Featured Action Button (FAB), that circle that you are supposed to put on your screen that is supposed to be your one magic item, your main action. This was hard to write before, but they have now given us a FAB control that allows us to do powerful stuff (see below).
  • Snackbar is this toast message on the bottom that gives you status, and a way to select stuff.
  • Dialogues and SwitchCompat. SwitchCompat has a nice animation and it is colored specifically and when you press it, it animates over and back. The alert dialogues are all standard. Use those standard alert dialogues, and then you know that your patterns match.

Coordination Layout (22:45)

Coordinator Layout is a main layout that you add to your main views, and it allows the views within that screen to interact with each other. It’s very easy to animate the FAB. Inside of my Coordinator Layout, I can add an anchor and tell that FAB to anchor to another view or to be associated with another view. Coordinator Layout assigns a view to listen to the scroll behaviors of a different view. Once the other view is scrolling it says, “I need to scroll too” or “I need to do something.” It is powerful to be able to tie two views together that can either scroll together or separately based on some unique pattern.

AppBar (24:31)

This is a good example showing how the Froyo API level title is a different color. When I scroll the view, the title bar up at the top both parallaxes out and fades out, and then the title also animates in and out. We have views animating in and out, views paralleling in and out, we have that title, that is shrinking and expanding, vibrant, valuable. And we do not have to do anything; all we do is we use the app collapsing toolbar layout controls.

Hopefully you are starting to see that there are visual patterns that provide interactivity and powerful graphics.

Percent Layout (25:52)

Percent Layout is something they’ve had in web dev forever that we have now too. You can specify a layout based on a percentage of your total screen. This was never possible before in Android, and it was difficult to do complex user interfaces because of it. Now we have percent layouts and we can specify, “I want this to be 60% and 20%.”

I want to show one example that I used recently:

<android.support.percent.PercentFrameLayout
    android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_centerVertical="true">
    <com.tmm.views.CustomVideoView
        tools:ignore="LayoutHeight" android:id="@+id/custom_video_view" app:layout_heightPercent="7096" app:layout_aspectRatio="17096" />.
</android.support.percent.PercentFrameLayout>

I work on an app that has a video control, and our view was set up as an absolute size. It was set up on the screen to 16dp from full-width of the screen and a margin on the sides. The problem is that Android screens are all different sizes: my viewport was always a different size, sometimes I had no control over how that video port was set up. Now, I am able to use two different things. I created this aspect ratio to set up the layout to be 16:9. Instead of trying to determine based on the actual screen real estate what size that is, I can just specify a percentage and the system itself does that. Now I have this viewport and I know it is always 16:9. I can just specify a percentage of the height that I want. Before, in order to get that view to be static and sized accurately, I would have had to create multiple resolutions for different devices, or calculate percentages manually within the code at runtime which can get hairy. Having figured this out, I get to walk away; I know it works, and it works well everywhere. I do hope that you learned that using the support libraries is the easiest way to get to Material Design.

I encourage you to go to this app and check out the open-source code. I originally forked this from Chris Bane’s Cheesesquare Material Design demo app, and extended it a bit so that it has everything you just saw, hopefully created in a simplistic manner with clear and basic examples.

Q&A (28:45)

Q: A cool thing I learned from your talk is the percent layout. You showed an example with percent layout and I think it was percent frame layout with a text view in it. Is there any possibility to use a more complex view, say I want to just refer a menu item, or a very restricted RecyclerView within the PercentRelativeLayout? Is that a possibility, or it has a limitations of basic views?

Mike: No, I think you could use it within any container, because all it is a relative layout. It is a special type of relative layout. Anywhere you can use a relative layout, I think you could use the percent relative layout. There is also a percent frame layout, obviously relative layout has more usability. But I do not think there are any limitations that I have discovered. The CardView example has a text view and two different percentage layouts inside of it, and it works.

Q: Thanks for the great presentation. I have a question about PercentRelativeLayout. For your project, you said 178% for the 16:9 ratio, I was wondering, how did you calculate that number? How did I figure that out? How does that number relate to 16:9?

Mike: I think that 16 divided by 9 is that 1.78:1 ratio, so 16 is 178% of 9. But I found that from an example, because it is a common use case to need this fixed viewport size.

Q: Great presentation. I have always wondered about the AppCompat libraries. Should you use them all the time, or how would you do that?

Mike: Absolutely yes, and here is the reason why. AppCompat backports all this functionality to work on older OS’s. You know that you can use it, and support all the way back to the older versions. But, if you are on a device that does support these things natively, AppCompat will not use native, it will go to the native shims. You always want to use AppCompat because if it is supported natively, you will not use it. The phone itself knows, “this stuff is native, I want to use the good stuff not the AppCompat stuff”.

Q: I was wondering because I know some people who will not support anything below 4.0. They would not use AppCompat.

Mike: But even so, the functionality in AppCompat is not available as far back as 4.0. That is pretty common now – not many people are supporting 2.3. I looked at one of my representative apps that has a huge population of users, and there are only 2% of people that are using 2.3 phones, so we do not really care about that. But even the 4.0. phones and 4.1, I think 15 is the new base. Many of the functionality we talked about is not backported all the way there, such as percentage layout for example. I advocate using it everywhere.


Mike Wolfson

Mike Wolfson

Mike is a passionate mobile designer/developer working out of Phoenix. He has been working in the software field for more than 20 years, and with Android since its introduction. Currently, he develops Android applications for an IoT startup, in the health care space. He is a Google Developer Expert in Android, and the author of the book "Android Developer Tools Essentials" published by O’Reilly. Mike has spoken about Android and mobile development at a variety of conferences and user groups (including Oscon, GDGSiliconValley, Droidcon NYC & Turin, AnDevCon, and others). When he is not geeking out about phones, he enjoys the outdoors (snowboarding, hiking, scuba diving), collecting PEZ dispensers, and chasing his young (but quick) daughter.