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.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
Android Design Support Library: Getting Started
30 mins
- Getting started
- Managing Design Support Dependencies
- Showcasing Items with RecyclerView
- Highlight with CardView
- RecyclerView in Action
- Listening to Click Events
- Using VectorDrawables for Icons
- Categorize items with BottomNavigationView
- Implementing BottomNavigationView
- Handling Item Selection on BottomNavigationView
- Adding New Items
- Using FloatingActionButton
- Interacting with TextInputLayout
- Using Snackbar for Temporary Messages
- Animating Item Details
- Using CoordinatorLayout and CollapsingToolbarLayout
- Adding Parallax Scrolling Effect
- Where To Go From Here?
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
}
}