I want to use com.google.android.material.tabs.TabLayout component with Android\'s new ViewPager implementation androidx.viewpager2.widget.Vi
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)
}
}
}
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"))
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
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.
It's code will look like this in kotlin
TabLayoutMediator(tabLayout, viewPager) { tab, position ->
tab.text = tabTitles[position]
viewPager.setCurrentItem(tab.position, true)
}.attach()
check this Create swipe views with tabs using ViewPager2
Here is the Updated answer How to use TabLayout with ViewPager2 in Android
TabLayoutMediatorUse 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
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 )
RECREATESall the tabs of thetabLayoutifnotifyDataSetChangedis called to the viewpageradapter.
Use the contents of TabLayoutMediator.java