ViewPager2 With Fragment and FragmentStateAdapter

This tutorial is 2nd part of our tutorial on ViewPager2 using Kotlin. Here, we will learn how to use ViewPager2 with Fragment, how to set FragmentStateAdapter adapter in ViewPager2 using Kotlin.

Output

Let’s have a quick demo of things we want to cover in this tutorial –
Tutorialwing Android Kotlin Using ViewPager2 With Fragment example

Getting Started

We can define android ViewPager2 widget as below –

ViewPager2 is advanced version of androidx.viewpager2.widget.ViewPager2 that supports right-to-left layout support, vertical orientation, modifiable Fragment collections etc.

Now, how do we use ViewPager2 in android application ?

Creating New Project

At first, we will create an application.
So, follow steps below to create any android project in Kotlin –

Step Description
1. Open Android Studio (Ignore if already done).
2. Go to File => New => New Project. This will open a new window. Then, under Phone and Tablet section, select Empty Activity. Then, click Next.
3. In next screen, select project name as ViewPagerWithFragment. Then, fill other required details.
4. Then, clicking on Finish button creates new project.

Newbie in Android ?

Some very important concepts (Recommended to learn before you move ahead)

Before we move ahead, we need to setup for viewBinding to access Android ViewPager2 Using Kotlin file without using findViewById() method.

Setup ViewBinding

Add viewBinding true in app/build.gradle file.

 
 android { 
 	// OTHER CODE... 
 	buildFeatures { 
 		viewBinding true 
 	} 
 } 
 

Now, set content in activity using view binding.
Open MainActivity.kt file and write below code in it.

 
 class MainActivity : AppCompatActivity() { 
 	
 	private lateinit var binding: ActivityMainBinding 
 	
 	override fun onCreate(savedInstanceState: Bundle?) { 
 		super.onCreate(savedInstanceState) 
 		binding = ActivityMainBinding.inflate(layoutInflater) 
 		val view = binding.root 
 		setContentView(view) 
 	} 
 } 
 

Now, we can access view in Kotlin file without using findViewById() method.

Using ViewPager2 in Kotlin

Follow steps below to use ViewPager2 in newly created project –

  • We are using an image, tw_logo.png, in our application. So, download this image and save it in res/drawable folder.
    Tutorialwing Logo
  • Open res/values/strings.xml file. Then, add below code into it.
    <resources>
        <string name="app_name">ViewPagerWithFragment</string>
    </resources>
    
  • Now, we need to create ui for single view inside viewPager2. So, create a new file, item_holder.xml, in res/layout folder. Then, add below code into it –

    <?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"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <ImageView
            android:id="@+id/labelHeader"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginBottom="20dp"
            android:contentDescription="@string/app_name"
            android:src="@drawable/tw_logo"
            app:layout_constraintBottom_toTopOf="@+id/label"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent" />
    
        <TextView
            android:id="@+id/label"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="20sp"
            android:textStyle="bold"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
    
    </androidx.constraintlayout.widget.ConstraintLayout>
    
  • Now, we need to create a fragment for each view in viewPager2. So, create a new file, ItemFragment.kt, in com.tutorialwing.viewpagerwithfragment package. Then, add below code into it –

    package com.tutorialwing.viewpagerwithfragment
    
    import android.graphics.Color
    import android.os.Bundle
    import android.view.LayoutInflater
    import android.view.View
    import android.view.ViewGroup
    import androidx.fragment.app.Fragment
    import com.tutorialwing.viewpagerwithfragment.databinding.ItemHolderBinding
    
    class ItemFragment : Fragment() {
    
    	private lateinit var binding: ItemHolderBinding
    
    	override fun onCreateView(
    		inflater: LayoutInflater,
    		container: ViewGroup?,
    		savedInstanceState: Bundle?
    	): View {
    		binding = ItemHolderBinding.inflate(layoutInflater)
    		return binding.root
    	}
    
    	override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    		super.onViewCreated(view, savedInstanceState)
    
    		setupData()
    	}
    
    	private fun setupData() {
    		binding.label.text = getString(R.string.app_name)
    
    		val color = arguments?.getString("color")
    		binding.root.setBackgroundColor(Color.parseColor(color))
    
    		val position = arguments?.getString("label")
    		binding.label.text = position
    	}
    }
    
  • Now, we need to create an adapter, ViewPagerAdapter.kt, in com.tutorialwing.viewpagerwithfragment package. Then, add below code into it –

    package com.tutorialwing.viewpagerwithfragment
    
    import androidx.fragment.app.Fragment
    import androidx.fragment.app.FragmentActivity
    import androidx.viewpager2.adapter.FragmentStateAdapter
    import android.os.Bundle
    
    class ViewPagerAdapter(fragmentActivity: FragmentActivity, var colorList: ArrayList<String>) :
    	FragmentStateAdapter(fragmentActivity) {
    
    	override fun getItemCount(): Int {
    		return colorList.size
    	}
    
    	override fun createFragment(position: Int): Fragment {
    		val fragment = ItemFragment()
    		val args = Bundle()
    		args.putString("color", colorList[position])
    		args.putString("label", "Fragment Number: ${position + 1}")
    		fragment.arguments = args
    		return fragment
    	}
    }
    
  • Open res/layout/activity_main.xml file. Then, add below code in it –
    <?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.viewpager2.widget.ViewPager2
            android:id="@+id/viewPager"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
    
    </androidx.constraintlayout.widget.ConstraintLayout>
    
  • Now, create a new file, ZoomOutPageTransformer.kt, in com.tutorialwing.viewpagerwithfragment package. Then, add below code in it –

    package com.tutorialwing.viewpagerwithfragment
    
    import android.view.View
    import androidx.viewpager2.widget.ViewPager2
    
    private const val MIN_SCALE = 0.85f
    private const val MIN_ALPHA = 0.5f
    
    class ZoomOutPageTransformer : ViewPager2.PageTransformer {
    
    	override fun transformPage(view: View, position: Float) {
    		view.apply {
    			val pageWidth = width
    			val pageHeight = height
    			when {
    				position < -1 -> { // [-Infinity,-1)
    					// This page is way off-screen to the left.
    					alpha = 0f
    				}
    				position <= 1 -> { // [-1,1]
    					// Modify the default slide transition to shrink the page as well
    					val scaleFactor = Math.max(MIN_SCALE, 1 - Math.abs(position))
    					val vertMargin = pageHeight * (1 - scaleFactor) / 2
    					val horzMargin = pageWidth * (1 - scaleFactor) / 2
    					translationX = if (position < 0) {
    						horzMargin - vertMargin / 2
    					} else {
    						horzMargin + vertMargin / 2
    					}
    
    					// Scale the page down (between MIN_SCALE and 1)
    					scaleX = scaleFactor
    					scaleY = scaleFactor
    
    					// Fade the page relative to its size.
    					alpha = (MIN_ALPHA +
    							(((scaleFactor - MIN_SCALE) / (1 - MIN_SCALE)) * (1 - MIN_ALPHA)))
    				}
    				else -> { // (1,+Infinity]
    					// This page is way off-screen to the right.
    					alpha = 0f
    				}
    			}
    		}
    	}
    }
    

    This class is used to set animation while we navigate from one view to another in viewPager2.

  • We can also access it in Kotlin File, MainActivity.kt, as below –

    package com.tutorialwing.viewpagerwithfragment
    
    import androidx.appcompat.app.AppCompatActivity
    import android.os.Bundle
    import com.tutorialwing.viewpagerwithfragment.databinding.ActivityMainBinding
    
    class MainActivity : AppCompatActivity() {
    
    	private lateinit var binding: ActivityMainBinding
    
    	override fun onCreate(savedInstanceState: Bundle?) {
    		super.onCreate(savedInstanceState)
    
    		binding = ActivityMainBinding.inflate(layoutInflater)
    		setContentView(binding.root)
    
    		setupViewPager2()
    	}
    
    	private fun setupViewPager2() {
    		val colorList = arrayListOf("#00ff00", "#ff0000", "#0000ff", "#f0f0f0")
    		binding.viewPager.adapter = ViewPagerAdapter(this, colorList)
    
    		binding.viewPager.setPageTransformer(ZoomOutPageTransformer())
    	}
    
            // This function handles back button press. When user press back button, previous view in viewPager2 
            // is displayed.
    	override fun onBackPressed() {
    		val viewPager = binding.viewPager
    		if (viewPager.currentItem == 0) {
    			// If the user is currently looking at the first step, allow the system to handle the
    			// Back button. This calls finish() on this activity and pops the back stack.
    			super.onBackPressed()
    		} else {
    			// Otherwise, select the previous step.
    			viewPager.currentItem = viewPager.currentItem - 1
    		}
    	}
    
    }
    

Now, run the application. We will get output as below –
Tutorialwing Android Kotlin Using ViewPager2 With Fragment example

That’s end of tutorial on viewPager2 With Fragment using Kotlin.

Leave a Reply