How to use TabLayout with ViewPager2 in Android

前端 未结 7 1737
春和景丽
春和景丽 2020-12-29 18:24

I want to use com.google.android.material.tabs.TabLayout component with Android\'s new ViewPager implementation androidx.viewpager2.widget.Vi

相关标签:
7条回答
  • 2020-12-29 18:54

    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)
            }
        }
    }
    
    0 讨论(0)
  • 2020-12-29 18:58

    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"))
    
    0 讨论(0)
  • 2020-12-29 19:02

    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

    0 讨论(0)
  • 2020-12-29 19:07

    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()
    
    0 讨论(0)
  • 2020-12-29 19:11

    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

    0 讨论(0)
  • 2020-12-29 19:11

    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 the tabLayout if notifyDataSetChanged is called to the viewpager adapter.

    Use the contents of TabLayoutMediator.java

    0 讨论(0)
提交回复
热议问题