Hands-on with Material Components for Android: Cards

Part 6 of a series covering practical usage of Material Components for Android

Nick Rout
Over Engineering

--

This post will be covering the features and API of Card components. To find out how to handle initial setup of Material Components for Android (including the Gradle dependency and creating an app theme), please see my original post:

Cards are sheets of surface material that contain content and actions related to a single subject. This content may include text, images, links and more, and may vary in size. While there are many patterns and variations in terms of content layout, the only required element is the card container.

Basic usage 🏁

A MaterialCardView can be included in your layout like so:

<FrameLayout
...
>

<com.google.android.material.card.MaterialCardView
android:id="@+id/card"
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<!-- Card contents --> </com.google.android.material.card.MaterialCardView></FrameLayout>

Checking ☑️

A MaterialCardView can be checked to indicate selection. There is no default behavior for enabling/disabling checked state; this can be done in response to long press, for example.

Firstly, checkable behavior needs to be enabled:

<com.google.android.material.card.MaterialCardView
...
android:clickable="true"
android:focusable="true"
android:checkable="true"
>

We can then toggle checked state (the below example is in response to a long click):

card.setOnLongClickListener {
card.isChecked = !card.isChecked
true
}

The UI changes include an overlay color and a checked icon:

A MaterialCardView in checked state

The checked icon can be changed using the checkedIcon attribute. The various color options will be discussed in the “Theming” section below.

For an advanced checking sample using RecyclerView selection, see the Material Components for Android catalog.

Dragging and swipe-to-dismiss ☝️

MaterialCardViews have built-in support for state changes specific to dragging. As with checking, no default behavior exists to implement the dragging itself. The recommended way of doing this is with ViewDragHelper and the Material Components for Android catalog includes a handy implementation class; DraggableCoordinatorLayout.

Note: It would be useful if DraggableCoordinatorLayout were included in the core Material Components for Android library to allow it to be used without having to copy the class. At the time of writing, the latest release of Material Components for Android is 1.2.0-alpha06 and this is not the case. You can star the feature request for this on the issue tracker.

Firstly, we need to change the parent container to a DraggableCoordinatorLayout:

<io.material.catalog.draggable.DraggableCoordinatorLayout
android:id="@+id/parentContainer"
...
>

<com.google.android.material.card.MaterialCardView
...
>
<!-- Card contents --></com.google.android.material.card.MaterialCardView></io.material.catalog.draggable.DraggableCoordinatorLayout>

We can then add a callback and toggle dragged state:

parentContainer.addDraggableChild(card)
parentContainer.setViewDragListener(object
: DraggableCoordinatorLayout.ViewDragListener {

override fun onViewCaptured(view: View, pointerId: Int) {
card.isDragged = true
}

override fun onViewReleased(view: View, vX: Float, vY: Float) {
card.isDragged = false
}
})

The UI changes include an overlay color and (animated) increased elevation:

A MaterialCardView in dragged state

For an advanced dragging sample using RecyclerView drag-and-drop, see the Material Components for Android catalog.

For an advanced swipe-to-dismiss sample using SwipeDismissBehavior, see the Material Components for Android catalog.

Theming 🎨

Cards can be themed in terms of the three Material Theming subsystems: color, typography and shape. When implementing a global card style, extend the Widget.MaterialComponents.CardView style and reference it in your app theme with the materialCardViewStyle attribute.

Color

The color of the card background can be customized with the cardBackgroundColor attribute. This defaults to colorSurface.

As mentioned above, the foreground color of a card is used to indicate both checked and dragged state. As such, this requires a ColorStateList, meaning a <selector> for checked/dragged states is required. It is usually transparent but uses color to indicate checking/dragging, defaulting to colorPrimary(checked)/colorOnSurface(dragged), with different opacities per state.

The tint color of the checked icon can be customized with the checkedIconTint attribute. This defaults to colorPrimary.

The color of an optional card stroke can be customized with the strokeColor attribute. This is disabled by default.

Lastly, the color of the card touch ripple can be customized with the rippleColor attribute. It too accepts a ColorStateList and defaults to colorOnSurface(unchecked)/colorPrimary(checked), with different opacities per state.

Color theming

Typography

There is no primary text as part of card components. Text included in the contents of a card will be styled according to the class/component used as well as the fontFamily app theme attribute.

Type theming

Shape

The shape of a card background can be customized with the shapeAppearance attribute. This defaults to shapeAppearanceMediumComponent.

The elevation of a card can be customized with the cardElevation attribute. This defaults to 1dp.

Interestingly, the corner size of a card’s current shape appearance can be interpolated between 0.0 and 1.0. This can be useful in animations and transitions. Use MaterialCardView#setProgress and MaterialCardView#getProgress for this.

While not strictly shape theming, it is worth mentioning that the width of an optional card stroke can be adjusted with the strokeWidth attribute. This defaults to 0dp (and will not be rendered if no strokeColor is set, regardless of width).

Shape theming

More resources 📚

I hope this post has provided some insight into Cards and how they can be used in your Android app(s). If you have any questions, thoughts or suggestions then I’d love to hear from you!

Find me on Twitter @ricknout

--

--

Nick Rout
Over Engineering

Principal Android Engineer at GoDaddy | Ex-Google | Google Developer Expert for Android