ZOFTINO.COM

Navigation with Tabs in Android Apps

Showing next and related actions on a screen is important to allow users to navigate thru hierarchy of screens to perform a task. There are several types of navigational patterns, such as navigation drawers, tabs and bottom navigation bar, to be followed to provide best user experience.

Tab navigation allows user to see few related actions on the screen. If your app has few top level parent actions, the tab navigation is the right choice to provide navigation in your app. The best practice is to display tabs in a single row and below the app bar.

android tablayout with fragments example

Android system provides TabLayout class to display tabs. TabLayout is part of design support library. You need to include design support library dependency in your android project to use tablayout by adding below line to your project gradle build script.

compile 'com.android.support:design:25.0.1'

You can control back ground color, text color, tab size, tabs position, tab types and more using TabLayout attributes. You can add tabs in your code or in xml layout file. TabLayout has a method called addOnTabSelectedListener that can be used to set listeners for tab selection events.

You need just one activity to configure TabLayout and tab content is displayed using fragments. If you want to provide content on swiping to switch tabs, you need to use ViewPager. I’ll show how to implement tabs with fragments without viewpager and tabs with viewpager.

Tablayout with fragments without view pager

Below example shows how to implement tabs with fragments. Tablayout is defined in xml file and listener is added to tablayout in activity’s oncreate method. Based on tab passed to tab selection handler, a fragment is created and displayed.

AndroidManifest.xml

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

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

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

MainActivity

package com.zoftino.tabs;

import android.os.Bundle;
import android.support.design.widget.TabLayout;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;


public class MainActivity extends AppCompatActivity {

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

        getTabContent("");

        TabLayout tabLayout = (TabLayout)findViewById(R.id.tabL);

        tabLayout.addOnTabSelectedListener( new TabLayout.OnTabSelectedListener(){
            public void onTabReselected(TabLayout.Tab tab) {

            }
            public void    onTabSelected(TabLayout.Tab tab){
                String tabId = (String)tab.getText();
                MainActivity.this.getTabContent(tabId);
            }
            public void    onTabUnselected(TabLayout.Tab tab){

            }
        });
    }
    public void getTabContent(String tabIndex){
        TabsContentFragment tabContentFragment = TabsContentFragment.newInstance(tabIndex);

        FragmentTransaction ft = getSupportFragmentManager().beginTransaction();

        ft.replace(R.id.tabContent, tabContentFragment);
        ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
        ft.commit();
    }
}

tabs.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="50dp">
    <android.support.design.widget.TabLayout
        android:layout_height="wrap_content"
        android:layout_width="match_parent"
        android:id="@+id/tabL">

        <android.support.design.widget.TabItem
            android:text="@string/stores"
            android:layout_height="wrap_content"
            android:layout_width="match_parent"
            android:id="@+id/stores"></android.support.design.widget.TabItem>

        <android.support.design.widget.TabItem
            android:text="@string/coupons"
            android:layout_height="wrap_content"
            android:layout_width="match_parent"
            android:id="@+id/coupons"></android.support.design.widget.TabItem>

        <android.support.design.widget.TabItem
            android:text="@string/cashback"
            android:layout_height="wrap_content"
            android:layout_width="match_parent"
            android:id="@+id/cashback"></android.support.design.widget.TabItem>

    </android.support.design.widget.TabLayout>
</RelativeLayout>

activity_main.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:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.zoftino.tabs.MainActivity">
    <include layout="@layout/tabs"></include>
    <LinearLayout
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginBottom="@dimen/activity_vertical_margin"
        android:layout_marginLeft="@dimen/activity_horizontal_margin"
        android:layout_marginRight="@dimen/activity_horizontal_margin"
        android:layout_marginTop="80dp">
    <FrameLayout android:id="@+id/tabContent" android:layout_weight="1" android:layout_width="match_parent" android:layout_height="0dp">
    </FrameLayout>
    </LinearLayout>
</RelativeLayout>

Fragment

package com.zoftino.tabs;

import android.os.Bundle;
import android.support.v4.app.ListFragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ListView;

import java.util.ArrayList;

public class TabsContentFragment extends ListFragment {

    public static TabsContentFragment newInstance(String tabIndex) {
        TabsContentFragment tcf = new TabsContentFragment();

        Bundle args = new Bundle();
        args.putString("tabIndex", tabIndex);
        tcf.setArguments(args);

        return tcf;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {

        ArrayList<String> content = new ArrayList<String>();
        if(getArguments() != null){
            String tabi = getArguments().getString("tabIndex");
            switch (tabi){
                case "Coupons" :
                    content = CouponsData.arrayOfCoupons;
                    break;
                case "Cashback" :
                    content = CouponsData.arrayOfCashback;
                    break;
                default:
                    content = CouponsData.arrayOfStores;
            }
        }

        ListView listView = new ListView(getActivity());
        listView.setAdapter(new ArrayAdapter<String>(getActivity(),
                android.R.layout.simple_list_item_1, content));

        return listView;
    }
    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {

    }
}

Tab layout with view pager and fragments

ViewPager is a layout manager which can be used to provide swipe functionality in your application. In this context, using view pager, tab views can be switched on right swipe or left swipe. In order for view pager to work it needs a page adapter which supplies pages. It is pager adapter responsibility to provide page count and provide page itself based on page number passed to it by page viewer.

To provide swap functionality with tab layout, first we need to add view pager to activity layout xml file. Then create a pager adapter class that supplies views. And set the pager adapter to view pager in the activity’s oncreate method. In this example, pager adapter uses fragment to provide views. Pager adapter’s getItem method creates fragment based on page id passed to it.

android tablayout with fragments and viewpager example

Here the goal is to provide the ability for users to switch tab views both by swiping right or left and by pressing tabs. So to accomplish this behavior, activity class should implement two listeners one listens for tab selection events and second one listens for swipe or page change events. These two listener interfaces are TabLayout.OnTabSelectedListener and ViewPager.OnPageChangeListener.

In TabLayout.OnTabSelectedListener’s onTabSelected method, which gets called when user selects a tab, selected tab index is passed to view pager so that it can render the requested page. This can be done by calling view pager’s setCurrentItem method.

ViewPager.OnPageChangeListener’s onPageSelected method is called when user swipes right or left. In this method, corresponding tab for the current page position is selected in tab layout using swipe page position so that selected tab will be highlighted in UI.

activity_tabsviewpager.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:id="@+id/activity_tab"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.zoftino.tabs.MainActivity">
    <include layout="@layout/tabs"></include>

    <android.support.v4.view.ViewPager
        android:id="@+id/tabViewPager"
        android:layout_width="match_parent"
        android:layout_height="fill_parent"
        android:layout_marginTop="80dp"/>

</RelativeLayout>
 

Activity

 package com.zoftino.tabs;

import android.os.Bundle;
import android.support.design.widget.TabLayout;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;

public class TabsViewPagerActivity extends AppCompatActivity implements TabLayout.OnTabSelectedListener, ViewPager.OnPageChangeListener{
    private ViewPager tabViewPager = null;

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

        ForTabsPagerAdapter tabPagerAdpter =  new ForTabsPagerAdapter(getSupportFragmentManager());
        tabViewPager = (ViewPager) findViewById(R.id.tabViewPager);
        tabViewPager.setAdapter(tabPagerAdpter);
        tabViewPager.addOnPageChangeListener(this);

        TabLayout tabLayout = (TabLayout)findViewById(R.id.tabL);
        tabLayout.addOnTabSelectedListener(this);
    }


    public void onTabReselected(TabLayout.Tab tab) {

    }
    public void    onTabSelected(TabLayout.Tab tab){
        tabViewPager.setCurrentItem(tab.getPosition());
    }
    public void    onTabUnselected(TabLayout.Tab tab){

    }
    @Override
    public void onPageSelected(int position) {
        TabLayout tabLayout = (TabLayout)findViewById(R.id.tabL);
        tabLayout.getTabAt(position).select();
    }

    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

    }

    @Override
    public void onPageScrollStateChanged(int state) {

    }

}

Pager adapter

 package com.zoftino.tabs;

import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;

public class ForTabsPagerAdapter extends FragmentStatePagerAdapter {
        String currentTab = "";
        public ForTabsPagerAdapter(FragmentManager fm) {
            super(fm);
        }

        @Override
        public Fragment getItem(int i) {
            setCurrentTab(i);
            Fragment fragment = TabsContentFragment.newInstance(getCurrentTab());
            return fragment;
        }

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

        @Override
        public CharSequence getPageTitle(int position) {
            return getCurrentTab();
        }
        public void setCurrentTab(int selected){
            switch (selected){
                case 1 :
                    currentTab = "Coupons";
                    break;
                case 2 :
                    currentTab = "Cashback";
                    break;
                default:
                    currentTab = "";
            }
        }

    public String getCurrentTab() {
        return currentTab;
    }
}