Setup ViewPager2 for Android (Kotlin)

Jun 18, 2019

Depedencies

dependencies {
    // https://mvnrepository.com/artifact/androidx.viewpager2/viewpager2
    implementation 'androidx.viewpager2:viewpager2:1.0.0-alpha05'
}

Layout

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        >

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

</androidx.constraintlayout.widget.ConstraintLayout>

Activity + ViewModel

  • Support Horizontal/Vertical Scrolling: viewPager.orientation = ViewPager2.ORIENTATION_HORIZONTAL
  • Observe page changed: viewPager.registerOnPageChangeCallback
  • Scroll to page programatically: viewPager.currentItem = PAGE or viewPager.setCurrentItem(position, true) (with Animation)
  • Disable user scroll: viewPager.isUserInputEnabled = false
class TestViewPagerActivity : AppCompatActivity() {    companion object {        @JvmStatic        fun newInstance(context: Context) =            Intent(context, TestViewPagerActivity::class.java).apply {            }    }    override fun onCreate(savedInstanceState: Bundle?) {        super.onCreate(savedInstanceState)        setContentView(R.layout.test_viewpager)        init()    }    private fun init() {        val viewModel = ViewModelProviders.of(this).get(TestViewPageViewModel::class.java)        val adapter = LocalAdapter(viewModel)        val items = listOf(            Item("Title 1", "Content 1"),            Item("Title 2", "Content 2"),            Item("Title 3", "Content 3")        )        adapter.replaceItems(items)        viewPager.orientation = ViewPager2.ORIENTATION_HORIZONTAL        viewPager.adapter = adapter        // disable scrolling        // viewPager.isUserInputEnabled = false        // viewPager.currentItem = 1        viewPager.registerOnPageChangeCallback(object: ViewPager2.OnPageChangeCallback() {            override fun onPageSelected(position: Int) {                super.onPageSelected(position)                Timber.d("page=$position")            }        })        viewModel.nextPageEvent.observe(this, Observer { position ->            viewPager.setCurrentItem(position, true)        })    }    class Item(val title: String, val content: String)    class LocalAdapter(val viewModel: TestViewPageViewModel) : RecyclerView.Adapter<LocalAdapter.ViewHolder>() {        private var items = listOf<Item>()        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): LocalAdapter.ViewHolder {            val view = LayoutInflater.from(parent.context)                .inflate(R.layout.test_viewpage_item, parent, false)            return ViewHolder(view)        }        override fun getItemCount(): Int = items.size        override fun onBindViewHolder(holder: LocalAdapter.ViewHolder, position: Int) {            val item = items[position]            holder.titleTextView.text  = item.title            holder.contentTextView.text = item.content            if (position < itemCount - 1) {                holder.nextButton.isEnabled = true                holder.nextButton.setOnClickListener {                    // next                    viewModel.nextPageEvent.value = position + 1                }            }            else {                holder.nextButton.isEnabled = false            }        }        fun replaceItems(items: List<Item>) {            this.items = items            notifyDataSetChanged()        }        inner class ViewHolder(override val containerView: View) : RecyclerView.ViewHolder(containerView), LayoutContainer    }}

test_viewpage_item layout

<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        app:cardUseCompatPadding="true"
        app:cardCornerRadius="12dp"
        android:layout_margin="8dp">

    <LinearLayout android:layout_width="wrap_content"
                  android:layout_height="wrap_content"
                  android:layout_gravity="center"
                  android:orientation="vertical"
                  android:padding="8dp">

        <TextView
                android:id="@+id/titleTextView"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:textAppearance="@style/TextAppearance.AppCompat.Large"
                android:textAlignment="center"
                tools:text="Title"
        />

        <TextView
                android:id="@+id/contentTextView"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:textAlignment="center"
                tools:text="Content"
        />

        <Button
                android:id="@+id/nextButton"
                android:text="Next"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"/>


    </LinearLayout>
</androidx.cardview.widget.CardView>
class TestViewPageViewModel: ViewModel() {    internal val nextPageEvent = SingleLiveEvent<Int>()}

NOTE: Source for SingleLiveEvent.

References:

❤️ Is this article helpful?

Buy me a coffee ☕ or support my work via PayPal to keep this space 🖖 and ad-free.

Do send some 💖 to @d_luaz or share this article.

✨ By Desmond Lua

A dream boy who enjoys making apps, travelling and making youtube videos. Follow me on @d_luaz

👶 Apps I built

Travelopy - discover travel places in Malaysia, Singapore, Taiwan, Japan.