Material Design / Material Shape

Material Shape: ShapeAppearance

One of the foundations of Material Design 2.0 is the ability to define shapes to reinforce the branding being applied to our apps. At first glance what we are able to control appears to be somewhat limited, but in this short series we’ll go deeper down the rabbit hole to explore some of the more subtle things that we can do with material shape.

Let’s start by looking at the holistic approach to applying shapes to our app: via the theme. This is the way that may apps will apply shape as it is the easiest and fastest way to consistently apply custom shapes across the entire app. The basic principles that shape themeing operates on is that all material components which support custom shapes will in to one of three size buckets: small, medium and large. Small components are generally discrete widgets such as buttons, text fields, tooltips and snackbars. Medium components are usually containers for these small items such as cards, dialogs, and menus. Large components are larger containers such as navigation drawers and bottom sheets. For the vast majority of cases, defining the shapes for these three size buckets will be all most apps need, so we’ll begin by looking at how we can do this.

To apply shapes to our theme we need to define styles for the three size bucket theme attributes:



We’ll look at the contents of the style definitions in a moment, but what we have here does an awful lot for us. Whenever one of the Material components that falls in to the ‘small’ size bucket is inflated, it will look up the value of shapeAppearanceSmallComponent from the theme and use that to define the shape of the view. That is unless the shapeAppearance is explicitly specified in the layout, or any of the shape attributes are overriden in the layout. This behaviour is nothing specific to material shapes (although it is the shape appearance that is being affected) but it is how styles and theme work in general. Any view will try and find a default style from the theme by looking up the value of a specific theme attribute, and that is precisely what is happening here.

Let’s now take a look at the style definitions:



Although this initially looks fairly simple, there is some clever stuff going on in these few lines. The first is hinted at by the base theme: ShapeAppearanceOverlay. This is working as a ThemeOverlay (which, once again, is not specific to Material shapes, but is a behaviour of the themeing framework). The overlay behaviour isn’t immediately obvious from this declaration because the overlay behaviour is actually implemented by the base ShapeAppearanceOverlay definition – that’s why it it is important that it contains the word Overlay in its name so that its name reflects its behaviour.

Although the concept of a ThemeOverlay is not specific to material shapes, it is worth a brief explanation of these because the behaviour that we’re looking at is dependent on the ThemeOverlay behaviour. Let’s dive in to ShapeAppearanceOverlay which is defined in the material components styles as:

In this case we declare a separate cornerFamily which only affects the top right corner which results in this:

All in all this is pretty flexible, and correctly defining shapes at theme level is an easy win for consistently defining a shape identity across the entire app. That said there are some gotchas that can causing things to break, and there are also some further customisations that we can do. We'll explore these further in the next article.

The source code for this article is available here.

© 2020, Mark Allison. All rights reserved.

Copyright © 2020 Styling Android. All Rights Reserved.
Information about how to reuse or republish this work may be available at

1 Comment

  1. Great article! I was especially glad to find out how to correctly generate shadows. Now I know you’ve got to change the Material shape, not just use a custom background.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.