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
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 & API documentation
How it works
MaterialShapeDrawable begins with a path generated by a
ShapeAppearanceModel is made of
EdgeTreatments that combine to create a custom shape path, and is usually
passed to a MaterialShapeDrawable's constructor.
shape library provides some subclassed
EdgeTreatments to make it easy to build new shapes:
EdgeTreatment can be subclassed to create custom
corners and edges.
Note: When subclassing
EdgeTreatment, make sure to
Cloneable interface to ensure that the
can create deep copies of the corner and edge treatments.
Components backed by
MaterialShapeDrawables can use themes across an
Shape theme attributes
Theme attributes can be set at the theme level to change the shape values that components use to set their shapes.
Note: These theme attributes will be deprecated soon for Material 3. New theme attribtues will be added and components styles will be updated to reference them, according to the new shape system guidelines coming soon.
|Attribute Name||Description||Default Value|
||Style reference that contains shape values that are used to style small components||4dp rounded|
||Style reference that contains shape values that are used to style medium components||8dp rounded|
||Style reference that contains shape values that are used to style large components||8dp rounded|
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.
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
The following attributes can be used in a
|Attribute Name||Format||Description||Supported Values|
||enum||corner family to be used for all four corners||rounded, cut|
||enum||corner family to be used for the top left corner||rounded, cut|
||enum||corner family to be used for the top right corner||rounded, cut|
||enum||corner family to be used for the bottom right corner||rounded, cut|
||enum||corner family to be used for the bottom left corner||rounded, cut|
||dimension||corner size to be used for all four corners||
||dimension||corner size to be used for the top left corner||
||dimension||corner size to be used for the top right corner||
||dimension||corner size to be used for the bottom right corner||
||dimension||corner size to be used for the bottom left corner||
To build a
shapeAppearance, you need at least a
cornerFamily value specified for each corner.
Two attributes are provided to set a component's shape style,
||Style reference that contains shape values that are used to style the component. Should point to a theme attribute style reference such as
||Style reference that contains shape values that layer on top of a
shapeAppearanceOverlay attribute is provided to override components on a
case by case basis. This attribute stacks on top of the
shapeAppearance is read first, and then if there is anything
specified in the
shapeAppearanceOverlay attribute, it overrides what’s set in
shapeAppearance styles require both
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
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 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 components' corners in your app to cut corners, define the shape theme attributes to point to custom style references that contain shape values:
<style name="Theme.MyApp" parent="Theme.Material3.Light"> ... <item name="shapeAppearanceSmallComponent">@style/ShapeAppearance.MyApp.SmallComponent</item> <item name="shapeAppearanceMediumComponent">@style/ShapeAppearance.MyApp.MediumComponent</item> <item name="shapeAppearanceLargeComponent">@style/ShapeAppearance.MyApp.LargeComponent</item> ... </style>
The shape theme attributes should point to custom
shapeAppearance styles that
might look something like this:
<style name="ShapeAppearance.MyApp.SmallComponent" parent="ShapeAppearance.Material3.SmallComponent"> <item name="cornerFamily">cut</item> <item name="cornerSize">4dp</item> </style> <style name="ShapeAppearance.MyApp.MediumComponent" parent="ShapeAppearance.Material3.MediumComponent"> <item name="cornerFamily">cut</item> <item name="cornerSize">8dp</item> </style> <style name="ShapeAppearance.MyApp.LargeComponent" parent="ShapeAppearance.Material3.LargeComponent"> <item name="cornerFamily">rounded</item> <item name="cornerSize">4dp</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:
<style name="Widget.MyApp.CardView" parent="Widget.Material3.CardView"> <item name="shapeAppearanceOverlay">@style/ShapeAppearanceOverlay.MyApp.CardView</item> </style>
<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:
<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
<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:
<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>
cornerFamily attribute set in the
shapeAppearanceOverlay will override
cornerFamily set in the card's
shapeAppearance, so the card should now
have 16dp cut corners instead of 16dp rounded corners.
Components that support shape theming have a
shapeAppearance attribute, a
shapeAppearanceOverlay attribute, and are backed by a