In this tutorial, we’ll discuss and implement Android TabLayout in our android application. Also we’ll get into the details of Material Design.
Android TabLayout AppBarLayout
In the previous tutorials, we’ve been discussing the perks of using CoordinatorLayout as the root of our activity’s layout. All this while we haven’t gone into the details of an AppBarLayout and it’s usages. Let’s look into it now.
AppBarLayout
AppBarLayout is a vertical LinearLayout that is generally the first child inside a CoordinatorLayout and acts as a wrapper for the ToolBar in most cases. Using the ToolBar as a direct child of CoordinatorLayout would work fine but it will not be able to coordinate with other child views present. Here’s where the importance of AppBarLayout arises. It allows it’s child views to achieve the desired scrolling behavior using the param app:layout_scrollFlags
A sample xml layout for the above description is given below:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<android.support.design.widget.AppBarLayout android:id="@+id/appBar" android:layout_width="match_parent" android:layout_height="wrap_content" android:theme="@style/ThemeOverlay.AppCompat.ActionBar"> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="?attr/colorPrimary" app:layout_scrollFlags="scroll|enterAlways" /> </android.support.design.widget.AppBarLayout> |
The app:layout_scrollFlags
attribute of the Toolbar indicates to the view how to respond. It has the following possible values.
- scroll : This flag is generally set for all views that need to scroll off-screen. Views that don’t use this flag remain static allowing the other scrollable views to slide behind it
- enterAlways : This flag ensures that any downward scroll will cause the view to become visible, enabling the quick return pattern
- enterAlwaysCollapsed : An additional flag for ‘enterAlways’ which modifies the returning view to only initially scroll back to it’s collapsed height.
- exitUntilCollapsed : This flag causes the view to be scrolled until it is collapsed (its minHeight is reached) before exiting
- snap : Upon a scroll ending, if the view is only partially visible then it will be snapped and scrolled to it’s closest edge. Hence this avoids mid-animation states of a view
TabLayout
TabLayout is another popular view type introduced in the Material Design Guidelines. It provides a horizontal layout of tabs which are generally placed at the top of the screen according to the Android UI Guidelines.
The following xml snippet depicts how a TabLayout is defined.
1 2 3 4 5 6 |
<android.support.design.widget.TabLayout android:id="@+id/tabs" android:layout_width="match_parent" android:layout_height="wrap_content"/> |
The TabLayout consists of two important xml attributes described below:
app:tabMode
– This takes two values:- fixed – This displays all the tabs within the screen. Generally used when there are upto 3 tabs
- scrolling – This lets the user scrolls through the tabs horizontally.
app:tabGravity
– This attribute only works ifapp:tapMode="fixed"
. This also takes two values:- filled – It’ll distribute the horizontal width across all the tabs
- center – It’ll display all the tabs in the center horizontal of the screen
Note: A TabLayout is generally implemented along with a ViewPager. We’ll implement that in a later tutorial.
Let’s get onto the business logic of our application that hosts a ToolBar and TabLayout inside the AppBarLayout.
Android TabLayout AppBarLayout Project Structure
Android TabLayout AppBarLayout Example Code
The activity_main.xml
is given below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
<?xml version="1.0" encoding="utf-8"?> <android.support.design.widget.CoordinatorLayout xmlns:android="https://schemas.android.com/apk/res/android" xmlns:app="https://schemas.android.com/apk/res-auto" xmlns:tools="https://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true" tools:context="com.journaldev.tablayoutappbar.MainActivity"> <android.support.design.widget.AppBarLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:theme="@style/AppTheme.AppBarOverlay"> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="?attr/colorPrimary" app:layout_scrollFlags="scroll|enterAlways" app:popupTheme="@style/AppTheme.PopupOverlay" /> <android.support.design.widget.TabLayout android:id="@+id/tabs" android:layout_width="match_parent" app:tabGravity="fill" app:tabMode="fixed" android:layout_height="wrap_content"/> </android.support.design.widget.AppBarLayout> <android.support.v4.widget.NestedScrollView android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior" android:orientation="vertical"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/sample_text"/> </LinearLayout> </android.support.v4.widget.NestedScrollView> <android.support.design.widget.FloatingActionButton android:id="@+id/fab" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom|end" android:layout_margin="@dimen/fab_margin" android:src="https://www.journaldev.com/12858/@android:drawable/ic_dialog_email" /> </android.support.design.widget.CoordinatorLayout> |
In the above code we’ve added a LinearLayout below the AppBarLayout.
Important inferences that need to be drawn are:
- LinearLayout without the statement
app:layout_behavior="@string/appbar_scrolling_view_behavior
would overlap the LinearLayout with the AppBarLayout. - The LinearLayout as a direct child in a CoordinatorLayout won’t scroll. Hence we’ve kept it inside a NestedScrollView
- The TabLayout doesn’t have the
layout_scrollFlags
. Hence it won’t scroll out of the screen like the ToolBar. We’ll see that shortly.
The MainActivity.java is given below
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
package com.journaldev.tablayoutappbar; import android.os.Bundle; import android.support.design.widget.FloatingActionButton; import android.support.design.widget.Snackbar; import android.support.design.widget.TabLayout; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; import android.view.View; public class MainActivity extends AppCompatActivity { TabLayout tabLayout; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab); fab.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG) .setAction("Action", null).show(); } }); tabLayout=(TabLayout)findViewById(R.id.tabs); tabLayout.addTab(tabLayout.newTab().setText("Tab 1")); tabLayout.addTab(tabLayout.newTab().setText("Tab 2")); tabLayout.addTab(tabLayout.newTab().setText("Tab 3")); } } |
The output of the above application is shown below
Few notable things from the above output are:
- On scrolling, the status bar scrolls up too thereby leaving the ToolBar in an inconsistent state most of the times
- The Tab Bar indicators have the default color set as the colorAccent
- The default background color of the Tabs is colorPrimary
The first issue is a serious one. To resolve it goto the res->values-21->styles.xml file.
Change the line
@android:color/transparent
to
@color/colorPrimaryDark
This is how the output should look now:
There are numerous ways to customise the TabLayouts. Try calling the setIcon() on the newTab() method instead of setText(). It’ll display the drawable icons. You can even implement both of them like
1 2 3 4 5 |
tabLayout.addTab(tabLayout.newTab().setText("Speaker Phone").setIcon(android.R.drawable.stat_sys_speakerphone)); tabLayout.addTab(tabLayout.newTab().setText("Headset").setIcon(android.R.drawable.stat_sys_headset)); tabLayout.addTab(tabLayout.newTab().setText("Bluetooth").setIcon(android.R.drawable.stat_sys_data_bluetooth)); |
I ended up with the output below on using the above snippet. What about you?
Besides we can create our own custom styles in the style.xml as shown below.
1 2 3 4 5 6 7 8 9 10 |
<style name="MyStyle" parent="Widget.Design.TabLayout"> <item name="tabIndicatorColor">#FFFF</item> <item name="tabIndicatorHeight">5dp</item> <item name="tabPaddingStart">8dp</item> <item name="tabPaddingEnd">8dp</item> <item name="tabBackground">?attr/selectableItemBackground</item> <item name="tabSelectedTextColor">#1f2124</item> </style> |
Let’s add the above style to the respective view in activity_main.xml
1 2 3 4 5 6 7 8 9 |
<android.support.design.widget.TabLayout android:id="@+id/tabs" android:layout_width="match_parent" app:tabGravity="fill" app:tabMode="fixed" style="@style/MyStyle" android:layout_height="wrap_content"/> |
We’ve ended up with an output like this:
You can further style it according to your own needs to enhance the UX of your application.
This brings an end to this tutorial. We’ll be implementing TabLayouts with ViewPager in our next application. You can download the Android TabLayouts Project from the below link