Cards contain content and actions about a single subject. They can be used standalone, or as part of a list. Cards are meant to be interactive, and aren't meant to be be used solely for style purposes.
- Material Design guidelines: Cards
- Class: MDCCard
- Class: MDCCardCollectionCell
- Enumeration: Enumerations
- Enumeration: MDCCardCellHorizontalImageAlignment
- Enumeration: MDCCardCellState
- Enumeration: MDCCardCellVerticalImageAlignment
Cards provides two different versions, MDCCard
inheriting from UIControl
and MDCCardCollectionCell
inheriting from UICollectionViewCell
.
A card's state determines its visual styling.
When treated as a UIControl
(MDCCard
), it has a default styling (UIControlStateNormal
), and a highlighted styling (UIControlStateHighlighted
) when interacted with.
When treated as a UICollectionViewCell
(MDCCardCollectionCell
), it has a default styling (MDCCardCellStateNormal
), a highlighted styling (MDCCardCellStateHighlighted
), and lastly a selected styling (MDCCardCellStateSelected
).
Customization to the card is exposed via its API either in MDCCard
or MDCCardCollectionCell
. Currently the card consists of these customizations:
- The border width for a specific state
- The border color for a specific state
- The shadow elevation for a specific state
- The shadow color for a specific state
- The corner radius for the card
(MDCCardCollectionCell
customization only):
- Changing the image that appears in the Selected state.
- Changing the image tint color that appears in the Selected state.
An MDCCard
can be added and used as you would add any UIView
or UIControl
, if manually in code, or through Interface Builder.
An MDCCardCollectionCell
can be added, used, and reused as a UICollectionViewCell
, if manually in code, or through Interface Builder.
MDCCardThemer exposes apis to theme MDCCard and MDCCardCollectionCell instances as either a default or outlined variant. An outlined variant behaves identically to a default styled card, but differs in its coloring and in that it has a stroked border. Use 'applyScheme:toCard:' to style an instance with default values and 'applyOutlinedVariantWithScheme:toCard:' to style an instance with the outlined values.
MDCCard
subclasses UIControl
and provides a simple class for developers to subclass and create custom cards with ink, shadows, corner radius, and stroke matching the Material spec.
MDCCard
uses the highlighted
property that is built-in in UIControl
and the UIControlState
to move between states.
MDCCardCollectionCell
subclasses UICollectionViewCell
and provides a simple collection view cell for developers to use in their collections with ink, shadows, corner radius, and stroke matching the Material spec.
MDCCardCollectionCell
uses the selected
property that is built-in in UICollectionViewCell
and has its own MDCCardCellState
to keep track of the current state it is in.
Add the following to your Podfile
:
pod 'MaterialComponents/Cards'
Then, run the following command:
pod install
To import the component:
import MaterialComponents.MaterialCards
#import "MaterialCards.h"
MDCCard
can be used like a regular UIView.
let card = MDCCard()
// Create, position, and add content views:
let imageView = UIImageView()
card.addSubview(imageView)
MDCCard *card = [[MDCCard alloc] init];
// Create, position, and add content views:
UIImageView *imageView = [[UIImageView alloc] init];
[card addSubview:imageView];
Use MDCCardCollectionCell
as a base class for your custom collection view cell
collectionView.register(MDCCardCollectionCell.self, forCellWithReuseIdentifier: "Cell")
func collectionView(_ collectionView: UICollectionView,
cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell",
for: indexPath) as! MDCCardCollectionCell
// If you wanted to have the card show the selected state when tapped
// then you need to turn isSelectable to true, otherwise the default is false.
cell.isSelectable = true
cell.selectedImageTintColor = .blue
cell.cornerRadius = 8
cell.setShadowElevation(6, for: .selected)
cell.setShadowColor(UIColor.black, for: .highlighted)
return cell
}
[self.collectionView registerClass:[MDCCardCollectionCell class]
forCellWithReuseIdentifier:@"Cell"];
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView
cellForItemAtIndexPath:(NSIndexPath *)indexPath {
MDCCardCollectionCell *cell =
[collectionView dequeueReusableCellWithReuseIdentifier:@"Cell"
forIndexPath:indexPath];
// If you wanted to have the card show the selected state when tapped
// then you need to turn selectable to true, otherwise the default is false.
[cell setSelectable:YES];
[cell setSelectedImageTintColor:[UIColor blueColor]];
[cell setCornerRadius:8];
[cell setShadowElevation:6 forState:MDCCardCellStateSelected];
[cell setShadowColor:[UIColor blackColor] forState:MDCCardCellStateHighlighted];
}
MDCCard
supports Material Theming using a Container Scheme.
There are two variants for Material Theming of a MDCCard and MDCCardCollectionCell, which are the default theme
and the outlined theme.
// Import the Cards Theming Extensions module
import MaterialComponents.MaterialCards_MaterialTheming
...
// Create or use your app's Container Scheme
let containerScheme = MDCContainerScheme()
// Theme the card with either default theme
card.applyTheme(withScheme: containerScheme)
// Or outlined theme
card.applyOutlinedTheme(withScheme: containerScheme)
// Import the Cards Theming Extensions header
#import <MaterialComponents/MaterialCards+MaterialTheming.h>
...
// Create or use your app's Container Scheme
MDCContainerScheme *containerScheme = [[MDCContainerScheme alloc] init];
// Theme the card with either default theme
[self.card applyThemeWithScheme:containerScheme];
// Or outlined theme
[self.card applyOutlinedThemeWithScheme:containerScheme];
To help ensure your cards are accessible to as many users as possible, please be sure to review the following recommendations:
Since assistive technologies visit all cards in a collection in a sequential order, it is often
easier to distinguish between elements that belong to different cards by aggregating all the
card's information so the card is read as a single sentence.
This can be done by setting an appropriate
accessibilityLabel
for the card. Additionally, set the card's
isAccessibilityElement
to true. Cards are a container element and setting isAccessibiltyElement for a container
turns off individually selecting its subelements.
Swift
card.isAccessibilityElement = true
card.accessibilityLabel = "Location \(userLocation.name) is popular with users " +
"who enjoy \(userLocation.popularActivityMatchingUserProfile(userProfile))"
Objective-C
card.isAccessibilityElement = YES;
card.accessibilityLabel = [NSString
stringWithFormat:@"Location %@ is popular with users who enjoy %@",
userLocation.name,
userLocation.popularActivityMatchingUserProfile(userProfile)];
Nested elements in MDCCards are available to assistive technologies without additional customization, however additional setup may be needed to accommodate special scenarios, such as:
Images that have additional context beyond text that is already presented on the card.
For example, news article images can benefit from an
accessibilityLabel
describing their content.
Swift
articleImageView.isAccessibilityElement = true
articleImageView.accessibilityLabel = "Event or scene description"
Objective-C
articleImageView.isAccessibilityElement = YES;
articleImageView.accessibilityLabel = @"Event or scene description";
Star or rating images should have an
accessibilityLabel
describing its purpuse and an
accessibilityValue
describing the rating value.
Swift
ratingView.isAccessibilityElement = true
ratingView.accessibilityLabel = "Average customer rating, out of " +
"\(MDCProductRating.maximumValue) stars"
ratingView.accessibilityValue = (String)product.averageRating
Objective-C
ratingView.isAccessibilityElement = YES;
ratingView.accessibilityLabel = [NSString stringWithFormat:@"Average customer" +
" rating, out of %d stars", MDCProductRating.maximumValue];
ratingView.accessibilityValue = @(product.averageRating).stringValue;
Primary content or actions that appear lower on the screen will be read last by assistive
technologies, sometimes after longer or non-primary content. To change the order, or group
elements together, you can make the card an accessibility container by adopting the
UIAccessibilityContainer
protocol. Grouping and order is controlled by creating as many
UIAccessibilityElement
elements as needed, and returning them in the desired order.
You can theme a card with your app's color scheme using the ColorThemer extension.
You must first add the Color Themer extension to your project:
pod 'MaterialComponents/Cards+ColorThemer'
// Step 1: Import the ColorThemer extension
import MaterialComponents.MaterialCards_ColorThemer
// Step 2: Create or get a color scheme
let colorScheme = MDCSemanticColorScheme()
// Step 3: Apply the color scheme to your component
MDCCardsColorThemer.applySemanticColorScheme(colorScheme, to: component)
// Step 1: Import the ColorThemer extension
#import "MaterialCards+ColorThemer.h"
// Step 2: Create or get a color scheme
id<MDCColorScheming> colorScheme = [[MDCSemanticColorScheme alloc] initWithDefaults:MDCColorSchemeDefaultsMaterial201804];
// Step 3: Apply the color scheme to your component
[MDCCardsColorThemer applySemanticColorScheme:colorScheme
toCard:component];
You can theme a card with your app's shape scheme using the ShapeThemer extension.
You must first add the ShapeThemer extension to your project:
pod 'MaterialComponents/Cards+ShapeThemer'
// Step 1: Import the ShapeThemer extension
import MaterialComponents.MaterialCards_ShapeThemer
// Step 2: Create or get a shape scheme
let shapeScheme = MDCShapeScheme()
// Step 3: Apply the shape scheme to your component
MDCCardsShapeThemer.applyShapeScheme(shapeScheme, to: component)
// Step 1: Import the ShapeThemer extension
#import "MaterialCards+ShapeThemer.h"
// Step 2: Create or get a shape scheme
id<MDCShapeScheming> shapeScheme = [[MDCShapeScheme alloc] init];
// Step 3: Apply the shape scheme to your component
[MDCCardsShapeThemer applyShapeScheme:shapeScheme
toCard:component];