Appearance
Shape theming
Material Design encourages brand expression through shapes. The Material Components library offers a shape
library that can be used to create non-standard shapes using a MaterialShapeDrawable
, a Drawable
that can draw custom shapes while taking shadows, elevation, scale and color into account.
On top of the shape library, the Material Components library provides a mechanism with which to easily customize component shapes at the theme level. Shape theming offers a new dimension with which to customize the look and feel of your app.
Design and API Documentation
How it works
MaterialShapeDrawable
and ShapeAppearanceModel
MaterialShapeDrawable
begins with a path generated by a ShapeAppearanceModel
. A ShapeAppearanceModel
is made of CornerTreatment
s and EdgeTreatment
s that combine to create a custom shape path, and is usually passed to a MaterialShapeDrawable's constructor.
The shape
library provides some subclassed CornerTreatment
s and EdgeTreatment
s to make it easy to build new shapes:
Both CornerTreatment
and EdgeTreatment
can be subclassed to create custom corners and edges.
Note: When subclassing CornerTreatment
or EdgeTreatment
, make sure to implement the Cloneable
interface to ensure that the ShapeAppearanceModel
can create deep copies of the corner and edge treatments.
Theming MaterialShapeDrawable
s
Components backed by MaterialShapeDrawable
s can use themes across an application.
Shape styles
Style Name | Description | Corner Sizes |
---|---|---|
ShapeAppearance.Material3.Corner.None | No corners (i.e., fully rectangular) | 0dp |
ShapeAppearance.Material3.Corner.ExtraSmall | Shape with extra small corner size | 4dp |
ShapeAppearance.Material3.Corner.Small | Shape with small corner size | 8dp |
ShapeAppearance.Material3.Corner.Medium | Shape with medium corner size | 12dp |
ShapeAppearance.Material3.Corner.Large | Shape with large corner size | 16dp |
ShapeAppearance.Material3.Corner.ExtraLarge | Shape with extra large corner size | 28dp |
ShapeAppearance.Material3.Corner.Full | Shape with full corner size i.e., circle with rounded corners or rhombus with cut corners | 50% |
These are the shape styles providing the Material 3 shape scale. The shape families in these styles (i.e., cornerFamily
) are mapped to the theme attribute ?attr/shapeCornerFamily
. See the section below for more details.
Shape theme attributes
Theme attributes can be set at the theme level to change the shape values that components use to set their shapes.
Attribute Name | Description | Default Value |
---|---|---|
shapeCornerFamily | The corner family for all shape appearance styles | rounded |
shapeAppearanceCornerExtraSmall | The style reference that contains shape appearance with extra small corners | ShapeAppearance.Material3.Corner.ExtraSmall |
shapeAppearanceCornerSmall | The style reference that contains shape appearance with small corners | ShapeAppearance.Material3.Corner.Small |
shapeAppearanceCornerMedium | The style reference that contains shape appearance with medium corners | ShapeAppearance.Material3.Corner.Medium |
shapeAppearanceCornerLarge | The style reference that contains shape appearance with large corners | ShapeAppearance.Material3.Corner.Large |
shapeAppearanceCornerExtraLarge | The style reference that contains shape appearance with extra large corners | ShapeAppearance.Material3.Corner.ExtraLarge |
Aside from defining these attributes in your theme, you likely will not need to reference these attributes at all; the widget styles are already mapped to the appropriate theme attribute to create a seamless shape theming experience. To change individual shapes throughout your app, you should use the shapeAppearance and shapeAppearanceOverlay attributes rather than redefining theme level attributes.
Note: There is no sanity check for the shape values mapped to these theme attributes. It is the developer's responsibility to guarantee the relative correctness, for example, "medium" is smaller than "large", etc.
Usage
Building a shape appearance
Component shapes are backed by "shape appearances", which are style references that define aspects of the shape. ShapeAppearanceModel
uses the shapeAppearance
style and creates corner and edge treatments out of the shapeAppearance
values.
The following attributes can be used in a shapeAppearance
style:
Attribute Name | Format | Description | Supported Values |
---|---|---|---|
cornerFamily | enum | corner family to be used for all four corners | rounded , cut |
cornerFamilyTopLeft | enum | corner family to be used for the top left corner | rounded , cut |
cornerFamilyTopRight | enum | corner family to be used for the top right corner | rounded , cut |
cornerFamilyBottomRight | enum | corner family to be used for the bottom right corner | rounded , cut |
cornerFamilyBottomLeft | enum | corner family to be used for the bottom left corner | rounded , cut |
cornerSize | dimension|fraction | corner size to be used for all four corners | dimension values, percentage |
cornerSizeTopLeft | dimension|fraction | corner size to be used for the top left corner | dimension values, percentage |
cornerSizeTopRight | dimension|fraction | corner size to be used for the top right corner | dimension values, percentage |
cornerSizeBottomRight | dimension|fraction | corner size to be used for the bottom right corner | dimension values, percentage |
cornerSizeBottomLeft | dimension|fraction | corner size to be used for the bottom left corner | dimension values, percentage |
To build a shapeAppearance
, you need at least a cornerSize
and cornerFamily
value specified for each corner.
ShapeAppearance
and shapeAppearanceOverlay
attributes
Two attributes are provided to set a component's shape style, shapeAppearance
and shapeAppearanceOverlay
:
Attribute Name | Description |
---|---|
shapeAppearance | Style reference that contains shape values that are used to style the component. Should point to a theme attribute style reference such as ?attr/shapeAppearanceCornerExtraSmall . |
shapeAppearanceOverlay | Style reference that contains shape values that layer on top of a shapeAppearance style. This attribute is intended for overrides on top of the themed shapeAppearance shape values, and should map to a custom style reference rather than a themed style reference. |
The shapeAppearanceOverlay
attribute is provided to override components on a case by case basis. This attribute stacks on top of the shapeAppearance
attribute; the shapeAppearance
is read first, and then if there is anything specified in the shapeAppearanceOverlay
attribute, it overrides what’s set in the shapeAppearance
.
Note: shapeAppearance
styles require both cornerSize
and cornerFamily
to be set, while shapeAppearanceOverlay
does not. This means that when defining a custom shapeAppearance
style, you should either inherit from a parent if one exists, or set both cornerSize
and cornerFamily
. However, when defining a style to be used as a shapeAppearanceOverlay
, you should generally set an empty parent by setting parent=""
. This is because shapeAppearanceOverlay
stacks on top of shapeAppearance
, so all values will be set in the shapeAppearance.
Using shapeAppearance
in the theme
The Material Components library supports theming shapes at the application level. To apply theme shapes across your app, specify the shape theme attributes in your theme. This will allow components that support shape theming to read the customized values and change their shapes accordingly.
If you want to change the small and medium corners in your app to cut corners, define the shape theme attributes to point to custom style references that contain shape values:
xml
<style name="Theme.MyApp" parent="Theme.Material3.Light">
...
<item name="shapeAppearanceCornerSmall">@style/ShapeAppearance.MyApp.Corner.Small</item>
<item name="shapeAppearanceCornerMedium">@style/ShapeAppearance.MyApp.Corner.Medium</item>
...
</style>
The shape theme attributes should point to custom shapeAppearance
styles that define both cornerSize
and cornerFamily
. You can either define both attributes in a style from scratch or modify the corner family from a built-in shape style like this:
xml
<style name="ShapeAppearance.MyApp.Corner.Small" parent="">
<item name="cornerFamily">cut</item>
<item name="cornerSize">4dp</item>
</style>
<style name="ShapeAppearance.MyApp.Corner.Medium" parent="ShapeAppearance.Material3.Corner.Medium">
<item name="cornerFamily">cut</item>
<item name="cornerSize">8dp</item>
</style>
Material components that support shape theming use theme attributes according to the themed shape values.
Customizing component shapes
Theme-wide component overrides
You can change a component's shape across the entire app by defining a custom shapeAppearanceOverlay
in the component's style.
If you want to modify MaterialCardView
so that it uses 16dp rounded corners across the entire app, define your own card style to extend from the widget's style, and set the relevant attributes to the desired theme attributes:
xml
<style name="Widget.MyApp.CardView" parent="Widget.Material3.CardView">
<item name="shapeAppearanceOverlay">@style/ShapeAppearanceOverlay.MyApp.CardView</item>
</style>
And define ShapeAppearanceOverlay.MyApp.CardView
:
xml
<style name="ShapeAppearanceOverlay.MyApp.CardView" parent="">
<item name="cornerFamily">rounded</item>
<item name="cornerSize">16dp</item>
</style>
Then make sure to set the component's style in your theme to your custom style:
xml
<style name="Theme.MyApp" parent="Theme.Material3.Light">
...
<item name="materialCardViewStyle">@style/Widget.MyApp.CardView</item>
...
</style>
All cards in your app should now have 16dp rounded corners.
Individual component overrides
You can also change an individual component's shape on a case by case basis. For example, if cards in your theme have 16dp rounded corners, but one card should have 16dp cut corners, you can change that card's cornerFamily
by setting the shapeAppearanceOverlay
attribute on the card in your layout.
Define a custom shapeAppearanceOverlay
style with just the attribute you want to overlay on top of the existing shapeAppearance
. In this case, you would set cornerFamily
to cut
:
xml
<style name="ShapeAppearanceOverlay.MyApp.CardView.Cut" parent="">
<item name="cornerFamily">cut</item>
</style>
Then, set the card's shapeAppearanceOverlay
attribute to that ShapeAppearanceOverlay
style in your layout:
xml
<com.google.android.material.card.MaterialCardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/mtrl_card_spacing"
android:layout_marginTop="@dimen/mtrl_card_spacing"
android:layout_marginRight="@dimen/mtrl_card_spacing"
app:shapeAppearanceOverlay="@style/ShapeAppearanceOverlay.MyApp.CardView.Cut">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/card_text"/>
</com.google.android.material.card.MaterialCardView>
The cornerFamily
attribute set in the shapeAppearanceOverlay
will override the cornerFamily
set in the card's shapeAppearance
, so the card should now have 16dp cut corners instead of 16dp rounded corners.
Supported components
Components that support shape theming have a shapeAppearance
attribute, a shapeAppearanceOverlay
attribute, and are backed by a MaterialShapeDrawable
: