The material design team at Google simply defines the functionality of tabs in Android as follows:
Tabs make it easy to explore and switch between different views.
In this post you’ll learn how to display tabs using the TabLayout
and ViewPager
API. In this practical tutorial, we’ll cover the following:
- The
TabLayout
andViewPager
components. - The different tab modes: scrollable and fixed.
- How to display icons instead of text for the tab titles.
- For a bonus, you’ll also learn how to use the Android Studio templates feature to quickly bootstrap your project with a tabbed interface.
A sample project for this tutorial can be found on our GitHub repo so you can easily follow along.
Prerequisites
To be able to follow this tutorial, you’ll need:
- Android Studio 3.0 or higher
- Kotlin plugin 1.1.51 or higher
You can also learn all the ins and outs of the Kotlin language in my Kotlin From Scratch series.
-
KotlinKotlin From Scratch: Nullability, Loops, and Conditions
-
KotlinKotlin From Scratch: Classes and Objects
Introduction to the TabLayout Component
According to the official Android documentation on TabLayout
, it says:
TabLayout
provides a horizontal layout to display tabs.
The TabLayout
component is one of the components introduced as part of the material design artifacts. Moreover, it is also included in the design support library. In a TabLayout
, when a tab is selected or tapped, a different page (or fragment) is shown to the user.
The TabLayout
component can have its displayed tabs function in one of two ways: fixed and scrollable. If the tabs are fixed, all of the tabs will be displayed on the screen at the same time.
The screenshot below is the latest official WhatsApp Android app (as of this writing), which uses a TabLayout
with a fixed mode configuration.
In scrollable tabs, if the number of tabs becomes too wide for the screen, the user can swipe left or right to view more tabs.
Here is an example of a TabLayout
with scrollable tab mode—showcased in the latest version of the News & Weather Android app by Google.
Furthermore, the information displayed on a tab can be text, an icon, or a combination of both text and an icon. For example, the latest Twitter app for Android uses icons instead of text on each tab.
In the following sections, we’ll dive into coding a simple app that makes use of TabLayout
with a ViewPager
. Let’s get rolling!
Design is not just what it looks like and feels like. Design is how it works. — Steve Jobs
1. Create an Android Studio Project
Fire up Android Studio 3 and create a new project (you can name it TabLayoutDemo
) with an empty activity called MainActivity
.
2. Creating the Fragments (Pages)
We’re going to create a TabLayout
with just three tabs. When each of the tabs is selected, it displays a different Android fragment or page. So let’s now create the three Android fragments for each of the tabs. We’ll start with the first fragment class, and you should follow a similar process for the remaining two fragment classes—FragmentTwo.kt and FragmentThree.kt.
Here is my FragmentOne.kt:
import android.os.Bundle import android.support.v4.app.Fragment import android.view.LayoutInflater import android.view.View import android.view.ViewGroup class FragmentOne : Fragment() { override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? = inflater!!.inflate(R.layout.fragment_one, container, false) companion object { fun newInstance(): FragmentOne = FragmentOne() } }
Here is also my R.layout.fragment_one
:
3. Adding the TabLayout and ViewPager
To begin using TabLayout
and ViewPager
in your project, make sure you import the design support and also the Android support artifact—so add these to your module’s build.gradle file to import them.
dependencies { implementation 'com.android.support:design:26.1.0' implementation 'com.android.support:support-v4:26.1.0' }
Also, visit your res/layout/activlty_main.xml file to include both the TabLayout
widget and the ViewPager
view.
Here we created a simple TabLayout
with id tab_layout
. In our TabLayout
XML widget, you can see that we included some attributes—such as app:tabMode
to be fixed
and also app:tabGravity
to be fill
. The app:tabGravity
property is used to configure how the tab items will be displayed so as to take up the available space. We set this to fill
, which will distribute the items evenly across the width of the TabLayout
. Note that this will be more visible in wider displays, such as tablets.
I also included a custom style attribute (@style/CustomTabLayout
) in our TabLayout
widget.
We begin customising our TabLayout
by setting the values of the attributes to be applied on the TabLayout
. Here are the details for some of the attributes applied:
-
tabIndicatorColor
: sets the tab indicator’s color for the currently selected tab. This can also be set programmatically by callingsetSelectedTabIndicatorColor()
on aTabLayout
instance. -
tabIndicatorHeight
: sets the tab indicator’s height for the currently selected tab. This can be also be set programmatically by calling thesetSelectedTabIndicatorHeight()
on aTabLayout
instance. -
tabSelectedTextColor
: sets the text colors for the different states (normal, selected) used for the tabs. The equivalent of this attribute in Java issetTabTextColors()
.
Immediately after creating our TabLayout
widget in XML, the next view was a ViewPager
. The official documentation says the following about ViewPager
:
Layout manager that allows the user to flip left and right through pages of data…
4. Creating the PagerAdapter
We need to create a subclass in SampleAdapter.kt that extends the FragmentPagerAdapter
. This class is responsible for managing the different fragments that will be displayed on the tabs.
import android.support.v4.app.Fragment import android.support.v4.app.FragmentManager import android.support.v4.app.FragmentPagerAdapter class SampleAdapter(fm: FragmentManager) : FragmentPagerAdapter(fm) { override fun getItem(position: Int): Fragment? = when (position) { 0 -> FragmentOne.newInstance() 1 -> FragmentTwo.newInstance() 2 -> FragmentThree.newInstance() else -> null } override fun getPageTitle(position: Int): CharSequence = when (position) { 0 -> "Tab 1 Item" 1 -> "Tab 2 Item" 2 -> "Tab 3 Item" else -> "" } override fun getCount(): Int = 3 }
Here we override three methods from the parent class: getItem()
, getCount()
, and getPageTitle()
. Here are the explanations for the methods:
-
getItem()
: returns aFragment
for a particular position within theViewPager
. -
getCount()
: indicates how many pages will be in theViewPager
. -
getPageTitle()
: this method is called by theViewPager
to obtain a title string to describe the specified tab.
For example, if the selected tab is the first tab with title "Tab 1 Item"
, a FragmentOne
page will be shown to the user immediately.
5. Initialization of Components
Next, we are going to initialize instances of our TabLayout
, ViewPager
, and SampleAdapter
. Initialization is going to happen inside onCreate()
in MainActivity.kt.
import android.os.Bundle import android.support.design.widget.TabLayout import android.support.v4.view.ViewPager import android.support.v7.app.AppCompatActivity import android.support.v7.widget.Toolbar class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) initToolbar() val tabLayout: TabLayout = findViewById(R.id.tab_layout) val viewPager: ViewPager = findViewById(R.id.view_pager) val adapter = SampleAdapter(supportFragmentManager) viewPager.adapter = adapter tabLayout.setupWithViewPager(viewPager) tabLayout.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener { override fun onTabSelected(tab: TabLayout.Tab) { } override fun onTabUnselected(tab: TabLayout.Tab) { } override fun onTabReselected(tab: TabLayout.Tab) { } }) } private fun initToolbar() { val toolbar: Toolbar = findViewById(R.id.toolbar) setSupportActionBar(toolbar) supportActionBar!!.title = "TabLayout Demo" } }
We got references to our TabLayout
and ViewPager
from R.layout.activity_main
and initialized them. We also created an instance of our SampleAdapter
—passing an instance of FragmentManager
as an argument. We need to supply the views for our ViewPager
, so we called setAdapter()
and passed in our created adapter to it. Finally, we called setupWithViewPager()
on an instance of TabLayout
to do some work:
- creation of the required tab for every page
- setting up the required listeners
When the user taps on a tab, it changes the pages in the ViewPager
and shows the required page (or Fragment
). Also, swiping between pages updates the selected tab. In other words, this method helps us take care of scroll state change and clicks on the tabs.
The onTabSelectedListener()
is used to include a listener that will be invoked when tab selection changes. We’ve overridden the following callbacks:
-
onTabSelected()
: triggered when a tab enters the selected state. -
onTabUnselected()
: invoked when a tab exits the selected state. -
onTabReselected()
: invoked when a tab that is already selected is chosen again by the user.
Note that we can also set the tab mode programmatically—instead of via the layout XML—using setTabMode()
on an instance of TabLayout
. We pass the mode (fixed or scrollable) to this method as arguments. For example, we can pass TabLayout.MODE_FIXED
for a fixed mode—or TabLayout.MODE_SCROLLABLE
for a scrollable mode.
tabLayout.tabMode = TabLayout.MODE_FIXED tabLayout.tabMode = TabLayout.MODE_SCROLLABLE
Note that if you want to explicitly create the tabs instead of using the helper method setUpWithViewPager()
, you can instead use newTab()
on a TabLayout
instance.
val tabLayout: TabLayout = findViewById(R.id.tab_layout) tabLayout.addTab(tabLayout.newTab().setText("Songs")) tabLayout.addTab(tabLayout.newTab().setText("Albums")) tabLayout.addTab(tabLayout.newTab().setText("Artists"))
Note also that we could explicitly create the tabs via XML instead of programmatically.
6. Testing the App
Finally, you can run the app!
Try interacting with the application by swiping left or right and tapping the tabs.
7. Scrollable Tabs
The official material design guidelines on tabs says the following about scrollable tabs:
Scrollable tabs display a subset of tabs at any given moment. They can contain longer tab labels and a larger number of tabs than fixed tabs. Scrollable tabs are best used for browsing contexts in touch interfaces when users don’t need to directly compare the tab labels.
Let’s see how to create tabs with scrollable mode configuration. I made the title for each of the tabs longer than before. Here is the result in fixed mode:
You can see that TabLayout
has used multiple lines to display each of the tab’s titles. In some situations, it will even truncate the titles! This creates a bad user experience, so if your tab titles need to be very long, you should consider using scrollable mode. Note also that if you are going to have more than four tabs, it’s recommended to make the tab mode scrollable.
Let’s change the app:tabMode
property from fixed
to scrollable
.
app:tabMode="scrollable"/>
Remember, you can also set the tab mode programmatically, as discussed earlier.
8. Showing Tab Icons
Let’s now dive into how to replace the tab item text with icons instead.
class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { // ... tabLayout.setupWithViewPager(viewPager) tabLayout.getTabAt(0)!!.setIcon(android.R.drawable.ic_dialog_email) tabLayout.getTabAt(1)!!.setIcon(android.R.drawable.ic_dialog_info) tabLayout.getTabAt(2)!!.setIcon(android.R.drawable.ic_dialog_alert) // ... } // ... }
Here we called the getTabAt()
on an instance of TabLayout
. Calling this method will return the tab at the specified index. Next, we call setIcon()
. Calling this method will set the icon displayed on this tab.
I also set the tab mode to be fixed.
I still override the getPageTitle()
inside the SampleAdapter
.
class SampleAdapter(fm: FragmentManager) : FragmentPagerAdapter(fm) { // ... override fun getPageTitle(position: Int): CharSequence = when (position) { 0 -> "TAB 1" 1 -> "TAB 2" 2 -> "TAB 3" else -> "" } // ... }
Here is the result:
Now, if you want only the icons, you simply don’t override getPageTitle()
.
9. Bonus: Using Android Studio Templates
Instead of writing so much code just to create a tabbed interface or activity from scratch, Android Studio 3.0 has some pre-existing code templates (available in Java and Kotlin) to help kick-start your project. One such template can be used to create a tabbed activity.
I’ll show you how to use this handy feature in Android Studio 3.
For a new project, fire up Android Studio 3.
Enter the application name and click the Next button.
You can leave the defaults as they are in the Target Android Devices dialog. Click the Next button again.
In the Add an Activity to Mobile dialog, scroll down and select Tabbed Activity. Click the Next button after that.
In the last dialog, scroll down to the Navigation Style drop-down menu and select Action Bar Tabs (with ViewPager). Finally, click the Finish button to accept all configurations.
Android Studio has now helped us to create a project with a tabbed activity. Really cool!
You are strongly advised to explore the code generated.
In an already existing Android Studio project, to use this template, simply go to File > Activity > Tabbed Activity. And follow the similar steps that were described previously.
The templates that come included with Android Studio are good for simple layouts and making basic apps, but if you want to kick-start your app even further, you might consider some of the app templates available from Envato Market.
They’re a huge time saver for experienced developers, helping them to cut through the slog of creating an app from scratch and focus their talents instead on the unique and customised parts of creating a new app.
-
App Templates15 Best Android App Templates of 2017
Conclusion
In this tutorial, you learned how to create a tabbed interface in Android using the TabLayout
and ViewPager
API from scratch. We also explored how to easily and quickly use the Android Studio templates to create a tabbed interface.
I highly recommend checking out the official material design guidelines for tabs to learn more about how to properly design and use tabs in Android.
To learn more about coding for Android, check out some of our other courses and tutorials here on Envato Tuts+!
-
Android SDKCreate a Music Player App With Anko
-
Android SDKBuild a Music App With an Android App Template
-
Android SDKImplementing an Event Bus With LiveData
Powered by WPeMatico