An Introduction to Material Design with Kotlin

In this tutorial you’ll learn how to integrate Material Design into an existing app and create delightful interactions using the animation APIs. By Aaqib Hussain.

Leave a rating/review
Download materials
Save for later
Share

Update Note: This tutorial has been updated to Kotlin by Aaqib Hussain. The original tutorial was written by Megha Bambra.

Update Note: This tutorial has been updated to Kotlin by Aaqib Hussain. The original tutorial was written by Megha Bambra.

Google’s material design brings with it exciting ways to delight your users with a visually appealing Android app. But wait—what is material design?

Google has described it as an interface that incorporates “tactile surfaces, bold graphic design, and fluid motion to create beautiful, intuitive experiences.” Material design is the “user experience philosophy” for Android apps!

In this tutorial, you’ll integrate material design into an app called Travel Wishlist. Along the way, you’ll learn how to:

  • Implement the material theme;
  • Build dynamic views using widgets like RecyclerView and CardView;
  • Use the Palette API to generate color schemes that you can use for text or background views;
  • Create delightful interactions using Android animation APIs.

This tutorial assumes you have a basic familiarity with Android programming including Kotlin, XML, Android Studio and Gradle. If you’re completely new to Android, you might want to go through our Beginning Android Development series and Kotlin Introduction first.

To follow along with this tutorial, you’ll need to use Android Studio 3.3.2 or later and Kotlin 1.3.20.

Let’s get started!

Getting Started

Download the starter project by clicking the Download Materials button at the top or bottom of this tutorial, then fire up Android Studio.

To import the starter project, first select Open an existing Android Studio project from the Welcome to Android Studio window:

Then select the downloaded project and click Open:

Travel Wishlist will be a very simple app. Users will see a grid of pictures from locations around the world, and be able to tap each picture to add notes about what to do and see.

Build and run the starter project, and you should see a screen with the most basic of interfaces:

Right now, the world is empty! You’re going to add material components to this existing project, including dynamic views, color schemes and animations that will truly complement the beauty of the photos in your dataset.

Open build.gradle for the app module and add RecyclerView, CardView, Palette, and Picasso to your dependencies:

dependencies {
    implementation fileTree(include: ['*.jar'], dir: 'libs')
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
    implementation 'com.android.support:design:27.1.1'
    implementation 'com.android.support:appcompat-v7:27.1.1'
    implementation 'com.android.support:recyclerview-v7:27.1.1'
    implementation 'com.android.support:cardview-v7:27.1.1'
    implementation 'com.android.support:palette-v7:27.1.1'
    implementation 'com.squareup.picasso:picasso:2.5.2'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}

Here you’re simply declaring the dependencies that you’ll use throughout the rest of the tutorial. The first few of the added dependencies are Google-provided APIs, but the final one, Picasso, is a fantastic image downloading and caching library provided by the good folks at Square.

With the dependencies declared, it’s time to begin incorporating Material Design into your app!

Setting Up the Theme

Before doing anything else, you will update the theme. Open style.xml under the res/values directory. By default, the theme selected is Theme.AppCompat.Light.DarkActionBar. Add the following items inside the theme tag:

<item name="android:navigationBarColor">@color/primary_dark</item>
<item name="android:displayOptions">disableHome</item>

Android automatically applies colorPrimary to the action bar, colorPrimaryDark to the status bar and colorAccent to UI widgets like text fields and checkboxes.

In the code above, you also alter the color of the navigation bar. For android:displayOptions, you pass disableHome to accommodate the screen layouts in this sample app.

Build and run, and you’ll see the new color scheme in the app.

It’s a subtle change, but like every trip on your travel wishlist, upgrading this design begins with a single step!

Using RecyclerView and CardView

To give your users a window into all the cool places they might go, you need a view. You can use RecyclerView as a replacement for ListView, but it’s much more versatile than that. Google describes RecyclerView as “a flexible view for providing a limited window into a large data set.” In this section, you’re going to demonstrate this by switching the view from a list to a custom grid that uses the same data source which supplies the user’s locations.

Implementing a Recycler View in XML

First, open activity_main.xml and add the following inside the LinearLayout tag:

<android.support.v7.widget.RecyclerView
  android:id="@+id/list"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:background="@color/light_gray"/>

Here you’re adding a RecyclerView to the activity’s layout, and specifying it should match the entire size of the parent view.

Initializing a Recycler View and Applying a Layout Manager

Before adding Kotlin code, configure Android Studio so that it automatically inserts import statements to save you having to add each one manually.

Go to Preferences\Editor\General\Auto Import and select the Add unambiguous imports on the fly checkbox. In MainActivity.kt, add the following to the top of the class:

lateinit private var staggeredLayoutManager: StaggeredGridLayoutManager

Here you’re simply declaring a property to hold a reference to the LayoutManager.

Next, add the following to the bottom of onCreate():

staggeredLayoutManager = StaggeredGridLayoutManager(1, StaggeredGridLayoutManager.VERTICAL)
list.layoutManager = staggeredLayoutManager

In the code above, you set the layout manager of the RecyclerView to a StaggeredGridLayoutManager, which you’ll use to create two types of vertically staggered grids. Here you start with the first type, passing 1 for the span count and StaggeredGridLayoutManager.VERTICAL for the orientation. A span count of 1 makes this a list rather than a grid, as you’ll soon see. Later, you’ll add a compact grid formation with two columns.

Note that you’re using Kotlin Android Extensions to find list, so there is no need for a call to findViewById(). Make sure that the following line is present in your import statements, as it should be automatically added when you type in list:

import kotlinx.android.synthetic.main.activity_main.*

Creating Rows and Cells Using a Card View

CardView provides a consistent backdrop for your views, including rounded corners and a drop shadow. You’re going to implement it for the row/cell layout of your RecyclerView. By default, CardView extends FrameLayout and therefore includes the ability to host other child views.

From the res\layout directory, create a new Layout resource file and call it row_places.xml. Press OK to create it.

To create your desired cell layout, replace all the contents of this file with the code below:

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:card_view="http://schemas.android.com/apk/res-auto"
  android:id="@+id/placeCard"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:layout_margin="8dp"
  card_view:cardCornerRadius="@dimen/card_corner_radius"
  card_view:cardElevation="@dimen/card_elevation">

  <ImageView
    android:id="@+id/placeImage"
    android:layout_width="match_parent"
    android:layout_height="200dp"
    android:scaleType="centerCrop" />

  <!-- Used for the ripple effect on touch -->
  <LinearLayout
    android:id="@+id/placeHolder"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="?android:selectableItemBackground"
    android:orientation="horizontal" />

  <LinearLayout
    android:id="@+id/placeNameHolder"
    android:layout_width="match_parent"
    android:layout_height="45dp"
    android:layout_gravity="bottom"
    android:orientation="horizontal">

    <TextView
      android:id="@+id/placeName"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:layout_gravity="center_vertical"
      android:gravity="start"
      android:paddingStart="10dp"
      android:paddingEnd="10dp"
      android:textAppearance="?android:attr/textAppearanceLarge"
      android:textColor="@android:color/white" />

  </LinearLayout>

</android.support.v7.widget.CardView>

By adding xmlns:card_view="http://schemas.android.com/apk/res-auto", you can define attributes like card_view:cardCornerRadius and card_view:cardElevation that are responsible for giving Material Design enabled Android apps their signature card-like look.

Notice that for mainHolder, you’ve added ?android:selectableItemBackground as the background. This enables the ripple effect animation when the user touches a cell, as seen in many Android apps now. You’ll get to see it in action soon.