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
You are currently viewing page 2 of 4 of this article. Click here to view the first page.

Listening to Click Events

You need to set a listener that’ll notify you when a user clicks on an item from the list. For that, you should declare an interface inside ItemsAdapter:

interface OnItemClickListener {
  fun onItemClick(item: Item, itemView: View)
}

The onItemClick(item: Item, itemView: View) function will be called by the interface to let you know which specific Item object is clicked. Here itemView is the view that represents the Item in RecyclerView.

Now modify ItemsAdapter‘s constructor to match the following:

class ItemsAdapter(private val items: List<Item>, private val clickListener: OnItemClickListener)

ItemsAdapter now requires an OnItemClickListener instance when created so that you can use the instance later.

Modify onBindViewHolder() as follows:

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

This binds the clickListener instance to every ViewHolder.

At this point you might see a compiler warning like this:

but don’t worry, all you need is to update ViewHolder class to fix that:

class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
  fun bind(item: Item, listener: OnItemClickListener) = with(itemView) {
    itemTitle.text = item.title
    itemPrice.text = "\$" + item.price
    itemImage.setImageResource(item.imageId)
    setOnClickListener {
      listener.onItemClick(item, it)
    }
  }
}

Notice that you are using listener.onItemClick(item, it) inside setOnClickListener for itemView. That means, onItemClick() function will be fired whenever user clicks on an itemView and passes the reference of it’s corresponding item and view through the listener interface.

You should navigate from MainActivity to DetailsActivity when a user clicks on a item to see its details. Implement the OnItemClickListener interface in MainActivity as follows:

class MainActivity : AppCompatActivity(),
    ItemsAdapter.OnItemClickListener {
}

and override onItemClick() function inside MainActivity:

override fun onItemClick(item: Item, itemView: View) {
  val detailsIntent = Intent(this, DetailsActivity::class.java)
  detailsIntent.putExtra(getString(R.string.bundle_extra_item), item)
  startActivity(detailsIntent)
}

When an item inside the RecyclerView is clicked on, the onItemClick(item: Item, itemView: View) function will notify MainActivity and navigate to DetailsActivity starting a new Intent. Update the creation of the ItemsAdapter

itemsRecyclerView.adapter = ItemsAdapter(items)

to include the OnItemClickListener inside populateItemList(category: Category) method.

itemsRecyclerView.adapter = ItemsAdapter(items, this)

Run again at this and click on a item from the list – you will see a white screen with a text like this:

But that’s ok for now, you will make it look good soon enough!

Before going any farther let’s import the icons you are going to use later…

Using VectorDrawables for Icons

VectorDrawables are graphic elements that consist of points, lines and color information defined in a XML. It adjusts itself to different screen densities without loss of image quality, so using one file is enough to support devices with different resolution which results a smaller APK!

Android Studio has a lot of VectorDrawables bundled with it for your convenience, but you can also use your own svg or psd icons as VectorDrawables. To import them, you would right-click on the res folder and select New > Vector Asset. This will open the Asset Studio.

The starter project for this tutorial has icons that have already been converted to vector drawables in a folder named SVG inside the project directory. Navigate to that folder and copy all the xml files into the res/drawables folder.

You can now use those vector drawables inside a BottomNavigationView.

Categorize items with BottomNavigationView

You may want to display items of different categories in different tabs. How about showing them at the bottom of MainActivity with a nice icons? Design Support Library provides a widget called BottomNavigationView that makes this task easy!

Implementing BottomNavigationView

Right-click on res > menu folder and add new Menu resource file.

Name it menu_bottom_navigation.xml and add following code:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:app="http://schemas.android.com/apk/res-auto">
    <item
        android:id="@+id/nav_laptops"
        android:icon="@drawable/ic_laptop"
        android:title="@string/laptops"/>
    <item
        android:id="@+id/nav_monitors"
        android:icon="@drawable/ic_monitor"
        android:title="@string/monitors"/>
    <item
        android:id="@+id/nav_headphones"
        android:icon="@drawable/ic_headphone"
        android:title="@string/headphones"/>
</menu>

The code is pretty straightforward here, you are setting an id, icon and title for each item in the BottomNavigationView which will be displayed as a Tab with an icon and title.

Now add BottomNavigationView inside activity_main.xml under RecyclerView:

<android.support.design.widget.BottomNavigationView
    android:id="@+id/bottomNavigationView"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    app:menu="@menu/menu_bottom_navigation"/>

You should also add

android:layout_above="@+id/bottomNavigationView"

to the RecyclerView so that it shows above BottomNavigationView instead of fullscreen.

Handling Item Selection on BottomNavigationView

The intention of the BottomNavigationView is to show Items of different categories when users select different tabs from the BottomNavigationView.

First, have MainActivity implement BottomNavigationView.OnNavigationItemSelectedListener. Modify the MainActivity declaration as follows:

class MainActivity : AppCompatActivity(),
        ItemsAdapter.OnItemClickListener,
        BottomNavigationView.OnNavigationItemSelectedListener {
}

and add following function inside MainActivity class:

override fun onNavigationItemSelected(item: MenuItem): Boolean {
  when (item.itemId) {
    R.id.nav_laptops -> populateItemList(Category.LAPTOP)
    R.id.nav_monitors -> populateItemList(Category.MONITOR)
    R.id.nav_headphones -> populateItemList(Category.HEADPHONE)
    else -> return false
  }
  return true
}

The onNavigationItemSelected(item: MenuItem) function fires each time a user clicks a MenuItem shown as Tab in BottomNavigationView.

This function, determines which MenuItem was clicked using the item.itemId and calls populateItemList() with it’s corresponding Category to show the items of that category in the RecyclerView.

onNavigationItemSelected(item: MenuItem) will return true to notify MainActivity that a NavigationItem is selected if item.itemId matches to any item defined in the menu_bottom_navigation.xml or returns false otherwise to keep things unchanged.

Add this line inside onCreate() function in MainActivity:

bottomNavigationView.setOnNavigationItemSelectedListener(this)

Run the app again you’ll notice the items changing after each tab is selected.

Adding New Items

Adding another button inside MainActivity to add new items will eat a lot of precious real estate in your landing page, but how about overlaying a button over the list of items? Did someone say FloatingActionButton?

Using FloatingActionButton

Add a FloatingActionButton at the bottom of activity_main.xml, to look as follows:

<?xml version="1.0" encoding="utf-8"?>
<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"
        android:layout_above="@+id/bottomNavigationView"
        app:layoutManager="android.support.v7.widget.GridLayoutManager"
        app:spanCount="2"/>

    <android.support.design.widget.BottomNavigationView
        android:id="@+id/bottomNavigationView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        app:menu="@menu/menu_bottom_navigation"/>

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/addFab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_above="@id/bottomNavigationView"
        android:layout_alignParentRight="true"
        android:clickable="true"
        android:onClick="onClickAddFab"
        app:srcCompat="@drawable/ic_add"
        app:useCompatPadding="true"/>

</RelativeLayout>

Then add following function inside MainActivity.kt:

fun onClickAddFab(view: View) {
  startActivity(Intent(this, AddItemActivity::class.java))
}

This function will be called when user clicks on the FloatingActionButton and navigate from MainActivity to AddItemsActivity by starting a new Intent.

Run the app again, and click on the FloatingActionButton, you should see the app transition into the AddItemsActivity:

Before moving to the next section, update imageFromCategory() inside AddItemActivity.kt so that it returns an icon that matches with provided Category:

private fun imageFromCategory(category: Category): Int {
  return when (category) {
    Category.LAPTOP -> R.drawable.ic_laptop
    Category.MONITOR -> R.drawable.ic_monitor
    else -> R.drawable.ic_headphone
  }
}