Search code examples
androidkotlinandroid-fragmentsandroid-viewpager2

How to use ViewPager2 with tabs in Kotlin?


Actually in my app i had an activity which had a include of first fragment in it and then from that fragment i was able to press some buttons to navigate to another fragment, now i would change the activity and add a tablayout from which i will be able to navigate between the three fragments i have, but by reading the documentation i'm can't understand on how i can use the ViewPager2 to show my fragment in it by cliking on the tab.

My activity layout looks like this now:

<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"
    tools:context=".LetturaActivity">

    <com.google.android.material.appbar.AppBarLayout
        android:layout_width="match_parent"
        app:elevation="0dp"
        android:layout_height="wrap_content"
        android:theme="@style/Theme.VisualStock.AppBarOverlay">

        <androidx.appcompat.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:popupTheme="@style/Theme.VisualStock.PopupOverlay" />

        <com.google.android.material.tabs.TabLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:elevation="8dp"
            app:tabSelectedTextColor="#ffffff"
            app:tabBackground="@drawable/tab_selector"
            app:tabIndicatorGravity="top"
            app:tabIndicatorColor="#ffffff"
            app:tabMode="fixed">

            <com.google.android.material.tabs.TabItem
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/riepilogo"
                />

            <com.google.android.material.tabs.TabItem
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/testata"
                />

            <com.google.android.material.tabs.TabItem
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/corpo"
                />

        </com.google.android.material.tabs.TabLayout>

    </com.google.android.material.appbar.AppBarLayout>

    <androidx.viewpager2.widget.ViewPager2
        android:id="@+id/pager"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />


    <com.google.android.material.floatingactionbutton.FloatingActionButton
        android:id="@+id/floatingActionButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="16dp"
        android:clickable="true"
        android:contentDescription="@string/menu_per_lo_scarico_nuovo_documento_o_riepilogo_articoli"
        android:focusable="true"
        app:fabSize="normal"
        app:layout_anchor="@+id/pager"
        app:layout_anchorGravity="end|bottom"
        app:srcCompat="@drawable/ic_add"
        app:tint="@android:color/white" />

</androidx.coordinatorlayout.widget.CoordinatorLayout>

And then i have three fragment files like this:

class LetturaFragment : Fragment() {
...
      override fun onCreateView(
            inflater: LayoutInflater, container: ViewGroup?,
            savedInstanceState: Bundle?
    ): View? {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_lettura, container, false)
    }
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
...
     }
 }

class ArticoliFragment : Fragment() {
    override fun onCreateView(
            inflater: LayoutInflater, container: ViewGroup?,
            savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.fragment_articoli, container, false)
    }
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
...
}
}

and the activity

class LetturaActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_lettura)
}

How can i use my fragments to navigate in the tab and show them in ViewPager2?


Solution

  • The same thing which you are asking i apply in my project its also work for you

    <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:id="@+id/root_layout_home_fragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    
    
    <com.google.android.material.tabs.TabLayout
        android:id="@+id/home_fragment_tabs"
        android:layout_width="match_parent"
        android:layout_height="?android:attr/actionBarSize"
        android:background="@drawable/gradianttoolbarbottom"
        app:itemTextColor="@drawable/custom_menue_bar_color"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
    
        app:layout_constraintTop_toBottomOf="@+id/constraintLayout3"
        app:tabGravity="fill"
        app:tabIndicatorColor="@color/Orange"
        app:tabMode="scrollable"
        app:tabSelectedTextColor="@color/white"
        app:tabTextColor="@color/gray_400_dark" />
    
    <androidx.viewpager2.widget.ViewPager2
        android:id="@+id/home_fragment_viewPager"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:animateLayoutChanges="true"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/home_fragment_tabs" />
    
     </androidx.constraintlayout.widget.ConstraintLayout>
    

    this is Kotlin class

     class Home_Fragment : Fragment() {
    private lateinit var homeViewModel: HomeFragmentViewModel
    private var myContext: FragmentActivity? = null
    
    
    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        homeViewModel = ViewModelProvider(this).get(HomeFragmentViewModel::class.java)
        val root = inflater.inflate(R.layout.fragment_home, container, false)
        myContext=activity
        val viewpagger: ViewPager2 =root.findViewById<ViewPager2>(R.id.home_fragment_viewPager)
        viewpagger.isSaveEnabled=false
        val tabs: TabLayout = root.findViewById<TabLayout>(R.id.home_fragment_tabs)
        val adapter =MyViewPagerAdapter(childFragmentManager,lifecycle)
        adapter.addFragment(Fragment1(), getString(R.string.text_Fragment1))
        adapter.addFragment(Fragment2(), getString(R.string.text_Fragment2))
        adapter.addFragment(Fragment3(), getString(R.string.text_Fragment3))
        adapter.addFragment(Fragment4(),getString(R.string.text_Fragment4))
        adapter.addFragment(Fragment5(), getString(R.string.text_Fragment5))
        adapter.notifyDataSetChanged()
        viewpagger.adapter =adapter
          TabLayoutMediator(tabs, viewpagger) { tab, position ->
            tab.text = adapter.getPageTitle(position)
            viewpagger.setCurrentItem(tab.position, true)
        }.attach()
        return root
      }
    
       class MyViewPagerAdapter(manager: FragmentManager, lifecycle: Lifecycle) :  FragmentStateAdapter(manager,lifecycle ){
        private val fragmentList : MutableList<Fragment> =ArrayList()
        private val titleList : MutableList<String> =ArrayList()
        override fun getItemCount(): Int {
            return fragmentList.size
        }
    
        override fun createFragment(position: Int): Fragment {
            return  fragmentList[position]
        }
    
    
        fun addFragment(fragment: Fragment, title: String){
            fragmentList.add(fragment)
            titleList.add(title)
        }
    
        fun getPageTitle(position: Int): CharSequence? {
            return titleList[position]
        }
      }
     }