mirror of
https://github.com/material-components/material-components-android.git
synced 2026-02-11 06:03:44 +08:00
303 lines
16 KiB
Markdown
303 lines
16 KiB
Markdown
<!--docs:
|
||
title: "Shape Theming"
|
||
layout: detail
|
||
section: theming
|
||
excerpt: "Shape Theming"
|
||
iconId: shape
|
||
path: /theming/shape/
|
||
-->
|
||
|
||
# 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
|
||
|
||
- [Material Design 3 guidelines: Shape](https://m3.material.io/styles/shape/overview)
|
||
|
||
## 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:
|
||
|
||
- [`CutCornerTreatment`](https://developer.android.com/reference/com/google/android/material/shape/CutCornerTreatment)
|
||
- [`RoundedCornerTreatment`](https://developer.android.com/reference/com/google/android/material/shape/RoundedCornerTreatment)
|
||
- [`TriangleEdgeTreatment`](https://developer.android.com/reference/com/google/android/material/shape/TriangleEdgeTreatment)
|
||
|
||
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.LargeIncreased` | Shape with increased large corner size | 20dp
|
||
`ShapeAppearance.Material3.Corner.ExtraLarge` | Shape with extra large corner size | 28dp
|
||
`ShapeAppearance.Material3.Corner.ExtraLargeIncreased` | Shape with increased extra large corner size | 32dp
|
||
`ShapeAppearance.Material3.Corner.ExtraExtraLarge` | Shape with extra extra large corner size | 48dp
|
||
`ShapeAppearance.Material3.Corner.Full` | Shape with full corner size </br> 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`
|
||
`shapeAppearanceCornerLargeIncreased` | The style reference that contains shape appearance with slightly increased large corners | `ShapeAppearance.Material3.Corner.LargeIncreased`
|
||
`shapeAppearanceCornerExtraLarge` | The style reference that contains shape appearance with extra large corners | `ShapeAppearance.Material3.Corner.ExtraLarge`
|
||
`shapeAppearanceCornerExtraLargeIncreased` | The style reference that contains shape appearance with slightly increased extra large corners | `ShapeAppearance.Material3.Corner.ExtraLargeIncreased`
|
||
`shapeAppearanceCornerExtraExtraLarge` | The style reference that contains shape appearance with extra extra large corners | `ShapeAppearance.Material3.Corner.ExtraExtraLarge`
|
||
|
||
### Corner family and corner sizes
|
||
|
||
Shape role | Android attribute | values
|
||
--------------------------------- | ---------------------------------- | -------
|
||
Corner Family | shapeCornerFamily | Rounded
|
||
Corner Size Extra Small | shapeCornerSizeExtraSmall | 4dp
|
||
Corner Size Small | shapeCornerSizeSmall | 8dp
|
||
Corner Size Medium | shapeCornerSizeMedium | 12dp
|
||
Corner Size Large | shapeCornerSizeLarge | 16dp
|
||
Corner Size Large Increased | shapeCornerSizeLargeIncreased | 20dp
|
||
Corner Size Extra Large | shapeCornerSizeExtraLarge | 28dp
|
||
Corner Size Extra Large Increased | shapeCornerSizeExtraLargeIncreased | 32dp
|
||
Corner Size Extra Extra Large | shapeCornerSizeExtraExtraLarge | 48dp
|
||
|
||
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](#shapeappearance-and-shapeappearanceoverlay-attributes)
|
||
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](#supported-components) 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`:
|
||
|
||
* [Bottom Sheet](../components/BottomSheet.md)
|
||
* [Card](../components/Card.md)
|
||
* [Chip](../components/Chip.md)
|
||
* [Date Picker](../components/DatePicker.md)
|
||
* [Dialog](../components/Dialog.md)
|
||
* [Extended Floating Action Button](../components/FloatingActionButton.md?#extended-fabs)
|
||
* [Floating Action Button](../components/FloatingActionButton.md)
|
||
* [Button](../components/Button.md)
|
||
* [Time Picker](../components/TimePicker.md)
|
||
* [Navigation Drawer](../components/NavigationDrawer.md)
|
||
* [Slider](../components/Slider.md)
|
||
* [Snackbar](../components/Snackbar.md)
|
||
* [Text Field](../components/TextField.md)
|