Missing android material components

Intro

Hello, my name is Dmytro Danylyk, I am developing Android Applications for about 4 years since G1 was released. I am finalist of Google Apps Developer Challenge 2012. I always try to help people on StackOverflow (8 000 reputation points. You may know me from my technical articles or open source libraries, like Process Buttons and Circular Progress Button, maybe some even used them.

Today I want to speak about Missing Android Material Components, which basically means Android Material Components which are present in Google Material Spec, but missing in Android SDK and AppCompat v7 library. Also I will share some gists and tutorials, recipes in general, of how to make those components.

But first, I would like to answer a question, which you will probably ask me.

Why we should write material components ourselves and not use 3rd part libraries?

My answer is - you should always write something yourself, if you have time for this, because it’s safer. Add new feature or fix bug in your own code - always easier.

Here's how things are done in my projects. I have a library module called material-components where I put all my custom material components. For my next project I will just copy / paste this module.

Slide 1

Now let’s get started. As you know Google has released AppCompat v7 library, where we have port of 8 material widgets. Google also released spec about material design for 50+ pages. Fair enough. I think Google want to say something to us:

Here is spec, do it yourself.

That's exactly what we are going to do.

Slide 2

To start cooking we need to prepare Ingredients which will be included almost in all our material component.

Slide 3

AppCompat v7 library not just contains port of some material widgets, it contains a lot of predefined material colors, text sizes and dimensions. Our first ingredient is - Typography which in Material Design has changed.

Slide 3/1

Here you can see sample code of AppCompat.TextAppearance - use them where possible.

Slide 4

Selector - is another important thing which has changed in Material Design. With release of Android Lollipop we now have Ripple Drawable which is used as a selector for all widgets. Unfortunately due to performance issue Ripple Drawable is only available for Android Lollipop. To make selectors look more ‘material like’ I suggest to use Fade Selector.

Slide 4/1

So recipe for selector for Android Lollipop is a Ripple Drawable.

Slide 4/2

And for older versions - Fade Selector. To create Fade Selector you only need to set exitFadeDuration and enterFadeDuration attributes for any of your selectors.

Slide 5

The last ingredient which we will need for today is - shadow. Since objects are placed on top of each other, they have different shadow. We all know in Android Lollipop we have elevation attribute, but what to do for previous versions? I prepared three different recipes, each have their own pros and cons.

Slide 5/1

As you may know Google released CardView library which has cardElevation attribute. This view perfectly draw shadow and uses three different algorithms based on Android version it’s running. However there are some things which are missing:

  • CardView can't draw circle shadow.
  • Not possible to set shadow position.
  • Not possible to set shadow color. (Make shadow darker or lighter).
  • No method to set selector for shadow. (Lift on touch).
Slide 5/2

Second recipe is to use 9.png image as a background. This is a good approach in terms of performance, but:

  • For every component you need shadow image for all drawable-dpi folders.
  • Ton's of resources increase apk size.
  • Not flexible for changes.
Slide 5/3

Third, and my favorite recipe is a custom ShadowLayout which can draw shadow. The reason I made it was to cover all issues of CardView. As you can see you can set shadowRadius and offset to get different type of shadow.

Slide 5/4

With current version you can set shadow color, offset, radius, and corner radius. If you want a circle shadow, just set corner radius the same value as your view size.

Slide 5/5

To draw shadow I am using setShadowLayer method of Paint object. There are two approaches how ShadowLayout can be made.

  • First is to create Bitmap, draw shadow on it, then set this Bitmap as a background of layout.
  • Second to draw shadow on layout canvas (without hardware acceleration)

The layout itself is very simple, only around 100 lines of code. But this doesn't mean it is very efficient. Generating Bitmap or drawing on Canvas without hardware acceleration will cost you some memory.

Slide 5/6

You can find source code and tutorial of ShadowLayout by following this links.

Slide 6

It’s time to start making some simple stuff.

Slide 7

Of course we will start from buttons. In material design we have three types of buttons: Floating Action, Raised and Flat. None of this are available in AppCompat library.

Slide 7/1

Flat button is the simplest.

Slide 7/2

It can be made with a simple style. As a background we will use selector, prepared before. Other stuff you can take from Material Design Spec.

Slide 7/3

Raised Button is little bit more complicated, because it has shadow.

Slide 7/4

Recipe for this button is to wrap Button with CardView and set cardElevation to imitate shadow for pre Lollipop devices.

Slide 7/5

Floating Action Button brings another issue - circle shadow.

Slide 7/6

My recipe for this kind of button is to wrap ImageButton with ShadowLayout, set cornerRadius attribute to the same value as size of FAB to make circle shadow.

Slide 7/7

Now answers to some questions you may have. Again, why we didn't use CardView to make shadow for FAB is because we will get some extra outlines.

Slide 7/8

Why we didn't use .png images? This is most efficient way to draw shadow, but it require set of resources.

Slide 7/9

I prepared tutorials and gists of how to make those buttons, but some are still in progress.

Slide 8

The next thing which we are missing are error labels for EditText.

Slide 8/1

Recipe is pretty simple - custom view group which will wrap EditText, show error label and tint EditText background to red or any other color.

Slide 8/2

However there are some remarks.

  • To tint EditText drawable you can use ColorFilter.
  • EditText background Drawable is not tinted, until EditText remains focus, don't forget to switch focus to other view.
  • For me, implementation of this view toked ~ 100 lines of code so keep it simple Slide 8/3

You can check out tutorials and gist following this links.

Slide 9

Floating label is something similar to error labels, but it appears with animation on top instead of bottom, also we don't need to deal with tinting EditText background.

Slide 9/1

Recipe is also similar - custom view group which will wrap EditText, show floating label when EditText is in focus.

Slide 9/2

Chris Banes prepared great tutorial and gist.

Slide 10

Material dialogs are only available in sdk v21, so to make them look consistent we need to create our own Material Dialog.

Slide 10/1

Recipe is the following - extend Dialog class and set custom content view. As a root layout use either CardView or ShadowLayout . Since Material Dialog can display only title or title and content, can have one, two or three buttons position in different places, it must have several configurable settings. To achieve this you can use Builder pattern as in sample code.

Slide 10/2

Remarks

  • As a root view preferable to use ShadowLayout which gives you darker shadow in comparison with CardView.
  • Material Dialog use lighter dim amount value.
  • For buttons use AppCompat.Button.Flat style (see Flat button section of this presentation).
  • For text style use TextAppearance.AppCompat.Body1 and TextAppearance.AppCompat.Title from appcompat-v7 library.
Slide 10/3

Unfortunately tutorial and gist are still in progress :)

Slide 11

With the release of Material Design, Toast can now have button and his brother - Snackbar is officially documented.

Slide 11/1

Easiest way to make Snackbar is to create class which will add or remove Snackbar's view to activity decor view over all other components. Just as Material Dialog it has several configurable settings, so please consider using Builder pattern.

Slide 11/2

Remarks:

  • To show Snackbar use activity decor view group.
  • For buttons use AppCompat.Button.Flat style (see Flat button section of this presentation).
  • For text style use TextAppearance.AppCompat.Body1 from appcompat-v7 library.
Slide 11/3

Tutorial and gist are still in progress :)

Slide 12

Not all material components can fit in 100 lines of code, some require few days of work. If you lack of time - that’s the case when third-party libraries are handy.

Slide 13

Material Design date and time pickers are complex widgets, which fortunately are available in google open source library.

Slide 13/1

First you need to grab a library from the url above and add it as a library module. API is the same as in native date and time pickers.

Slide 14

Chips View is only available as a third party library based on Google's internal chips library.

Slide 15

In Material Design Spec. progress now has several different states. Determinate and Indeterminate views are available as a third party library.

Slide 16

Material Sliders now have number indicator, available as a third party library, without possibility to modify indicator shape.

Slide 17

There are a lot of material tabs libraries, but all have some issues, like wrong indicator animation, ripple effect instead of reveal etc. I highly recommend to create your own tabs indicator :)

Slide 18

Summary

  • Use CardView or ShadowLayout if you need shadow for pre Lollipop.
  • Almost all third party libraries have issues and only partly imitates Material Design spec behavior.
  • Some components are easy to implement - it is worth it to make your own material-support library and reuse it.
comments powered by Disqus