Implementation of ViewPager2 with Android Kotlin and Fragments: A Step-by-Step Guide

Abhishek Pathak
5 min readJul 31, 2023

ViewPager2 is a versatile component in Android that allows users to swipe horizontally between different fragments. In this implementation article, we will explore how to create a ViewPager2 with Kotlin and Fragments. By the end of this guide, you will have a fully functional ViewPager2 integrated into your Android app.

Prerequisites:

  • Basic understanding of Android development with Kotlin
  • Android Studio installed on your system
  • Familiarity with creating and managing fragments

Step 1: Create a new Android Project

  1. Open Android Studio and create a new project with an appropriate name.
  2. Choose an Empty Activity template as the project’s starting point.

Step 2: Add the ViewPager2 Dependency

  1. Open the app-level build.gradle file.
  2. In the dependencies block, add the following line to include the ViewPager2 library:
implementation "androidx.viewpager2:viewpager2:1.0.0"

3. Sync the project to download the library.

Step 3: Create Fragments

  1. Right-click on the package in the Project Explorer and select New -> Fragment -> Fragment (Blank).
  2. Repeat this step to create multiple fragments that you want to display in the ViewPager2.

Step 4: Design ViewPager2 Layout

  1. Open the activity_main.xml layout file.
  2. Replace the default layout with the following code:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

<androidx.viewpager2.widget.ViewPager2
android:id="@+id/viewPager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />

<com.google.android.material.tabs.TabLayout
android:id="@+id/tabLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
android:minHeight="?attr/actionBarSize"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" />
</LinearLayout>

Step 5: Implement the ViewPager2 Adapter

  1. Create a new Kotlin class for the ViewPager2 Adapter, e.g., ViewPagerAdapter.
  2. Implement the RecyclerView.Adapter and create a ViewHolder for the fragments.
class ViewPagerAdapter(private val fragments: List<Fragment>, fragmentManager: FragmentManager) :
FragmentStateAdapter(fragmentManager) {

override fun getItemCount(): Int = fragments.size

override fun createFragment(position: Int): Fragment = fragments[position]
}

Step 6: Initialize the ViewPager2 in MainActivity

  1. Open the MainActivity.kt file.
  2. Initialize the ViewPager2 and provide it with the adapter in the onCreate method:
import com.google.android.material.tabs.TabLayout
import com.google.android.material.tabs.TabLayoutMediator

class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)

val viewPager: ViewPager2 = findViewById(R.id.viewPager)
val fragments = listOf(FirstFragment(), SecondFragment(), ThirdFragment()) // Replace with your fragment instances
val adapter = ViewPagerAdapter(fragments, supportFragmentManager)
viewPager.adapter = adapter

val tabLayout: TabLayout = findViewById(R.id.tabLayout)
TabLayoutMediator(tabLayout, viewPager) { tab, position ->
// Set tab text or icon here if needed
tab.text = "Tab ${position + 1}"
}.attach()
}
}

Step 7: Run the App

  1. Connect your Android device or use an emulator.
  2. Run the app and verify that the ViewPager2 displays the fragments correctly.
  3. Swipe left and right to navigate between the fragments.

Congratulations! You have successfully implemented a ViewPager2 with Kotlin and Fragments. This component is a powerful tool for creating interactive and user-friendly interfaces in your Android applications. Feel free to experiment further with different fragments and layouts to suit your app’s needs. Happy coding!

How do you customize this tabs

Step 1: Create a Custom Layout for Tabs

Create a new XML layout file named custom_tab_layout.xml in the res/layout directory.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">

<ImageView
android:id="@+id/tabIcon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:src="@drawable/ic_tab_placeholder" />

<TextView
android:id="@+id/tabText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="Tab"
android:textColor="@color/tab_text_color" />
</LinearLayout>

In this layout, we have a LinearLayout containing an ImageView and a TextView. You can customize the ImageView and TextView attributes to suit your app's design.

Step 2: Update MainActivity.kt Now, we'll modify the MainActivity.kt file to use the custom layout for the tabs:

import com.google.android.material.tabs.TabLayout
import com.google.android.material.tabs.TabLayoutMediator

class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)

val viewPager: ViewPager2 = findViewById(R.id.viewPager)
val fragments = listOf(FirstFragment(), SecondFragment(), ThirdFragment()) // Replace with your fragment instances
val adapter = ViewPagerAdapter(fragments, supportFragmentManager)
viewPager.adapter = adapter

val tabLayout: TabLayout = findViewById(R.id.tabLayout)
TabLayoutMediator(tabLayout, viewPager) { tab, position ->
// Set custom tab view
val tabView = layoutInflater.inflate(R.layout.custom_tab_layout, tabLayout, false)
val tabIcon: ImageView = tabView.findViewById(R.id.tabIcon)
val tabText: TextView = tabView.findViewById(R.id.tabText)

// Set icon and text for each tab
when (position) {
0 -> {
tabIcon.setImageResource(R.drawable.ic_tab_1)
tabText.text = "Tab 1"
}
1 -> {
tabIcon.setImageResource(R.drawable.ic_tab_2)
tabText.text = "Tab 2"
}
2 -> {
tabIcon.setImageResource(R.drawable.ic_tab_3)
tabText.text = "Tab 3"
}
// Add more cases for additional tabs
else -> {
tabIcon.setImageResource(R.drawable.ic_tab_placeholder)
tabText.text = "Tab"
}
}

// Set custom view as the tab
tab.customView = tabView
}.attach()
}
}

This will set the text color of the tabs to white. Modify the color value to match your app’s design.

By following these steps, you can now have a customized TabLayout with both icons and text for each tab, making your app’s UI more visually appealing and user-friendly.

How to make swipe dots demo

To implement swipe dots like ViewPager or demo screens in your Android app, you can use the combination of ViewPager2, TabLayout, and a custom indicator. Let's go through the steps to achieve this:

Step 1: Set Up ViewPager2 and TabLayout Follow the previous steps to set up the ViewPager2 and TabLayout as explained in the earlier responses. You should have a ViewPager2 with fragments and a corresponding TabLayout with custom tabs showing icons and text.

Step 2: Create the Custom Indicator Layout

  1. Create a new XML layout file named indicator_dot.xml in the res/layout directory.
<?xml version="1.0" encoding="utf-8"?>
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/dot"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:src="@drawable/ic_dot_unselected" />

Create drawable resources ic_dot_unselected and ic_dot_selected to represent the unselected and selected dot indicators, respectively. For simplicity, you can use simple shapes or custom icons.

Step 3: Update MainActivity.kt Modify the MainActivity.kt file to set up the custom indicator:

import com.google.android.material.tabs.TabLayout
import com.google.android.material.tabs.TabLayoutMediator

class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)

val viewPager: ViewPager2 = findViewById(R.id.viewPager)
val fragments = listOf(FirstFragment(), SecondFragment(), ThirdFragment()) // Replace with your fragment instances
val adapter = ViewPagerAdapter(fragments, supportFragmentManager)
viewPager.adapter = adapter

val tabLayout: TabLayout = findViewById(R.id.tabLayout)
TabLayoutMediator(tabLayout, viewPager) { tab, position ->
// Set custom tab view (from previous response)
// ...
}.attach()

// Set up custom indicator dots
val dotsContainer: LinearLayout = findViewById(R.id.dotsContainer) // A LinearLayout to hold the dots
val dotCount = fragments.size // Number of dots equals the number of fragments
val dotViews = arrayOfNulls<ImageView>(dotCount)

for (i in 0 until dotCount) {
dotViews[i] = layoutInflater.inflate(R.layout.indicator_dot, dotsContainer, false) as ImageView
dotsContainer.addView(dotViews[i])
}

// Set a page change listener to update the indicator dots
viewPager.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
override fun onPageSelected(position: Int) {
for (i in 0 until dotCount) {
if (i == position) {
dotViews[i]?.setImageResource(R.drawable.ic_dot_selected)
} else {
dotViews[i]?.setImageResource(R.drawable.ic_dot_unselected)
}
}
}
})
}
}

In this updated code, we’ve created a custom indicator using indicator_dot.xml layout for each page in the ViewPager2. We dynamically add the dots to a LinearLayout named dotsContainer, and we use a page change listener to update the selected and unselected states of the dots based on the current page.

Step 4: Update Custom Indicator Drawables Replace ic_dot_unselected and ic_dot_selected drawables with your own custom indicator drawables.

By following these steps, you will have a ViewPager2 with a TabLayout displaying customized tabs and a custom indicator with swipe dots that change according to the selected page. This approach will create a smooth and user-friendly UI for demo screens or any other content that requires swipe-based navigation.

--

--