Building Tab Layouts in XML Using ViewPager

In Android app development, tab layouts are a common UI pattern for organizing content into separate sections, allowing users to switch between different views with ease. Using XML along with ViewPager to create tab layouts remains a viable approach, especially for projects that haven’t migrated to Jetpack Compose. This article provides a comprehensive guide on building tab layouts using XML and ViewPager.

What is a Tab Layout?

A tab layout is a UI element that displays a horizontal series of tabs, each representing a different view or section of content. Tapping on a tab navigates the user to the associated view, which is typically displayed within a container such as a ViewPager.

Why Use XML and ViewPager?

  • Wide Compatibility: Compatible with older Android versions, making it suitable for projects with broad device support requirements.
  • Simplicity: Straightforward implementation for simple tab layouts without requiring complex state management.
  • Established Pattern: Familiarity among developers, facilitating easier maintenance and updates.

How to Build Tab Layouts in XML Using ViewPager

To implement a tab layout using XML and ViewPager, follow these steps:

Step 1: Add Dependencies

Ensure that you have the necessary dependencies in your build.gradle file. If you’re using AndroidX, add the AndroidX version of the support libraries:

dependencies {
    implementation 'com.google.android.material:material:1.6.0' // or newer
    implementation 'androidx.viewpager:viewpager:1.0.0'
}

If you’re still using the legacy support libraries:

dependencies {
    implementation 'com.android.support:design:28.0.0'
    implementation 'com.android.support:support-v4:28.0.0'
}

Choose the dependencies based on whether your project is using AndroidX or the older support libraries.

Step 2: Create the Layout XML File

Create the main layout XML file (e.g., activity_main.xml) to define the TabLayout and ViewPager:

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

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

    <androidx.viewpager.widget.ViewPager
        android:id="@+id/viewPager"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"/>

</LinearLayout>

In this layout:

  • TabLayout is used to display the tabs.
  • ViewPager is used to swipe between different views.
  • tabMode="fixed" ensures that all tabs are visible, and tabGravity="fill" distributes tabs evenly across the TabLayout.

Step 3: Create Fragment Layouts

Create individual layout XML files for each tab’s content. For example:

fragment_tab1.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#FFEB3B">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:text="Tab 1 Content"
        android:textSize="20sp"/>

</FrameLayout>
fragment_tab2.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#4CAF50">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:text="Tab 2 Content"
        android:textSize="20sp"/>

</FrameLayout>
fragment_tab3.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#F44336">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:text="Tab 3 Content"
        android:textSize="20sp"/>

</FrameLayout>

Step 4: Create Fragments

Create Fragments corresponding to each tab. For example:

Tab1Fragment.java
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.fragment.app.Fragment;

public class Tab1Fragment extends Fragment {
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_tab1, container, false);
    }
}
Tab2Fragment.java
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.fragment.app.Fragment;

public class Tab2Fragment extends Fragment {
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_tab2, container, false);
    }
}
Tab3Fragment.java
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.fragment.app.Fragment;

public class Tab3Fragment extends Fragment {
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_tab3, container, false);
    }
}

Step 5: Create a PagerAdapter

Create a custom PagerAdapter to manage the Fragments within the ViewPager:

import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentPagerAdapter;

import java.util.ArrayList;
import java.util.List;

public class ViewPagerAdapter extends FragmentPagerAdapter {

    private final List<Fragment> fragmentList = new ArrayList<>();
    private final List<String> fragmentTitleList = new ArrayList<>();

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

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

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

    public void addFragment(Fragment fragment, String title) {
        fragmentList.add(fragment);
        fragmentTitleList.add(title);
    }

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

Step 6: Set up the Activity

In your Activity (e.g., MainActivity.java), set up the ViewPager and TabLayout:

import androidx.appcompat.app.AppCompatActivity;
import androidx.viewpager.widget.ViewPager;

import android.os.Bundle;

import com.google.android.material.tabs.TabLayout;

public class MainActivity extends AppCompatActivity {

    private ViewPager viewPager;
    private TabLayout tabLayout;

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

        viewPager = findViewById(R.id.viewPager);
        tabLayout = findViewById(R.id.tabLayout);

        ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
        adapter.addFragment(new Tab1Fragment(), "Tab 1");
        adapter.addFragment(new Tab2Fragment(), "Tab 2");
        adapter.addFragment(new Tab3Fragment(), "Tab 3");

        viewPager.setAdapter(adapter);
        tabLayout.setupWithViewPager(viewPager);
    }
}

Key components:

  • Initialize ViewPager and TabLayout from the layout XML.
  • Create an instance of ViewPagerAdapter and add Fragments to it.
  • Set the adapter for the ViewPager.
  • Use tabLayout.setupWithViewPager(viewPager) to link the TabLayout with the ViewPager.

Advanced Customization

You can further customize the appearance and behavior of the TabLayout:

  • Custom Tab Views: Use custom layouts for individual tabs to add icons or other UI elements.
  • Tab Indicators: Change the color, height, and other properties of the tab indicator using XML attributes or programmatically.
  • Tab Listeners: Implement TabLayout.OnTabSelectedListener to respond to tab selection events and perform actions accordingly.

Here is an example on how to change the colors of tabs

<com.google.android.material.tabs.TabLayout
        android:id="@+id/tabLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:tabMode="fixed"
        app:tabGravity="fill"
        app:tabTextColor="@color/tab_text_color"
        app:tabSelectedTextColor="@color/tab_selected_text_color"
        app:tabIndicatorColor="@color/tab_indicator_color"/>

Conclusion

Building tab layouts in XML using ViewPager is a straightforward and widely adopted approach for creating tabbed interfaces in Android apps. By following the steps outlined in this guide, developers can create functional and visually appealing tab layouts, providing users with an intuitive way to navigate through different sections of content. While modern alternatives like Jetpack Compose offer more advanced capabilities, using XML and ViewPager remains a valuable technique for projects requiring compatibility with older Android versions or simpler implementations.