Mehedi Hassan Piash [Sr. Software Engineer]

January 22, 2021

ViewPager2 with recyclerView adapter

January 22, 2021 Posted by Piash No comments

It was a nightmare working with viewPager when had to handle fragmentPagerAdapter. But in terms of viewPager2 its just fun. Cause we can easily use recyclerview adapter in ViewPager2. I have just done a demo project with custom indicator for viewPager2 with recyclerView Adapter. Let’s start coding step by step.

Image for post
  1. activity_main.xml
<?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">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">

<androidx.viewpager2.widget.ViewPager2
android:id="@+id/view_Pager"
android:layout_width="match_parent"
android:layout_height="250dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<com.google.android.material.tabs.TabLayout
android:id="@+id/into_tab_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="200dp"
app:layout_constraintTop_toTopOf="@+id/view_Pager"
app:tabBackground="@drawable/pager_indicator"
android:background="@android:color/transparent"
app:tabGravity="center"
app:tabIndicatorHeight="0dp"
app:tabPaddingEnd="6dp"
app:tabPaddingStart="6dp" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

2. MainActivity.kt

package com.piashcse.experiment.viewpager2withrvadapter

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.databinding.DataBindingUtil
import com.google.android.material.tabs.TabLayoutMediator
import com.piashcse.experiment.viewpager2withrvadapter.adapter.ImageSliderAdapter
import com.piashcse.experiment.viewpager2withrvadapter.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {
private lateinit var bind: ActivityMainBinding
private lateinit var imageSliderAdapter: ImageSliderAdapter

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
bind = DataBindingUtil.setContentView(this, R.layout.activity_main)
viewPager2()
}

private fun viewPager2() {
imageSliderAdapter = ImageSliderAdapter()
bind.viewPager.adapter = imageSliderAdapter
TabLayoutMediator(bind.intoTabLayout, bind.viewPager)
{ tab, position ->
}
.attach()
imageSliderAdapter.addItem(
listOf(
"https://cdn.pixabay.com/photo/2021/01/09/02/13/manhattan-5901178_960_720.jpg",
"https://cdn.pixabay.com/photo/2020/11/22/20/45/venice-5767937_960_720.jpg",
"https://cdn.pixabay.com/photo/2021/01/10/12/00/road-5904909_640.jpg"
)
)
}
}

3. ImageSliderAdapter.kt

package com.piashcse.experiment.viewpager2withrvadapter.adapter

import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.piashcse.experiment.viewpager2withrvadapter.databinding.ImageSliderItemLayoutBinding

class ImageSliderAdapter: RecyclerView.Adapter<ImageSliderAdapter.ImageViewHolder>() {
private var items = ArrayList<String>()
private var onItemClick: ((String) -> Unit)? = null

fun addItem(newItems: List<String>?) {
newItems?.let {
items.addAll(newItems)
notifyDataSetChanged()
}
}

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ImageViewHolder {
val inflater = LayoutInflater.from(parent.context)
val binding = ImageSliderItemLayoutBinding.inflate(inflater, parent, false)
return ImageViewHolder(binding)
}

override fun getItemCount() = items.size

override fun onBindViewHolder(holder: ImageViewHolder, position: Int) {
val image = items[position]
return holder.bind(image)
}

inner class ImageViewHolder(private val bind: ImageSliderItemLayoutBinding) : RecyclerView.ViewHolder(bind.root) {
fun bind(item: String) {
bind.item = item
bind.executePendingBindings()
itemView.setOnClickListener {
onItemClick?.invoke(item)
}
}
}
}

4. image_slider_item_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="item"
type="java.lang.String" />
</data>
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.appcompat.widget.AppCompatImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
loadSliderImage='@{item}'/>

</androidx.appcompat.widget.LinearLayoutCompat>
</layout>

5. default_indicator_dot.xml

<?xml version="1.0" encoding="utf-8"?>
<layer-list
xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape
android:innerRadius="0dp"
android:shape="ring"
android:thickness="3dp"
android:useLevel="false">
<solid android:color="@color/material_white"/>
</shape>
</item>
</layer-list>

6. selected_indicator_dot.xml

<?xml version="1.0" encoding="utf-8"?>
<layer-list
xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape
android:innerRadius="0dp"
android:shape="ring"
android:thickness="3dp"
android:useLevel="false">
<solid android:color="@color/material_amber900"/>
</shape>
</item>
</layer-list>

7. pager_indicator.xml

<?xml version="1.0" encoding="utf-8"?>
<selector
xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/selected_indicator_dot"
android:state_selected="true"/>
<item android:drawable="@drawable/default_indicator_dot"/>
</selector>

Github:https://github.com/piashcse/blog_piashcse_code/tree/master/ViewPager2WithRvAdapter
Medium:https://piashcse.medium.com/viewpager2-with-recyclerview-adapter-b048f625a208