Android Viewpager2 with Kotlin Example
In this article, We are going to learn how to implement android viewpager2 in our android apps and how to use android viewpager2 with recyclerview using kotlin example.
ViewPager2 is an improved version of ViewPager. It comes with important new features and performance improvements. ViewPager is normally used to showcase important app features one at a time and to use swipeable tabs in android apps. You can also checkout sample app at HERE.
Difference between ViewPager2 & ViewPager
- In ViewPager2, We can use RecyclerView to add items dynamically which is not possible in old ViewPager.
- In old ViewPager, Vertical swiping is not possible. We can only use horizontal swipe. But in ViewPager2, We can use both orientations for swiping.
- Right-to-left layout support for app locale is not provided in old viewpager. But in ViewPager2, this feature is enabled.
- We can use animations for swipeable pages when they are switching because ViewPager2 supports page transformations.
We will create swipeable tabs using ViewPager2 in this example. We also use databinding to bind data in xml layouts. I already explained how to use databinding in android apps in my previous article How to use Data Binding Library for RecyclerView using Kotlin in Android.
Add below dependency in your app level build.gradle
Add ViewPager2 in xml layout
You can also change orientation of swipeable pages. If you want to swipe pages vertically, then you need to add android:orientation=”vertical” in viewpager2 view in xml layout.
<?xml version="1.0" encoding="utf-8"?> <layout 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"> <data> </data> <androidx.constraintlayout.widget.ConstraintLayout android:layout_width="match_parent" android:layout_height="match_parent"> <androidx.viewpager2.widget.ViewPager2 android:id="@+id/view_pager_main" android:layout_width="0dp" android:layout_height="0dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout> </layout>
Create POJO Class to pass data
package com.example.viewpager2sample data class Club(var logo:Int, var name:String, var desc:String, var color:Int) {}
Create Swipeable Page layout
package com.example.viewpager2sample import android.content.Context import android.widget.ImageView import androidx.constraintlayout.widget.ConstraintLayout import androidx.core.content.ContextCompat import androidx.databinding.BindingAdapter object Utils { @BindingAdapter("setBackgroundColor") @JvmStatic fun ConstraintLayout.setBgColor(color:Int){ setBackgroundColor(ContextCompat.getColor(this.context,color)) } @BindingAdapter("setImage") @JvmStatic fun ImageView.setLogo(resource:Int){ setImageResource(resource) } }
Create RecyclerView Adapter for ViewPager2
We need to create recyclerview adapter for swipeable tabs like we use for horizontal recyclerview.
<?xml version="1.0" encoding="utf-8"?> <layout 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"> <data> <variable name="club" type="com.example.viewpager2sample.Club" /> </data> <androidx.constraintlayout.widget.ConstraintLayout android:id="@+id/container" android:layout_width="match_parent" android:layout_height="match_parent" app:setBackgroundColor="@{club.color}"> <TextView android:id="@+id/txt_title_row" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="100dp" android:gravity="center_horizontal" android:textColor="#FFFFFF" android:textSize="30sp" android:textStyle="bold" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" android:text="@{club.name}" /> <ImageView android:id="@+id/img_logo_item" android:layout_width="200dp" android:layout_height="200dp" android:layout_marginTop="40dp" app:setImage="@{club.logo}" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/txt_title_row"/> <TextView android:id="@+id/txt_desc_row" android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="8dp" android:gravity="center_horizontal" android:layout_marginTop="40dp" android:text="@{club.desc}" android:textColor="#FFFFFF" android:textSize="22sp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/img_logo_item" /> </androidx.constraintlayout.widget.ConstraintLayout> </layout>
package com.example.viewpager2sample import android.content.Context import android.view.LayoutInflater import android.view.ViewGroup import androidx.databinding.DataBindingUtil import androidx.recyclerview.widget.RecyclerView import com.example.viewpager2sample.databinding.ClubRowBinding class ClubsAdapter(private var ctx: Context?, private var listClubs: MutableList<Club>?) : RecyclerView.Adapter<ClubsAdapter.MyViewHolder>() { class MyViewHolder(val itemBinding: ClubRowBinding) : RecyclerView.ViewHolder(itemBinding.root){ private var binding : ClubRowBinding? = null init { this.binding = itemBinding } } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder { val inflater = LayoutInflater.from(ctx) val binding: ClubRowBinding = DataBindingUtil.inflate(inflater, R.layout.club_row,parent,false) return MyViewHolder(binding) } override fun getItemCount(): Int { listClubs?.let { return it.size } return 0 } override fun onBindViewHolder(holder: MyViewHolder, position: Int) { holder.itemBinding.club = listClubs?.get(position) } }
Integrate Adapter to ViewPager2
package com.example.viewpager2sample import android.app.Activity import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import androidx.databinding.DataBindingUtil import com.example.viewpager2sample.databinding.ActivityMainBinding class MainActivity : Activity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val binding: ActivityMainBinding = DataBindingUtil.setContentView(this@MainActivity, R.layout.activity_main) val listClubs = mutableListOf<Club>() listClubs.add(Club(R.drawable.premier_league,"Premier League","English Premier League or EPL",android.R.color.holo_purple)) listClubs.add(Club(R.drawable.laliga,"La Liga","The Campeonato Nacional de Liga de Primera División",android.R.color.holo_orange_dark)) listClubs.add(Club(R.drawable.bundesliga,"Bundesliga","Federal League",android.R.color.holo_red_dark)) listClubs.add(Club(R.drawable.serie_a,"Serie A","Lega Nazionale Professionisti Serie A",android.R.color.holo_blue_dark)) listClubs.add(Club(R.drawable.ligue_one,"Ligue 1","Ligue 1 Conforama",android.R.color.holo_orange_light)) val adapter = ClubsAdapter(this@MainActivity, listClubs) binding.viewPagerMain.adapter = adapter } }