• Meghan Gill

Swipe Tabs Example with TabLayout & ViewPager2

Updated: Jun 26, 2021

Swipe views allow you to navigate between sibling screens, such as tabs, with a horizontal finger gesture, or swipe. This navigation pattern is also referred to as horizontal paging. In this tutorial we will create an app with swipe tabs. The app has TabLayout with three tabs: Home, Settings and Favorites. We can navigate to a tab by touching the tab label or swiping.





Create a new project and select Empty Activity. Call the project Swipe Tabs Example.


Part I: XML


Step 1: In activity_main.xml add <com.google.android.material.tabs.TabLayout


What is TabLayout?

TabLayout provides a horizontal layout to display tabs. To make that clear you can give the TabLayout a background color. Here I’ve chosen #E0E69D


The width should “match_parent” and we want our tabs at the top of the screen so constrain the top to the top of “parent”.


Step 2: Add the ViewPager2 widget <androidx.viewpager2.widget.ViewPager2


ViewPager2 is the container for fragments. So, there will be one fragment for each tab.


See the code for activity_main.xml below:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <com.google.android.material.tabs.TabLayout
        android:id="@+id/tabLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toTopOf="parent"
        android:background="#E0E69D" />

    <androidx.viewpager2.widget.ViewPager2
        android:id="@+id/viewPager2"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        app:layout_constraintTop_toBottomOf="@id/tabLayout"
        app:layout_constraintBottom_toBottomOf="parent"/>

</androidx.constraintlayout.widget.ConstraintLayout>

Part II: Add Adapter


Step 1: Right click on the package name. Create a new Java Class. Name the class ViewPager2Adapter. There should be no spaces in a class name and it should be CamelCase.

New > Java Class > ViewPager2Adapter


Step 2: In code make ViewPager2Adapter extend FragmentStateAdapter

public class ViewPager2Adapter extends FragmentStateAdapter

What is FragmentStateAdapter?

FragmentStateAdapter is the newer version of FragmentPagerAdapter, which is deprecated. FragmentStateAdapter should be used with ViewPager2.

What does FragmentStateAdapter do?

For ViewPager2 we need the adapter to set the data for the fragments. We need to pass the number of fragments to set them into ViewPager2. You can create any number of fragments and inject them into ViewPager, so that when you swipe, the ViewPager will automatically show the fragments one after the other.

Step 3: Implement all the necessary methods that need to be overridden. You can do that by clicking the class name and pressing Option + Enter. Choose Implement methods and select all the methods.


ViewPager2Adapter should now include:

@NonNull
@Override
public Fragment createFragment(int position) {
    return null;
}

@Override
public int getItemCount() {
    return 0;
}

Step 4: Choose the correct constructor. FragmentStateAdapter has three available. Click FragmentStateAdapter and press Option Enter to create a constructor. Choose FragmentStateAdapter(fragmentActivity:FragmentActivity).

public ViewPager2Adapter(@NonNull FragmentActivity fragmentActivity) {
    super(fragmentActivity);
}

Step 5: Create a class level variable named private ArrayList<Fragment> fragments;


Step 6: Create a new method and assign the data for the fragments variable:


 public void setData(ArrayList<Fragment> fragments) {
    this.fragments = fragments;
}

We use the this operator so that we can use the same variable name for the method parameter and the class level variable. this.fragments is the class member variable. The second fragments is the method parameter variable.


Step 8: In the method getItemCount() change it to return fragments.size();


Step 9: In the method createFragment() change it to return fragments.get(position);


Code for ViewPager2Adapater.java:

package io.meghandev.swipetabsexample;

import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.viewpager2.adapter.FragmentStateAdapter;

import java.util.ArrayList;

public class ViewPager2Adapter extends FragmentStateAdapter {
    private ArrayList<Fragment> fragments; //variable holds the fragments the ViewPager2 allows us to swipe to.

    public ViewPager2Adapter(@NonNull FragmentActivity fragmentActivity) {         //this is the constructor
        super(fragmentActivity); 

    }

    @NonNull
    @Override
    public Fragment createFragment(int position) {
        return fragments.get(position);
    }

    @Override
    public int getItemCount() {
        return fragments.size();
    }

    public void setData(ArrayList<Fragment> fragments) {
        this.fragments = fragments;
    }
}


Part III: Create Fragments


Step 1: We will be using three blank fragments. To create a fragment, right click on the package name, select New, Fragment, Fragment(Blank). Name it HomeFragment. It will automatically generate a layout XML file.


New > Fragment > Fragment(Blank) > HomeFragment


Step 2: Create the other fragments you will be using. Name them SettingsFragment and FavoritesFragment. These fragments will automatically generate XML files.


Part IV: Main Activity, Create Method


Step 1: Create a ViewPager2 variable and inside onCreate( ) use findViewById(int) to retrieve the widget in the UI so we can work with it programmatically.


viewPager2 = findViewById(R.id.viewPager2);

Step 2: Create a public method. Call it setViewPagerAdapter( )


public void setViewPagerAdapter() 

Step 3: Inside setViewPagerAdapter() create a variable of type ViewPager2Adapter. Name it viewPager2Adapter.


Step 4: Add an ArrayList of fragments and add the fragments you have made.


public void setViewPagerAdapter() {
    ViewPager2Adapter viewPager2Adapter = new                  
        ViewPager2Adapter(this);
    ArrayList<Fragment> fragmentList = new ArrayList<>(); //creates     
        an ArrayList of Fragments
    fragmentList.add(new HomeFragment());
    fragmentList.add(new SettingsFragment());
    fragmentList.add(new FavoritesFragment());

}

Step 5: Now we can connect the ViewPager2 to the ViewPager2Adapter programmatically by using the setData() method and the setAdapter() method.


viewPager2Adapter.setData(fragmentList); //sets the data for the adapter
viewPager2.setAdapter(viewPager2Adapter);  

The full setViewPagerAdapter() method should read:


public void setViewPagerAdapter() {
    ViewPager2Adapter viewPager2Adapter = new     
        ViewPager2Adapter(this);
    ArrayList<Fragment> fragmentList = new ArrayList<>(); //creates 
        an ArrayList of Fragments
    fragmentList.add(new HomeFragment());
    fragmentList.add(new SettingsFragment());
    fragmentList.add(new FavoritesFragment());
    viewPager2Adapter.setData(fragmentList); //sets the data for 
        the adapter
    viewPager2.setAdapter(viewPager2Adapter); 

}

Run the app and take a victory lap.


You have now implemented swiping between fragments.



We still have a few things left to do. We can see the swiping, but let's add some color and text to distinguish each fragment for testing purposes. Also, at the top we have a TabLayout but we haven't added any tabs yet. So that's on the agenda as well.

Part V: XML


Step 1: Give a background color and some text to each fragment. Go to fragment_home.xml and change the text to "Home Fragment" and increase its size to "24sp". Add a background color. Here I've chosen #CFDCDF.


<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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=".HomeFragment">
    
    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="Home fragment"
        android:textSize="24sp"
        android:background="#CFDCDF"/>

</FrameLayout> 

Step 2: Repeat for fragment_settings.xml and fragment_favorites.xml. I've chosen the background colors #EFDECD and #CFDFCD.



Part V: themes.xml


When we use TabLayout we already have a tab, so we will choose a theme without an action bar.


Step 1: Go to the res folder, select values and open themes.xml.


res > values > themes > themes.xml

Change the parent theme so that it does not have an action bar.


<style name="Theme.SwipeTabsExample" parent="Theme.MaterialComponents.DayNight.NoActionBar">

Part VI: Main Activity & TabLayoutMediator


At this stage we need to set the data for the tabs. To do this, we use TabLayoutMediator and implement the onConfigureTab() method from the tabConfigurationStrategy.

Step 1: In Main Activity, create a variable of type TabLayout. Name it tabLayout. In onCreate assign tabLayout to its UI widget using findViewById( ).


tabLayout = findViewById(R.id.tabLayout);

Step 2: We need to create a TabLayoutMediator to connect the TabLayout to ViewPager2.


new TabLayoutMediator(tabLayout, viewPager2, this).attach();


Step 3: this will show an error. We need to implement the tabConfigurationStrategy. Click on this and press Option + Enter. Make Main Activity implement com.google.android.material.tabs.TabLayoutMediator.TabConfigurationStrategy and the method onConfigureTab(). onConfigureTab will allow us to customize our tabs.


Step 4: Create a new global variable named ArrayList<String> titles; We will need these titles as the titles of our tabs. In onCreate add the names of the tabs as follows:


titles = new ArrayList<String>();
titles.add("Home");
titles.add("Settings");
titles.add("Favorites");

Step 5: Set the text for the tab labels in the onConfigureTab ( ) method.


@Override
public void onConfigureTab(@NonNull TabLayout.Tab tab, int position) {
    tab.setText(titles.get(position));
}


Run the app. Appreciate navigating with your new tab labels and swiping between fragments.



Complete code for MainActivity.java

package io.meghandev.swipetabsexample;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.viewpager2.widget.ViewPager2;

import android.os.Bundle;

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

import java.util.ArrayList;

public class MainActivity extends AppCompatActivity implements TabLayoutMediator.TabConfigurationStrategy {
    //global variables
    ViewPager2 viewPager2; 
    TabLayout tabLayout;
    ArrayList<String> titles;

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

        viewPager2 = findViewById(R.id.viewPager2);
        tabLayout = findViewById(R.id.tabLayout);
        titles = new ArrayList<String>();
        titles.add("Home");
        titles.add("Settings");
        titles.add("Favorites");
        setViewPagerAdapter();
        new TabLayoutMediator(tabLayout, viewPager2, this).attach();
    }

    public void setViewPagerAdapter() {
        ViewPager2Adapter viewPager2Adapter = new ViewPager2Adapter(this);
        ArrayList<Fragment> fragmentList = new ArrayList<>(); //creates an ArrayList of Fragments
        fragmentList.add(new HomeFragment());
        fragmentList.add(new SettingsFragment());
        fragmentList.add(new FavoritesFragment());
        viewPager2Adapter.setData(fragmentList); //sets the data for the adapter
        viewPager2.setAdapter(viewPager2Adapter);

    }


    @Override
    public void onConfigureTab(@NonNull TabLayout.Tab tab, int position) {
        tab.setText(titles.get(position));
    }
}

For more information on Tabs check out Android Material Design: Tabs with TabLayout


3,110 views1 comment

Recent Posts

See All