I want to use com.google.android.material.tabs.TabLayout
component with Android's new ViewPager
implementation androidx.viewpager2.widget.ViewPager2
. However, the setupWithViewPager(..)
method provided by TabLayout
supports only the old ViewPager
implementation. Is there a way to bind a TabLayout
to a ViewPager2
component easily?

- 10,997
- 7
- 33
- 52

- 5,973
- 3
- 42
- 73
-
Perhaps this ViewPager2 sample from Google would help: https://github.com/android/views-widgets-samples/tree/master/ViewPager2 – IgorGanapolsky Mar 04 '20 at 00:25
12 Answers
You have to use this TabLayoutMediator
that mimics tabLayout.setupWithViewPager()
and sets up the ViewPager2
with Tablayout
. Otherwise, you will have to write your own adapter that will combine both parties.
Its code will look like this in Kotlin
TabLayoutMediator(tabLayout, viewPager) { tab, position ->
tab.text = tabTitles[position]
}.attach()

- 4,265
- 5
- 38
- 57

- 49,966
- 15
- 119
- 148
-
16Code to use this **TabLayoutMediator** is as follow: `TabLayoutMediator(tabLayout, viewPager2) { tab, position -> viewPager2.setCurrentItem(tab.position, true) if (position == 1) tab.setText("Test2") if (position == 0) tab.setText("Test1") }.attach()` – taranjeetsapra Apr 13 '19 at 20:04
-
5anyone reading this should double check the material library version of their app. `TabLayoutMediator` is present in `implementation 'com.google.android.material:material:1.1.0-alpha08' `, but android studio had imported version `1.0.0` by default for me, which did not had this. – ansh sachdeva Aug 23 '19 at 23:08
-
2How can I set dots on the TabLayout (like a carousel), instead of numbers in tabs? – IgorGanapolsky Mar 09 '20 at 21:17
-
6`viewPager.setCurrentItem(tab.position, true)` is unnecessary and causes the 2nd tab to be selected and the pages to be swiped always! – ericn May 14 '20 at 22:41
-
1@ericn you are right brother, setting current item is done swip itself. – Vikas Pandey Aug 26 '20 at 18:36
-
1@IgorGanapolsky Hi, you just have to app:tabBackground="@drawable/tab_selector" and yout tab_selector should provide different drwable for selected and unselected case – Vikas Pandey Aug 26 '20 at 18:38
-
@anshsachdeva I am using thr latest 1.3.0-alpha02, but i can't find TablayoutMediator class – Vikas Pandey Sep 20 '20 at 18:02
-
@ericn, if remove `viewPager.setCurrentItem(tab.position, true)`, it will show tabs, but we won't have enough control over a fragment (for instance, won't filter a list in `RecyclerView`). So, it should be added. – CoolMind Feb 03 '21 at 11:56
-
If you call this method from `onCreateView`, make sure `viewPager != null` or will get NPE. – CoolMind Feb 03 '21 at 11:57
-
No hacks, no extensions, no TabLayoutMediator
I am on implementation 'com.google.android.material:material:1.2.0-alpha02'
and do the following without needing the TabLayoutMediator.
Instead, I link the TabLayout with the ViewPager2 using the method described here. I've also added a working example to github here. I think I've minimized the solution to a minimal working example. I'll explain the important bits.
Adding the elements to the template
First we'll need to add the TabLayout and ViewPager2 to the layout. I've placed them inside a LinearLayout and CoordinatorLayout here, but you can do whatever you like of course.
<!-- activity_main.xml -->
<?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">
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.google.android.material.tabs.TabLayout
android:id="@+id/tabLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
Connecting an adapter to the viewpager
So the adapter is in charge of supplying the correct fragments to the activity. You'll have to extend FragmentStateAdapter which I've done very simply as below (it's a private class because it's declared within my MainActivity.java here):
private class ViewStateAdapter extends FragmentStateAdapter {
public ViewStateAdapter(@NonNull FragmentManager fragmentManager, @NonNull Lifecycle lifecycle) {
super(fragmentManager, lifecycle);
}
@NonNull
@Override
public Fragment createFragment(int position) {
// Hardcoded in this order, you'll want to use lists and make sure the titles match
if (position == 0) {
return new BarFragment();
}
return new FooFragment();
}
@Override
public int getItemCount() {
// Hardcoded, use lists
return 2;
}
}
I can then connect my own Adapter to the ViewPager as below:
FragmentManager fm = getSupportFragmentManager();
ViewStateAdapter sa = new ViewStateAdapter(fm, getLifecycle());
final ViewPager2 pa = findViewById(R.id.pager);
pa.setAdapter(sa);
I've added the fragments to my viewpager. (Because I hardcoded the Fragments in my adapter, you should use a list and something like an 'addFragment' method or something)
The TabLayout
Then with
TabLayout tabLayout = findViewById(R.id.tabLayout);
tabLayout.addTab(tabLayout.newTab().setText("Bar"));
tabLayout.addTab(tabLayout.newTab().setText("Foo"));
I add two tabs to my TabLayout, showing the titles but not letting me switch to the fragments yet.
Connecting TabLayout to Adapter
tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
pa.setCurrentItem(tab.getPosition());
}
@Override
public void onTabUnselected(TabLayout.Tab tab) {
}
@Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
This should be pretty straightforward. User clicks on a tab, I get the position in my callback and I simply set the adapter's current item to that position.
Change Tab when swiping
Finally we couple back when the user swipes the fragment to set the correct tab item as selected
pa.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
@Override
public void onPageSelected(int position) {
tabLayout.selectTab(tabLayout.getTabAt(position));
}
});

- 959
- 8
- 10
-
2
-
-
Thanks for the answer, can you tell me will the swiping between tabs cause the fragments to be recreated? – Kraken Sep 21 '21 at 12:12
UPDATE
check this Create swipe views with tabs using ViewPager2
Here is the Updated answer How to use TabLayout with ViewPager2 in Android
Now we no need to create a class from TabLayoutMediator
Use below dependencies
implementation 'com.google.android.material:material:1.1.0-alpha08'
implementation 'androidx.viewpager2:viewpager2:1.0.0-beta02'
SAMPLE CODE
XMl layout
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout
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">
<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.tabs.TabLayout
android:id="@+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</com.google.android.material.appbar.AppBarLayout>
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/viewpager"
app:layout_anchor="@id/tabs"
app:layout_anchorGravity="bottom"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
Activity
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.android.synthetic.main.activity_main.*
import com.google.android.material.tabs.TabLayoutMediator
import com.google.android.material.tabs.TabLayout
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// setSupportActionBar(toolbar)
viewpager.adapter = AppViewPagerAdapter(supportFragmentManager, lifecycle)
TabLayoutMediator(tabs, viewpager, object : TabLayoutMediator.OnConfigureTabCallback {
override fun onConfigureTab(tab: TabLayout.Tab, position: Int) {
// Styling each tab here
tab.text = "Tab $position"
}
}).attach()
}
}
UPDATE
If your using implementation 'com.google.android.material:material:1.1.0-alpha10'
then use below code
TabLayoutMediator(tabs, viewpage,
TabLayoutMediator.TabConfigurationStrategy { tab, position ->
when (position) {
0 -> { tab.text = "TAB ONE"}
1 -> { tab.text = "TAB TWO"}
}
}).attach()
OUTPUT
-
3anyone reading this should double check the material library version of their app. this version worked for me, but android studio had imported version 1.0.0 by default which did not had this – ansh sachdeva Aug 16 '19 at 11:34
-
1@anshsachdeva same, I cannot find TabLayoutMediator class in com.google.android.material:material:1.0.0-alpha08, com.google.android.material:material:1.0.0-alpha09. – Seyid-Kanan Bagirov Aug 23 '19 at 20:00
-
4@Seyid-KananBagirov it is present in implementation 'com.google.android.material:material:1.1.0-alpha08' (notice the version 1.1.0-alpha08 and not 1.0.0) – ansh sachdeva Aug 23 '19 at 23:04
-
4in 1.1.0-alpha10 they renamed `TabLayoutMediator.OnConfigureTabCallback` to `TabLayoutMediator.TabConfigurationStrategy` – Almighty Sep 08 '19 at 05:13
-
-
@crmepham you need to create `AppViewPagerAdapter` class like this https://github.com/RathodNilesh14/TabLayout-with-viewpager2-/blob/master/app/src/main/java/com/nilu/demoapplication/AppViewPagerAdapter.kt – AskNilesh Sep 09 '19 at 04:56
-
-
1
-
1@NileshRathod Thank you. Why do we have to specify TabConfigurationStrategy ? It's marked as non-null, but I actually don't need to do anything for the callback. To me it's empty... – android developer Sep 19 '19 at 08:07
-
also tabl;ayoutmediatar is unsupported now, we should use some other method to attach tablayout and viewpager 2 – Vikas Pandey Oct 07 '20 at 06:49
-
In the accepted answer we also have `viewPager.setCurrentItem(tab.position, true)`. It makes more control over fragments. – CoolMind Feb 03 '21 at 12:02
-
the new way to connect viewpager2 and tablayout also solve issue where we will get crash if still using the old way to connect viewpager2 and tablayout when I turned on ProGuard – Franz Andel May 26 '21 at 13:19
Initialize the TabLayoutMediator
object with an object of TabLayout
, ViewPager2
, autoRefresh
-- boolean type, and an object of OnConfigurationChangeCallback
.
TabLayoutMediator tabLayoutMediator = new TabLayoutMediator(tabLayout, viewPager2, true, new TabLayoutMediator.OnConfigureTabCallback() {
@Override
public void onConfigureTab(TabLayout.Tab tab, int position) {
// position of the current tab and that tab
}
});
Finally just call attach()
to the TabLayoutMediator
object to wire up the tablayout to the viewpager :-
tabLayoutMediator.attach();
autoRefresh
- key if set to true
-- ( By default its set to true )
RECREATES
all the tabs of thetabLayout
ifnotifyDataSetChanged
is called to the viewpageradapter
.
Use the contents of TabLayoutMediator.java

- 54,294
- 25
- 151
- 185

- 10,997
- 7
- 33
- 52
You can use Kotlin extension function:
fun TabLayout.setupWithViewPager(viewPager: ViewPager2, labels: List<String>) {
if (labels.size != viewPager.adapter?.itemCount)
throw Exception("The size of list and the tab count should be equal!")
TabLayoutMediator(this, viewPager,
TabLayoutMediator.TabConfigurationStrategy { tab, position ->
tab.text = labels[position]
}).attach()
}
And call it:
tabLayout.setupWithViewPager(viewPager, listOf("Tab A", "Tab B"))

- 1,421
- 14
- 16
-
What dependency do I need to add in order to use this extension fun? – Bartek Pacia Jan 20 '20 at 14:22
-
There is not any dependency except Kotlin in order to use extension functions :) – seyfullah.bilgin Jan 20 '20 at 16:33
-
1Yeah, I know. I meant what Android KTX artifact must I add in order to use this extension function. Also I don't have `setupWithViewPager(ViewPager2, List)` available – I only have `setupWithViewPager(ViewPager)` – Bartek Pacia Jan 20 '20 at 18:11
-
You should implement ViewPager2 (androidx.viewpager2:1.0.0) and matarial components (com.google.android.material:material:1.2.0-alpha03) as artifact to able to use this extension function. – seyfullah.bilgin Jan 21 '20 at 09:16
-
And i also recommend to use ViewPager2 instead of old ViewPager component. – seyfullah.bilgin Jan 21 '20 at 13:37
-
Yeah I had those artifacts included and that extension function wasn't available. I somehow got it working without using that extension func. Thanks anyway. – Bartek Pacia Jan 23 '20 at 11:46
If you're coding in JAVA. You can use the following adapter for the viewPager2:
public class ViewPagerAdapter extends FragmentStateAdapter {
private static final int CARD_ITEM_SIZE = 10;
public ViewPagerAdapter(@NonNull FragmentActivity fragmentActivity) {
super(fragmentActivity);
}
@NonNull @Override public Fragment createFragment(int position) {
return CardFragment.newInstance(position);
}
@Override public int getItemCount() {
return CARD_ITEM_SIZE;
}
}
And on the mainActivity you need to have something inline with the following:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
viewPager = findViewById(R.id.view_pager);
tabLayout = findViewById(R.id.tabs);
viewPager.setAdapter(new ViewPagerAdapter(this));
new TabLayoutMediator(tabLayout, viewPager,
new TabLayoutMediator.TabConfigurationStrategy() {
@Override public void onConfigureTab(@NonNull TabLayout.Tab tab, int position) {
tab.setText("Tab " + (position + 1));
}
}).attach();
}
}

- 1,714
- 1
- 13
- 23
it is very simple:
java code:
tabLayout=findViewById(R.id.tabLayout);
viewPager=findViewById(R.id.viewPager);
viewPager.setAdapter(new ViewPagerAdapter(this));
new TabLayoutMediator(tabLayout, viewPager, new TabLayoutMediator.TabConfigurationStrategy() {
@Override
public void onConfigureTab(@NonNull TabLayout.Tab tab, int position) {
if (position==0){
tab.setText(R.string.photos);
tab.view.setBackground(getResources().getDrawable(R.drawable.ic_rectangle_1345));
}
else {
tab.setText(R.string.videos);
}
}
}).attach();
tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
tab.view.setBackground(getResources().getDrawable(R.drawable.ic_rectangle_1345));
}
@Override
public void onTabUnselected(TabLayout.Tab tab) {
tab.view.setBackgroundColor(Color.TRANSPARENT);
}
@Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
adapter:
public class ViewPagerAdapter extends FragmentStateAdapter {
public ViewPagerAdapter(@NonNull FragmentActivity fragmentActivity) {
super(fragmentActivity);
}
@NonNull
@Override
public Fragment createFragment(int position) {
if (position==0) {
return new PhotosFragment();
}
else {
return new VideosFragment();
}
}
@Override
public int getItemCount() {
return 2;
}}
XML:
<com.google.android.material.tabs.TabLayout
android:id="@+id/tabLayout"
android:layout_width="match_parent"
android:layout_height="60dp"
android:background="@color/tool_bar_bg"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/collection_bar" />
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/viewPager"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tabLayout" />

- 71
- 1
- 4
If your tab title comes from string.xml
.
You can put the fragment
with title
together in a List
then set title by TabLayoutMediator
. It helps you easily to reorder, delete or add new fragment
class MyFragment : Fragment() {
override fun onCreateView(...): View? {
...
TabLayoutMediator(tabLayout, viewPager) { tab, position ->
tab.text = pagerAdapter.getTabTitle(position)
}.attach()
}
private inner class PagerAdapter(fa: FragmentActivity) : FragmentStateAdapter(fa) {
val pages = listOf(
Pair(HomeFragment.newInstance(), R.string.home),
Pair(GraphFragment.newInstance(), R.string.graph),
Pair(SettingFragment.newInstance(), R.string.setting),
)
override fun createFragment(position: Int): Fragment {
return pages[position].first
}
override fun getItemCount(): Int {
return pages.count()
}
fun getTabTitle(position: Int): String {
return getString(pages[position].second)
}
}
}

- 57,942
- 23
- 262
- 279
You layouts are ready, fragments are ready and Adapters are ready. All you need now is to setup an event listener to
tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener(){
@Override
public void onTabSelected(TabLayout.Tab tab) {
viewPager.setCurrentItem(tab.getPosition());
}
@Override
public void onTabUnselected(TabLayout.Tab tab) {
}
@Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
This should bind the Tab layout to your ViewPager2.

- 11
- 3
Im running mine on the implementation 'com.google.android.material:material:1.2.1' and didn't use the tabLayoutMediator either. For starters the https://developer.android.com/jetpack/androidx/migrate/class-mappings have changed for the TabLayout in androidX so be sure to be using com.google.android.material.tabs.TabLayout in your import statement. Heres the rest of my implementation of the solution: The Xml layout declaration of the viewPager and the TabLayout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:background="@color/tan_background"
android:orientation="vertical">
<com.google.android.material.tabs.TabLayout
android:id="@+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/viewpager"
app:layout_anchor="@id/tabs"
app:layout_anchorGravity="bottom"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
and the activity file
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Set the content of the activity to use the activity_main.xml layout file
setContentView(layout.activity_main);
// Find the view pager that will allow the user to swipe between fragments
ViewPager viewPager = (ViewPager) findViewById(R.id.viewpager);
// Create an adapter that knows which fragment should be shown on each page
SimpleFragmentPagerAdapter adapter = new SimpleFragmentPagerAdapter(this,getSupportFragmentManager());
// Set the adapter onto the view pager
viewPager.setAdapter(adapter);
// Find the tab layout that shows the tabs
TabLayout tabLayout = findViewById(R.id.tabs);
// Connect the tab layout with the view pager. This will
// 1. Update the tab layout when the view pager is swiped
// 2. Update the view pager when a tab is selected
// 3. Set the tab layout's tab names with the view pager's adapter's titles
// by calling onPageTitle()
tabLayout.setupWithViewPager(viewPager);
}
}
I used a fragment adapter setup in a different class as well where I passed the context to the constructor for the different Tabs

- 1
Make sure you use TabLayoutMediator after your set adapter to view_pager2
TabLayoutMediator(tab_layout, view_pager2) { tab, position ->
tab.text = fragmentList[position].second // here u can modify you text..
}.attach()

- 961
- 9
- 13
You can take inspiration from my sample project to create UIs with Viewpager2. I use TabLayoutMediator
on all examples, Simple and very useful.
https://github.com/gabriel-TheCode/OnboardingViewPagerExamples.

- 163
- 2
- 8