Android Sliding Tab Layout Example

0

In this article, we will see an example of TabLayout. A TablLayout is part of the support design library to provide the horizontal layout to display tabs. We will also make use of ViewPager to associate a tab with a child view. In order to view the page, user can either select tab or simply swipe between the views.

Set up

  1. Your Android Gradle plugin version must be at least v1.2.3. Here is the project’s gradle build file.build.gradle:
    buildscript {
        repositories {
            jcenter()
        }
        dependencies {
            classpath 'com.android.tools.build:gradle:1.2.3'
        }
    }
    
    allprojects {
        repositories {
            jcenter()
        }
    }
    
  2. In order to use the latest designs in older Android platforms, we need to add support libraries. See Support Library Setup to know more about how to download and setup the support libraries.
  3. Include 'com.android.support:appcompat-v7:23.0.0' to the module’s gradle build file to add support library.
  4. Include 'com.android.support:support-v13:22.2.1' to add support for the Fragment user interface and additional fragment support classes.
  5. We also need to include the support design library 'com.android.support:design:22.2.1', this is required to access the TabLayout feature.
  6. In order to use ViewPager, you also need to include support-v4 library bitsince AppCompat library has an implicit dependency on the support-v4 library you don’t have to explicitly declare it in the gradle build file.
  7. Modify the module’s gradle build file to include the support libraries specified abovebuild.gradle:
    apply plugin: 'com.android.application'
    
    android {
        compileSdkVersion 23
        buildToolsVersion "23.0.0"
    
        defaultConfig {
            applicationId "com.javarticles.tabs"
            minSdkVersion 15
            targetSdkVersion 23
            versionCode 1
            versionName "1.0"
        }
        buildTypes {
            release {
                minifyEnabled false
                proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            }
        }
    }
    
    dependencies {
        compile fileTree(dir: 'libs', include: ['*.jar'])
        compile 'com.android.support:appcompat-v7:23.0.0'
        compile 'com.android.support:support-v13:22.2.1'
        compile 'com.android.support:design:22.2.1'
    }
    

Sliding Tabs Layout – Layout composed of TabLayout and ViewPager

android.support.design.widget.TabLayout represents tab layout, we will use it for rendering the different tab options. The android.support.v4.view.ViewPager component will be used to page between the various fragments we will create. We will include both these components within a RelativeLayout.

Here is the mock TabLayout Layout that we want to see.

Layout composed of TabLayout and Viewpgaer

Layout composed of TabLayout and Viewpgaer

and here is the layout XML.

activity_main.xml:

<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:id="@+id/root_view_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.javarticles.tabs.PianoClassesTabLayout
        android:id="@+id/tab_layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/tab_background"
        app:tabIndicatorColor="@color/tab_indicator" />

    <android.support.v4.view.ViewPager
        android:id="@+id/viewpager_main"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/tab_layout" />

</RelativeLayout>

Class PianoClassesTabLayout is a custom android.support.design.widget.TabLayout. Later we will add methods to create tabs and the tab icons.

PianoClassesTabLayout:

package com.javarticles.tabs;

import android.content.Context;
import android.support.annotation.DrawableRes;
import android.support.annotation.StringRes;
import android.support.design.widget.TabLayout;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;


public class PianoClassesTabLayout extends TabLayout {
    public PianoClassesTabLayout(Context context) {
        super(context);
    }

    public PianoClassesTabLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public PianoClassesTabLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

....
}

Create Fragments

As we select each tab, the content related to the tab will be shown. Since each tab is just a fragment, we need to create and define the Fragment to be shown. In our example, we have two tabs, the first one is about the tutor and the other tab is about piano courses.

Here is the tutor layout.

tutor_layout.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/about_tutor" />

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/tutor_details" />
</LinearLayout>

and the courses layout.

courses_layout.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/about_course" />

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/course_details" />
</LinearLayout>

In onCreateView(), we will the fragment and return the tab content:

PianoTutorFragment:

package com.javarticles.tabs;

import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;


public class PianoTutorFragment extends Fragment {
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        final ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.tutor_layout, container, false);
        return rootView;
    }
}

CoursesFragment:

package com.javarticles.tabs;

import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;


public class CoursesFragment extends Fragment {
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        final ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.courses_layout, container, false);
        return rootView;
    }
}

strings.xml:

<resources>
    <string name="app_name">TabExample</string>
    <string name="about_tutor">About Tutor</string>
    <string name="about_course">About Course</string>
    <string name="courses">Courses</string>
    <string name="hello_world">Hello world!</string>
    <string name="action_settings">Settings</string>
    <string name="tutor_details">He is training students in Piano for ABRSM university, UK for the past 10 years. He is known for his specified and individual approaches to each and every student.</string>
    <string name="course_details">We are conducting summer classes for 2 different age groups. (4 – 10 years and 11 – 16 years.) It will be a fun–filled learning experience to improve their skills and also define their interests towards different activities.</string>
</resources>

Implement FragmentPagerAdapter

In order to associate a tab with page content, we implement the adapter for the ViewPager. We implement getItem(int position), which determines the fragment to show based on the tab’s position.

PianoTabAdapter:

package com.javarticles.tabs;

import android.app.Fragment;
import android.app.FragmentManager;
import android.support.v13.app.FragmentStatePagerAdapter;
import android.util.SparseArray;
import android.view.ViewGroup;

public class PianoTabAdapter extends FragmentStatePagerAdapter {
    public PianoTabAdapter(FragmentManager fm) {
        super(fm);
    }

    @Override
    public Fragment getItem(int position) {
        switch (position) {
            case 0:
                return new PianoTutorFragment();
            case 1:
                return new CoursesFragment();
            default:
                return null;
        }
    }

    @Override
    public int getCount() {
        return 2;
    }
}

Setting up Sliding Tabs

Let’s now come to the main activity, so what do we do here?

  1. We inflate the main layout composed of the tab layout and view pager.
    setContentView(R.layout.activity_main);
  2. We find the ViewPager and TabLayout, attach our ViewPager to the PianoTabAdapter
            mViewPager = (ViewPager) findViewById(R.id.viewpager_main);
            mTabLayout = (PianoClassesTabLayout) findViewById(R.id.tab_layout);
    
            mTabAdapter = new PianoTabAdapter(getFragmentManager());
            mViewPager.setAdapter(mTabAdapter);
  3. Next, we create tabs.
    mTabLayout.createTabs();
  4. As we select the tab, we want the page view to change.
            
           mTabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
                @Override
                public void onTabSelected(TabLayout.Tab tab) {
                    mViewPager.setCurrentItem(tab.getPosition());
                }
    
                @Override
                public void onTabUnselected(TabLayout.Tab tab) {
                    //  nop
                }
    
                @Override
                public void onTabReselected(TabLayout.Tab tab) {
                }
            });
    

PianoClassesMainActivity:

package com.javarticles.tabs;

import android.app.Activity;
import android.app.Fragment;
import android.support.design.widget.TabLayout;
import android.support.v4.view.ViewPager;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;


public class PianoClassesMainActivity extends Activity {
    private ViewPager mViewPager;
    private PianoTabAdapter mTabAdapter;
    private PianoClassesTabLayout mTabLayout;

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

        mViewPager = (ViewPager) findViewById(R.id.viewpager_main);
        mTabLayout = (PianoClassesTabLayout) findViewById(R.id.tab_layout);

        mTabAdapter = new PianoTabAdapter(getFragmentManager());
        mViewPager.setAdapter(mTabAdapter);

        mTabLayout.createTabs();

        mTabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
            @Override
            public void onTabSelected(TabLayout.Tab tab) {
                mViewPager.setCurrentItem(tab.getPosition());
            }

            @Override
            public void onTabUnselected(TabLayout.Tab tab) {
                //  nop
            }

            @Override
            public void onTabReselected(TabLayout.Tab tab) {
            }
        });
    }
}

Adding Icons to the Layout

As we create the tabs, we also set the custom view of the tab.

Tab tab = newTab();
tab.setCustomView(tabView).setContentDescription(contentDescriptionId);
addTab(tab);

The custom view can either contain just the image view or image view along with a title. In the below custom view, we just include an ImageView.

tab_icon.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="wrap_content"
    android:layout_height="@dimen/toolbar_height">

    <ImageView
        android:id="@+id/tab_icon"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        tools:src="@drawable/tab_piano_tutor" />

</RelativeLayout>

We will inflate the above custom view and set the image resource to a drawable XML.

View tabView = LayoutInflater.from(getContext()).inflate(R.layout.tab_icon, null);
ImageView imageView = (ImageView) tabView.findViewById(R.id.tab_icon);
imageView.setImageResource(iconId);

We associate a tab to a drawable resource as we create them.

    public void createTabs() {
        addTab(R.drawable.tab_piano_tutor, R.string.about_tutor);
        addTab(R.drawable.tab_piano_courses, R.string.courses);
    }

Here is the complete TabLayout class.

PianoClassesTabLayout:

package com.javarticles.tabs;

import android.content.Context;
import android.support.annotation.DrawableRes;
import android.support.annotation.StringRes;
import android.support.design.widget.TabLayout;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;


public class PianoClassesTabLayout extends TabLayout {
    public PianoClassesTabLayout(Context context) {
        super(context);
    }

    public PianoClassesTabLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public PianoClassesTabLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    public void createTabs() {
        addTab(R.drawable.tab_piano_tutor, R.string.about_tutor);
        addTab(R.drawable.tab_piano_courses, R.string.courses);
    }

    private void addTab(@DrawableRes int iconId, @StringRes int contentDescriptionId) {
        View tabView = LayoutInflater.from(getContext()).inflate(R.layout.tab_icon, null);
        ImageView imageView = (ImageView) tabView.findViewById(R.id.tab_icon);
        imageView.setImageResource(iconId);
        Tab tab = newTab();
        tab.setCustomView(tabView).setContentDescription(contentDescriptionId);
        addTab(tab);
    }
}

Tab’s Drawable Resource

tab_piano_courses.xml:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/ic_tab_piano_pressed" android:state_selected="true" />
    <item android:drawable="@drawable/ic_tab_piano_normal" />
</selector>

tab_piano_tutor.xml:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/ic_tab_about_tutor_pressed" android:state_selected="true" />
    <item android:drawable="@drawable/ic_tab_about_tutor_normal" />
</selector>

Tab’s normal and pressed state

ic_tab_about_tutor_normal.9

Normal State

Here is the image that represents the normal state.

Tutor’s image in 9-patch format. This one represents pressed state of the tab.

ic_tab_about_tutor_pressed.9

Pressed State

For the courses icon, we have used individual icons for each resolution.

Normal state

Normal state

Pressed State

Pressed State

Run the application

Tutor Tab

Tutor Tab

Tutor Tab

Courses Tab

courses_tab

Download the source code

This was an example about Android TabLayout.

You can download the source code here: TabExample.zip
Share.

Comments are closed.