Android Design Support Library: Getting Started

The Design Support Library helps you implement shiny, interactive Material Design components and supports phones running extremely old versions of Android! By Zahidur Rahman Faisal.

Leave a rating/review
Download materials
Save for later
Share

Have you been surfing through thousands of Github libraries to add a Facebook-like Sliding Navigation menu in your project? Or searching for a convenient widget that will show tabs with icons at the bottom of your app’s homepage?

Behold – the Android Design Support Library is for you!

The Android Design Support Library helps you implement those shiny, interactive design components with minimal code!

In this tutorial, you’ll create a marketplace app called iSell using the Android Design Support Library. By the end, you will learn how to:

  • Use common Material Design components like BottomNavigationView and FloatingActionButton
  • Get rid of needing different images for the same icon to support different device resolutions with VectorDrawables
  • Bring some wow-factors to your users with CoordinatorLayout and CollapsingToolbarLayout

This is gonna be awesome!

This is gonna be awesome!

This is gonna be awesome!

Getting started

To kick things off, start by downloading the materials for this tutorial (you can find a link at the top or bottom of this tutorial). Unzip iSell.zip folder into your desktop.

Now launch Android Studio 3.1.2 or greater and select Open an existing Android Studio project to import the starter project.

Open an existing Android Studio project

Choose iSell-Starter inside the iSell folder and click Open

select iSell-Starter and click Open

Build and run by firing keyboard shortcut Shift + F10 (or Control + R if you are using a Mac)

empty home screen

And you will see a screen with the project name. Kudos – you’ve successfully kickstarted the project!

Managing Design Support Dependencies

Adding Design Support Library to your project is a piece of cake, but it requires a few different components. You should always use the latest version of each component, and make sure they’re the same version for all the components.
To manage this efficiently, an external variable is defined in your Project level build.gradle file as following:

ext.supportLibraryVersion = '27.1.1'

You will use this version with all the Design Support Library components later.

Open the build.gradle file from your app module and append the following lines inside the dependencies section:

// 1: Design Support Library
implementation "com.android.support:design:$supportLibraryVersion"
// 2: CardView
implementation "com.android.support:cardview-v7:$supportLibraryVersion"

Let’s take a moment to understand what each of dependencies provides:

  1. Design Support Library: Adds all those “exciting” UI components we are talking about. For example: BottomNavigationView, FloatingActionButton. We’ll be adding one of each later in this tutorial.
  2. CardView: Is a View component that shows its content in an elevated card, and highlights it to stand-out from the background. Most commonly used with list items.

Also, you’re are going to use VectorDrawables for the icons, so add this inside the defaultConfig section:

vectorDrawables.useSupportLibrary = true

Your app module’s build.gradle file finally may look like this:

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'

android {
    compileSdkVersion 27
    defaultConfig {
        applicationId "com.raywenderlich.isell"
        minSdkVersion 16
        targetSdkVersion 27
        versionCode 1
        versionName "1.0"
        vectorDrawables.useSupportLibrary = true
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    androidExtensions {
        experimental = true
    }
}

dependencies {
    // Kotlin
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlinVersion"
    // AppCompat
    implementation "com.android.support:appcompat-v7:$supportLibraryVersion"
    // Design Support Library
    implementation "com.android.support:design:$supportLibraryVersion"
    // CardView
    implementation "com.android.support:cardview-v7:$supportLibraryVersion"
}

Notice that the build.gradle file has uses a plugin:

apply plugin: 'kotlin-android-extensions'

With kotlin-android-extensions, you can directly access a View‘s id without having to initialize it using findViewById(). Its just sweet syntactic sugar! If you are keen to know more about kotlin-android-extensions you can find out more here.

Before adding any Kotlin code, configure Android Studio to automatically insert import statements so that you don’t need to worry about imports for every change you make.

Go to Preferences\Editor\General\Auto Import, check Add unambiguous imports on the fly and Optimize imports on the fly checkboxes and click OK.

Again, don’t forget to click Sync Now in the top-right corner of your IDE. You’re now done with all the setup!

Showcasing Items with RecyclerView

First things first, you’ll display a list of items to sell. To show the list, replace the TextView inside activity_main.xml with a RecyclerView:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                xmlns:app="http://schemas.android.com/apk/res-auto"
                xmlns:tools="http://schemas.android.com/tools"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                tools:context=".ui.activity.MainActivity">

  <android.support.v7.widget.RecyclerView
      android:id="@+id/itemsRecyclerView"
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      app:layoutManager="android.support.v7.widget.GridLayoutManager"
      app:spanCount="2"/>

</RelativeLayout>

Here, RecyclerView will be identified as itemsRecyclerView and the width and height properties should match its parent layout.

app:layoutManager="android.support.v7.widget.GridLayoutManager"
app:spanCount="2"

You’ll notice that you set the layoutManager directly in the XML to use a GridLayoutManager. Setting the app:spanCount tells the GridLayoutManager that you want to show 2 items in a row, so you tell the layoutManager to prepare layout for the grid.

Next, you need to design the layout for the items in the list.

Highlight with CardView

For each item in being sold, you’ll want to show the image, price and title. To make a layout for that, right-click on layout folder, select New, then select Layout resource file and name it layout_list_item.xml.

Now add following code inside layout_list_item.xml:

<?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"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="@dimen/default_margin"
    android:foreground="?android:attr/selectableItemBackground"
    card_view:cardBackgroundColor="@color/cardview_light_background"
    card_view:cardCornerRadius="@dimen/cardview_default_radius"
    card_view:cardElevation="@dimen/cardview_default_elevation">

  <RelativeLayout
      android:layout_width="match_parent"
      android:layout_height="wrap_content">

    <ImageView
        android:id="@+id/itemImage"
        android:layout_width="match_parent"
        android:layout_height="@dimen/item_image_height"
        android:scaleType="fitCenter"
        tools:src="@drawable/laptop_1"/>

    <TextView
        android:id="@+id/itemPrice"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/itemImage"
        android:layout_marginLeft="@dimen/default_margin"
        android:layout_marginRight="@dimen/default_margin"
        android:maxLines="1"
        android:textAppearance="@style/TextAppearance.AppCompat.Headline"
        android:textColor="@color/colorAccent"
        tools:text="@string/hint_price"/>

    <TextView
        android:id="@+id/itemTitle"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/itemPrice"
        android:layout_marginBottom="@dimen/default_margin"
        android:layout_marginLeft="@dimen/default_margin"
        android:layout_marginRight="@dimen/default_margin"
        android:ellipsize="end"
        android:maxLines="2"
        android:minLines="2"
        android:textAppearance="@style/TextAppearance.AppCompat.Title"
        tools:text="@string/hint_title"/>
  </RelativeLayout>
</android.support.v7.widget.CardView>

It will look like this in the Preview pane:

Here the CardView and its properties may seem new to you, but other components are quite familiar – you are just adding views to show the image, price and title inside a RelativeLayout sequentially.

Using CardView makes your item appear elevated with the use of drop shadows around the element.

card_view:cardBackgroundColor="@color/cardview_light_background"

The above property adds a light-themed background color for the CardView from Design Support Library.

card_view:cardCornerRadius="@dimen/cardview_default_radius"

This property makes the card’s corners to look rounded. You are using the default radius provided in Design Support Library. You can play with the values for this property, the edges will look more rounded with a larger value.

The most interesting property of CardView is:

card_view:cardElevation="@dimen/cardview_default_elevation"

This property allows a CardView to look more or less elevated. This elevation of the view determines the size of the drop shadow. The larger the value you provide, the more elevated it’ll look.

RecyclerView in Action

It’s time to bind some data to the layout. Consider the DataProvider class inside util package as a storehouse of all your Items. You need an adapter to show items in the RecyclerView added earlier. To do so, add a new class inside the adapter package named ItemsAdapter as follows:

// 1
class ItemsAdapter(private val items: List<Item>)
  : RecyclerView.Adapter<RecyclerView.ViewHolder>() {

  // 2
  class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
    fun bind(item: Item) = with(itemView) {
      itemTitle.text = item.title
      itemImage.setImageResource(item.imageId)
    }
  }

  // 3
  override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
    val view = LayoutInflater.from(parent?.context)
        .inflate(R.layout.layout_list_item, parent, false)
    return ViewHolder(view)
  }

  // 4
  override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
    (holder as ViewHolder).bind(items[position])
  }

  // 5
  override fun getItemCount(): Int {
    return items.size
  }
}

That’s a lot of code to digest at once! Let’s break it down…

  1. ItemsAdapter is declared as a subclass of RecyclerView.Adapter which accepts a list of Item.
  2. ViewHolder is a subclass of RecyclerView.ViewHolder. It inherits the power of being cached into memory and re-used to display an Item inside the RecyclerView. The bind(item: Item) function inside it does all the binding between the Item and the View.
  3. onCreateViewHolder() function creates a new ViewHolder when the adapter needs a new one with the view you designed in layout_list_item.xml.
  4. onBindViewHolder() glues each Item from the list with a ViewHolder to populate it using the bind() function.
  5. getItemCount() function tells ItemsAdapter the number of items in the list.

Add a function that will set the data in RecyclerView according to the category you want inside MainActivity.kt:

private fun populateItemList(category: Category) {
  val items = when (category) {
    Category.LAPTOP -> DataProvider.laptopList
    Category.MONITOR -> DataProvider.monitorList
    Category.HEADPHONE -> DataProvider.headphoneList
  }
  if (items.isNotEmpty()) {
    itemsRecyclerView.adapter = ItemsAdapter(items)
  }
}

This function accepts Category as input and fetches a list of items from that category through the DataProvider. Then it creates a new ItemsAdapter with those items and sets to itemsRecyclerView.

Call this function with a Category from onCreate() function inside MainActivity:

populateItemList(Category.LAPTOP)

Here you are fetching items from the LAPTOP category through the DataProvider. Feel free to play around with other categories also.

Run the app again. You’ll see the list as follows: