blob: e8476d1f713209146c68ab529e4a9184cb88c8bd [file] [log] [blame] [view] [edit]
<!--docs:
title: "Shape scheme"
layout: detail
section: components
excerpt: "The Material shape scheme provides support for theming an app with a set of custom shapes."
iconId: themes
path: /catalog/theming/shape/
api_doc_root: true
-->
<!-- This file was auto-generated using scripts/generate_readme schemes/Shape -->
# Shape scheme
The Material Design shape system can be used to create a shape theme that reflects your brand or
style.
## Related Documentation
<ul class="icon-list">
<li class="icon-list-item icon-list-item--link"><a href="../">Theming</a></li>
</ul>
## Table of contents
- [Overview](#overview)
- [Shape Values](#shape-values)
- [Shape to Component Mapping](#shape-to-component-mapping)
- [Installation](#installation)
- [Installation with CocoaPods](#installation-with-cocoapods)
- [Importing](#importing)
- [Usage](#usage)
- [Typical use: customizing a shape scheme](#typical-use-customizing-a-shape-scheme)
- [Component content awareness when using custom shapes](#component-content-awareness-when-using-custom-shapes)
- - -
## Overview
An implementation of the Material Design shape scheme is provided in the `MDCShapeScheme`
class. By default, an instance of this class is configured with the Material defaults.
The following image shows an MDCButton themed with the default
shape scheme values (bottom) and an MDCButton themed with custom shape scheme values (top).
<img src="docs/assets/shapethemedbuttons.png" width="144" alt="An MDCButton themed with the default shape scheme and a custom one.">
Currently, 5 components support being themed with a shape scheme using a `shape themer` extension, namely Cards, Buttons, FABs, Chips,
and Bottom Sheet. You can learn more about which extensions are available for a given component by reading the
[component documentation](../../).
### Shape Values
A shape scheme consists of the following shape values:
| Shape Category | Use |
|:--------------------- |:---------- |
| `smallComponentShape` | The shape defining small sized components. |
| `mediumComponentShape` | The shape defining medium sized components. |
| `largeComponentShape` | The shape defining large sized components. |
Each of the shape categories are of the class `MDCShapeCategory`.
An `MDCShapeCategory` holds properties that define a shape value. It consists of 4 corners of type `MDCCornerTreatment` that represent each corner of the shape. It also has a convenience initializer to set all the 4 corners at once to the same value, creating a symmetrical shape.
Lastly, an `MDCCornerTreatment` can be set by using any of the convenience initializers in [MDCCornerTreatment+CornerTypeInitializer.h](https://github.com/material-components/material-components-ios/blob/develop/components/private/ShapeLibrary/src/MDCCornerTreatment%2BCornerTypeInitalizer.h).
### Shape to Component Mapping
<!-- Extracted from docs/shape-category-mapping.md -->
Below is a table showing how our shape categories are mapped to each component.
| Small Components | Medium Components | Large Components |
|------------------|-------------------|----------------------------|
| Button | Card | Bottom Sheet (modal) |
| Chip | Dialog | Navigation Drawer (bottom) |
| Extended FAB | | |
| FAB | | |
| Snackbar | | |
| Textfield | | |
## Installation
### Installation with CocoaPods
Add the following to your `Podfile`:
```bash
pod 'MaterialComponents/schemes/Shape'
```
<!--{: .code-renderer.code-renderer--install }-->
Then, run the following command:
```bash
pod install
```
### Importing
To import the component:
<!--<div class="material-code-render" markdown="1">-->
#### Swift
```swift
import MaterialComponents.MaterialShapeScheme
```
#### Objective-C
```objc
#import "MaterialShapeScheme.h"
```
<!--</div>-->
## Usage
<!-- Extracted from docs/typical-use-customizing-a-scheme.md -->
### Typical use: customizing a shape scheme
You'll typically want to create one default `MDCShapeScheme` instance for your app where all
of the shape properties are set to your desired brand or style.
<!--<div class="material-code-render" markdown="1">-->
#### Swift
```swift
let shapeScheme = MDCShapeScheme()
// Small Component Shape
shapeScheme.smallComponentShape = MDCShapeCategory(cornersWith: .cut, andSize: 4)
// Medium Component Shape
shapeScheme.mediumComponentShape = MDCShapeCategory(cornersWith: .rounded, andSize: 10)
// Large Component Shape
let largeShapeCategory = MDCShapeCategory()
let rounded50PercentCorner = MDCCornerTreatment.corner(withRadius: 0.5,
valueType: .percentage)
let cut8PointsCorner = MDCCornerTreatment.corner(withCut: 8)
largeShapeCategory?.topLeftCorner = rounded50PercentCorner
largeShapeCategory?.topRightCorner = rounded50PercentCorner
largeShapeCategory?.bottomLeftCorner = cut8PointsCorner
largeShapeCategory?.bottomRightCorner = cut8PointsCorner
shapeScheme.largeComponentShape = largeShapeCategory
```
#### Objective-C
```objc
MDCShapeScheme *shapeScheme = [[MDCShapeScheme alloc] init];
// Small Component Shape
shapeScheme.smallComponentShape =
[[MDCShapeCategory alloc] initCornersWithFamily:MDCShapeCornerFamilyCut
andSize:4];
// Medium Component Shape
shapeScheme.mediumComponentShape =
[[MDCShapeCategory alloc] initCornersWithFamily:MDCShapeCornerFamilyRounded
andSize:10];
// Large Component Shape
MDCShapeCategory *largeShapeCategory = [[MDCShapeCategory alloc] init];
MDCCornerTreatment *rounded50PercentCorner =
[MDCCornerTreatment cornerWithRadius:(CGFloat)0.5 valueType:MDCCornerTreatmentValueTypePercentage];
MDCCornerTreatment *cut8PointsCorner = [MDCCornerTreatment cornerWithCut:8];
largeShapeCategory.topLeftCorner = rounded50PercentCorner;
largeShapeCategory.topRightCorner = rounded50PercentCorner;
largeShapeCategory.bottomLeftCorner = cut8PointsCorner;
largeShapeCategory.bottomRightCorner = cut8PointsCorner;
shapeScheme.largeComponentShape = largeShapeCategory;
```
<!--</div>-->
## Component content awareness when using custom shapes
<!-- Extracted from docs/shape-content-margins.md -->
Choosing a shape value for your shape scheme or component has an effect on the component's content.
As an example, we may choose the `smallComponentShape` category to have a cut corner treatment at a 50% value of its height.
That will create a diamond-like shape, which in certain cases is likely to clip content.
In other cases, such as with dynamic type, or a typography scheme with large fonts, even a less intrusive shape could potentially cut out content.
Therefore, it is recommended to be mindful of how a custom shape manipulates the component and if that shape makes sense for your specific case.
One recommendation is to use the built-in UIView’s `layoutMargins`. By setting it to a custom `UIEdgeInset` you can get the desired outcome for your content when using a custom shape.