Android Design Support Library made our day easier by providing backward compatibility to number of material design components all the way back to Android 2.1. In Design support Library the components like navigation drawer, floating action button, snackbar, tabs, floating labels and animation frameworks were introduced. In this article we are going to learn how to implement material tabs in your apps.

1. Making the App Material

1. In Android Studio, go to File ⇒ New ⇒ New Project and fill all the details required to create a new project. When it prompts to select a default activity, select Blank Activity and proceed.

2. Open build.gradle and add android design support library com.android.support:design:27.1.1 or the latest one.

build.gradle

dependencies {
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
    implementation 'com.google.android.material:material:1.1.0'
}

3. Open colors.xml located under res ⇒ values and add the below color values.

colors.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="colorPrimary">#125688</color>
    <color name="colorPrimaryDark">#125688</color>
    <color name="textColorPrimary">#FFFFFF</color>
    <color name="windowBackground">#FFFFFF</color>
    <color name="navigationBarColor">#000000</color>
    <color name="colorAccent">#c8e8ff</color>
</resources>

4. Add the below dimensions to dimens.xml located under res ⇒ values.

dimens.xml

<resources>
    <dimen name="activity_horizontal_margin">16dp</dimen>
    <dimen name="activity_vertical_margin">16dp</dimen>
    <dimen name="tab_max_width">264dp</dimen>
    <dimen name="tab_padding_bottom">16dp</dimen>
    <dimen name="tab_label">14sp</dimen>
    <dimen name="custom_tab_layout_height">72dp</dimen>
    <dimen name="btn_margin_top">10dp</dimen>
</resources>

5. Open styles.xml located under res ⇒ values and add below styles. The styles defined in this styles.xml are common to all the android versions.

<resources>

    <style name="MyMaterialTheme" parent="MyMaterialTheme.Base"/>

    <style name="MyMaterialTheme.Base" parent="Theme.AppCompat.Light.DarkActionBar">
        <item name="windowNoTitle">true</item>
        <item name="windowActionBar">false</item>
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>

</resources>

6. Finally open AndroidManifest.xml and modify the theme to our customized theme by changing the android:theme attribute value.

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.codedecode.androidmaterialtabs">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/MyMaterialTheme">
        <activity
            android:name=".activity.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>

Run the app and verify the material theme by observing the notification bar color. If you see the notification bar color changed, it means that the material design theme is applied successfully.

android-material-design

Now we have our app material ready. So let’s start adding the tabs. But before that we’ll create few fragment activities for testing purpose. All these fragment activities contains very simple UI with only one TextView.

7. Under your main package create a fragment named OneFragment.java and add the below code.

OneFragment.java

package com.codedecode.androidmaterialtabs.fragments;

import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.fragment.app.Fragment;
import com.codedecode.androidmaterialtabs.R;

public class OneFragment extends Fragment {

    public OneFragment() {
        // Required empty public constructor
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_one, container, false);
    }
}

8. Open fragment_one.xml located under res ⇒ layout and do the below changes.

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".fragments.OneFragment">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/one"
        android:textSize="40dp"
        android:textStyle="bold"
        android:layout_centerInParent="true"/>

</RelativeLayout>

9. Likewise create few more fragment activities with same code we used for OneFragment.java. I have created TwoFragment.javaThreeFragment.javaFourFragemnt.java ….. upto TenFragment.java.

2. Fixed Tabs

Fixed tabs should be used when you have limited number of tabs. These tabs are fixed in position. In android design support library lot of new elements like CoordinatorLayout, AppBarLayout, TabLayout and lot more were introduced. I won’t cover all of these as it’s not the agenda of this article.

10. Open the layout activity_main.xml and add below layout code.

app:tabMode – Defines the mode of the tab layout. In our case the value should be “fixed”.

activity_main.xml

<androidx.coordinatorlayout.widget.CoordinatorLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <com.google.android.material.appbar.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

        <androidx.appcompat.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/ThemeOverlay.AppCompat.Light" />

    </com.google.android.material.appbar.AppBarLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

11. Open MainActivity.java and do the below changes.

  • tabLayout.setupWithViewPager() – Assigns the ViewPager to TabLayout.
  • setupViewPager() – Defines the number of tabs by setting appropriate fragment and tab name.
  • ViewPagerAdapter – Custom adapter class provides fragments required for the view pager.

MainActivity.java

package com.codedecode.androidmaterialtabs.activity;

import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentPagerAdapter;
import androidx.viewpager.widget.ViewPager;
import com.codedecode.androidmaterialtabs.R;
import com.codedecode.androidmaterialtabs.fragments.OneFragment;
import com.codedecode.androidmaterialtabs.fragments.ThreeFragment;
import com.codedecode.androidmaterialtabs.fragments.TwoFragment;
import com.google.android.material.tabs.TabLayout;
import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ViewPager viewPager = findViewById(R.id.viewpager);
        setupViewPager(viewPager);

        TabLayout tabLayout = findViewById(R.id.tabs);
        tabLayout.setupWithViewPager(viewPager);
    }

    private void setupViewPager(ViewPager viewPager) {
        ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
        adapter.addFragment(new OneFragment(), "ONE");
        adapter.addFragment(new TwoFragment(), "TWO");
        adapter.addFragment(new ThreeFragment(), "THREE");
        viewPager.setAdapter(adapter);
    }

    static class ViewPagerAdapter extends FragmentPagerAdapter {
        private final List<Fragment> mFragmentList = new ArrayList<>();
        private final List<String> mFragmentTitleList = new ArrayList<>();

        ViewPagerAdapter(FragmentManager manager) {
            super(manager);
        }

        @Override
        public Fragment getItem(int position) {
            return mFragmentList.get(position);
        }

        @Override
        public int getCount() {
            return mFragmentList.size();
        }

        void addFragment(Fragment fragment, String title) {
            mFragmentList.add(fragment);
            mFragmentTitleList.add(title);
        }

        @Override
        public CharSequence getPageTitle(int position) {
            return mFragmentTitleList.get(position);
        }
    }
}

Now run the app. You should able to see the tabs displayed with swipe functionality between the tabs.

android-material-design-tab-layout

 

2.1 Full Width Tabs

If you want the tabs to be occupied the fullwidth of the screen, you need to assign app:tabGravity=”fill” to our TabLayout.

android-material-design-tab-layout

2.2 Center Aligned Tabs

If you want to keep your tabs horizontally centered, assign app:tabGravity=”center” to TabLayout.

simple tab

3. Scrollable Tabs

The scrollable tabs should be used when you have many number of tabs where there is insufficient space on the screen to fit all of them. To make the tabs scrollable, set app:tabMode=”scrollable” to TabLayout.

12. open activity_main.xml and change the app:tabMode to scrollable.

<com.google.android.material.tabs.TabLayout
     android:id="@+id/tabs"
     android:layout_width="match_parent"
     android:layout_height="@dimen/custom_tab_layout_height"
     app:tabMode="scrollable"/>

13. edit MainActivity.java and add few fragments to ViewPager in setupViewPager() method. I have added total of 10 fragments to ViewPager. After the changes, your main activity should look like below.

MainActivity.java

package com.codedecode.androidmaterialtabs.activity;

import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentPagerAdapter;
import androidx.viewpager.widget.ViewPager;
import com.codedecode.androidmaterialtabs.R;
import com.codedecode.androidmaterialtabs.fragments.EightFragment;
import com.codedecode.androidmaterialtabs.fragments.FiveFragment;
import com.codedecode.androidmaterialtabs.fragments.FourFragment;
import com.codedecode.androidmaterialtabs.fragments.NineFragment;
import com.codedecode.androidmaterialtabs.fragments.OneFragment;
import com.codedecode.androidmaterialtabs.fragments.SevenFragment;
import com.codedecode.androidmaterialtabs.fragments.SixFragment;
import com.codedecode.androidmaterialtabs.fragments.TenFragment;
import com.codedecode.androidmaterialtabs.fragments.ThreeFragment;
import com.codedecode.androidmaterialtabs.fragments.TwoFragment;
import com.google.android.material.tabs.TabLayout;
import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Toolbar toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        ViewPager viewPager = findViewById(R.id.viewpager);
        setupViewPager(viewPager);

        TabLayout tabLayout = findViewById(R.id.tabs);
        tabLayout.setupWithViewPager(viewPager);
    }

    private void setupViewPager(ViewPager viewPager) {
        ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
        adapter.addFrag(new OneFragment(), "ONE");
        adapter.addFrag(new TwoFragment(), "TWO");
        adapter.addFrag(new ThreeFragment(), "THREE");
        adapter.addFrag(new FourFragment(), "FOUR");
        adapter.addFrag(new FiveFragment(), "FIVE");
        adapter.addFrag(new SixFragment(), "SIX");
        adapter.addFrag(new SevenFragment(), "SEVEN");
        adapter.addFrag(new EightFragment(), "EIGHT");
        adapter.addFrag(new NineFragment(), "NINE");
        adapter.addFrag(new TenFragment(), "TEN");
        viewPager.setAdapter(adapter);
    }

    static class ViewPagerAdapter extends FragmentPagerAdapter {
        private final List<Fragment> mFragmentList = new ArrayList<>();
        private final List<String> mFragmentTitleList = new ArrayList<>();

        ViewPagerAdapter(FragmentManager manager) {
            super(manager);
        }

        @Override
        public Fragment getItem(int position) {
            return mFragmentList.get(position);
        }

        @Override
        public int getCount() {
            return mFragmentList.size();
        }

        void addFrag(Fragment fragment, String title) {
            mFragmentList.add(fragment);
            mFragmentTitleList.add(title);
        }

        @Override
        public CharSequence getPageTitle(int position) {
            return mFragmentTitleList.get(position);
        }
    }
}

Now if you run the app, you can see the more number of tabs with scrollable functionality.

android-scrollable-tab-layout

android-scrollable-tab-layout 2

4. Tabs with Icon & Text

Sometimes you might wanted to add an icon to Tab. Earlier adding an icon to tab is tedious process. But with the design support library it is very easy. All you have to do is call setIcon() method by passing appropriate icon. The icon will be placed in front of tab label.

tabLayout.getTabAt(0).setIcon(tabIcons[0]);
tabLayout.getTabAt(1).setIcon(tabIcons[1]);
tabLayout.getTabAt(2).setIcon(tabIcons[2]);

14. Add MainActivity.java and insert code as below. Here I have added a new method called setupTabIcons() in which I have set all the tab icons.

MainActivity.java

package com.codedecode.androidmaterialtabs.activity;

import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentPagerAdapter;
import androidx.viewpager.widget.ViewPager;
import com.codedecode.androidmaterialtabs.R;
import com.codedecode.androidmaterialtabs.fragments.OneFragment;
import com.codedecode.androidmaterialtabs.fragments.ThreeFragment;
import com.codedecode.androidmaterialtabs.fragments.TwoFragment;
import com.google.android.material.tabs.TabLayout;
import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {

    private TabLayout tabLayout;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ViewPager viewPager = findViewById(R.id.viewpager);
        setupViewPager(viewPager);

        tabLayout = findViewById(R.id.tabs);
        tabLayout.setupWithViewPager(viewPager);
        setupTabIcons();
    }

    private void setupTabIcons() {
        int[] tabIcons = {
                R.drawable.ic_tab_favourite,
                R.drawable.ic_tab_call,
                R.drawable.ic_tab_contacts
        };

        tabLayout.getTabAt(0).setIcon(tabIcons[0]);
        tabLayout.getTabAt(1).setIcon(tabIcons[1]);
        tabLayout.getTabAt(2).setIcon(tabIcons[2]);
    }

    private void setupViewPager(ViewPager viewPager) {
        ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
        adapter.addFrag(new OneFragment(), "ONE");
        adapter.addFrag(new TwoFragment(), "TWO");
        adapter.addFrag(new ThreeFragment(), "THREE");
        viewPager.setAdapter(adapter);
    }

    static class ViewPagerAdapter extends FragmentPagerAdapter {
        private final List<Fragment> mFragmentList = new ArrayList<>();
        private final List<String> mFragmentTitleList = new ArrayList<>();

        ViewPagerAdapter(FragmentManager manager) {
            super(manager);
        }

        @Override
        public Fragment getItem(int position) {
            return mFragmentList.get(position);
        }

        @Override
        public int getCount() {
            return mFragmentList.size();
        }

        void addFrag(Fragment fragment, String title) {
            mFragmentList.add(fragment);
            mFragmentTitleList.add(title);
        }

        @Override
        public CharSequence getPageTitle(int position) {

            // return null to display only the icon
            return null;
        }
    }
}

android-tab-layout-with-only-icons

5. Tabs with only Icons

Setting only icon to tab is same as setting text and icon except the method getPageTitle() in ViewPagerAdapter class returns null instead of tab label.

15. Open MainActivity.java and modify the getPageTitle() method as below and run the project.

@Override
public CharSequence getPageTitle(int position) {

    // return null to display only the icon
    return null;
}

android tab layout with only icons

6. Custom Tab View with Icon & Text

Setting a custom view to the tab is very useful when you are not able to achieve desired output by following the methods provided by tab layout. While setting a custom view to tab, make sure that you follow the specs suggested by android for tabs.

When we set the tab an icon and text, you can see the icon is horizontally aligned with tab text. But if you want to place the icon above the tab label, you have to use a custom view to achive it.

16. Under res ⇒ values, create an xml file named fonts.xml and add below string value. This xml file defines the font family for the tab label.

fonts.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="font_fontFamily_medium">sans-serif</string>
</resources>

17. Open activity_main.xml and set the custom height to TabLayout. Setting this height is important as placing icon above the tab label takes more space than normal.

<com.google.android.material.tabs.TabLayout
        android:id="@+id/tabs"
        android:layout_width="match_parent"
        android:layout_height="@dimen/custom_tab_layout_height"
        app:tabMode="fixed"
        app:tabGravity="fill"/>
</com.google.android.material.appbar.AppBarLayout>

18. Create an xml layout named custom_tab.xml under res ⇒ layout. In this layout we have defined the custom view for the tab.

custom_tab.xml

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:gravity="center_horizontal"
    android:id="@+id/tab"
    android:textColor="@color/colorAccent"
    android:textSize="@dimen/tab_label"
    android:fontFamily="@string/font_fontFamily_medium"/>

19. Open MainActivity.java and modify the code as below. Here if you observe setupTabIcons() method, I have rendered custom_tab.xml layout in each tab using below lines of code.

TextView tabOne = (TextView) LayoutInflater.from(this).inflate(R.layout.custom_tab, null);
tabOne.setText("ONE");
tabOne.setCompoundDrawablesWithIntrinsicBounds(0, R.drawable.ic_tab_favourite, 0, 0);
tabLayout.getTabAt(0).setCustomView(tabOne);

MainActivity.java

package com.codedecode.androidmaterialtabs.activity;

import android.os.Bundle;
import android.view.LayoutInflater;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentPagerAdapter;
import androidx.viewpager.widget.ViewPager;
import com.codedecode.androidmaterialtabs.R;
import com.codedecode.androidmaterialtabs.fragments.OneFragment;
import com.codedecode.androidmaterialtabs.fragments.ThreeFragment;
import com.codedecode.androidmaterialtabs.fragments.TwoFragment;
import com.google.android.material.tabs.TabLayout;
import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {

    private TabLayout tabLayout;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Toolbar toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        ViewPager viewPager = findViewById(R.id.viewpager);
        setupViewPager(viewPager);

        tabLayout = findViewById(R.id.tabs);
        tabLayout.setupWithViewPager(viewPager);
        setupTabIcons();
    }

    /**
     * Adding custom view to tab
     */
    private void setupTabIcons() {

        TextView tabOne = (TextView) LayoutInflater.from(this).inflate(R.layout.custom_tab, null);
        tabOne.setText("ONE");
        tabOne.setCompoundDrawablesWithIntrinsicBounds(0, R.drawable.ic_tab_favourite, 0, 0);
        tabLayout.getTabAt(0).setCustomView(tabOne);

        TextView tabTwo = (TextView) LayoutInflater.from(this).inflate(R.layout.custom_tab, null);
        tabTwo.setText("TWO");
        tabTwo.setCompoundDrawablesWithIntrinsicBounds(0, R.drawable.ic_tab_call, 0, 0);
        tabLayout.getTabAt(1).setCustomView(tabTwo);

        TextView tabThree = (TextView) LayoutInflater.from(this).inflate(R.layout.custom_tab, null);
        tabThree.setText("THREE");
        tabThree.setCompoundDrawablesWithIntrinsicBounds(0, R.drawable.ic_tab_contacts, 0, 0);
        tabLayout.getTabAt(2).setCustomView(tabThree);
    }

    /**
     * Adding fragments to ViewPager
     */
    private void setupViewPager(ViewPager viewPager) {
        ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
        adapter.addFrag(new OneFragment(), "ONE");
        adapter.addFrag(new TwoFragment(), "TWO");
        adapter.addFrag(new ThreeFragment(), "THREE");
        viewPager.setAdapter(adapter);
    }

    static class ViewPagerAdapter extends FragmentPagerAdapter {
        private final List<Fragment> mFragmentList = new ArrayList<>();
        private final List<String> mFragmentTitleList = new ArrayList<>();

        ViewPagerAdapter(FragmentManager manager) {
            super(manager);
        }

        @Override
        public Fragment getItem(int position) {
            return mFragmentList.get(position);
        }

        @Override
        public int getCount() {
            return mFragmentList.size();
        }

        void addFrag(Fragment fragment, String title) {
            mFragmentList.add(fragment);
            mFragmentTitleList.add(title);
        }

        @Override
        public CharSequence getPageTitle(int position) {
            return mFragmentTitleList.get(position);
        }
    }
}

Now if you run the app, you can see the icon placed above the tab label.

android-tab-layout-with-custom-view-icon-and-text

Download Code

Happy Coding 🙂