How to Create an Onboarding Screen in Android with ViewPager2 ?
Here is the demo of the onboarding screen which we are going to create in this article.
We are going to learn that how we can add Onboarding Screen to our android application in the android studio so that we can provide a better user experience to the user of the application.
What is Onboarding Screen?
- The onboarding screen can be understood as a virtual unboxing of an application.
- Users go through a series of screens which finally directs users to the application interface.
Goals or purposes of Onboarding screen:
- Welcomes user and excite them about application ahead.
- Tell the features or functions of the application.
- Allow users to register or log in.
- Collect information about the interests of the user(for example – when we open the Google application for the first time it asks the user to select singers which he/she likes).
..
Let us start Onboarding Screens with ViewPager2 Android:
ViewPager2 is an improved version of the ViewPager library that offers enhanced functionality and addresses common difficulties when using ViewPager.
..
First onboarding screen
Now create a new activity for first onboarding screen.
And design for the first onboarding screen
<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.LinearLayoutCompat xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerHorizontal="true"
android:gravity="center_horizontal"
android:orientation="vertical">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/intro_image"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="20dp"
android:layout_weight="1"
android:padding="35dp"
tools:srcCompat="@tools:sample/backgrounds/scenic" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/intro_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:textColor="@android:color/black"
android:textStyle="bold"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
tools:text="@tools:sample/lorem" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/intro_description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="20dp"
android:textAlignment="center"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
tools:text="@tools:sample/lorem/random"
android:maxLines="3"
android:ellipsize="end" />
</androidx.appcompat.widget.LinearLayoutCompat>
..
Now create another xml to create an item container layout for the onboarding screen
<?xml version="1.0" encoding="utf-8"?>
<!--Add ViewPage2, TabLayout & 2 MaterialButton to your layout.-->
<androidx.appcompat.widget.LinearLayoutCompat xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:background="@android:color/white"
android:fitsSystemWindows="true"
android:id="@+id/dialogInfo"
android:orientation="vertical">
<!--ViewPager2-->
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/viewPager2"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<!--indicator-->
<com.google.android.material.tabs.TabLayout
android:id="@+id/tabLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:background="@color/white"
app:tabBackground="@drawable/intro_tab_selector"
app:tabGravity="center"
app:tabIndicatorHeight="0dp" />
<!--Next-->
<com.google.android.material.button.MaterialButton
android:id="@+id/btnNext"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:text="@string/intro_next"
android:textAllCaps="true"
android:backgroundTint="#356DF1"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
android:textColor="@android:color/white"
android:textStyle="bold"
app:cornerRadius="30dp" />
<!--SKIP-->
<com.google.android.material.button.MaterialButton
android:id="@+id/btnSkip"
android:layout_gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:text="@string/intro_skip"
app:cornerRadius="30dp"
android:textAllCaps="true"
style="@style/Widget.MaterialComponents.Button.TextButton"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
android:textColor="@android:color/darker_gray"
android:textStyle="bold" />
</androidx.appcompat.widget.LinearLayoutCompat>
..
Next, add the functionality (in the fragment)
package com.boltuix.androidpreferences
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.RecyclerView
import androidx.viewpager2.widget.ViewPager2
import com.boltuix.androidpreferences.AppIntro.Companion.MAX_STEP
import com.boltuix.androidpreferences.databinding.IntroAppContentBinding
import com.boltuix.androidpreferences.databinding.IntroAppDesignBinding
import com.google.android.material.tabs.TabLayoutMediator
class AppIntro : Fragment() {
private var _binding: IntroAppContentBinding? = null
// This property is only valid between onCreateView and
// onDestroyView.
private val binding get() = _binding!!
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
// Inflate the layout for this fragment
//return inflater.inflate(R.layout.intro_app_content, container, false)
_binding = IntroAppContentBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
//............................................................
binding.viewPager2.adapter = AppIntroViewPager2Adapter()
//............................................................
TabLayoutMediator(binding.tabLayout, binding.viewPager2) { tab, position ->
}.attach()
//............................................................
binding.viewPager2.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
override fun onPageSelected(position: Int) {
super.onPageSelected(position)
if(position== MAX_STEP -1){
binding.btnNext.text = getString(R.string.intro_get_started)//"Get Started"
binding.btnNext.contentDescription = getString(R.string.intro_get_started)//"Get Started"
}else{
binding.btnNext.text = getString(R.string.intro_next)//"Next"
binding.btnNext.contentDescription = getString(R.string.intro_next)//"Next"
}
}
})
//............................................................
binding.btnSkip.setOnClickListener {
findNavController().navigateUp()
}
//............................................................
binding.btnNext.setOnClickListener {
if(binding.btnNext.text.toString()==getString(R.string.intro_get_started)){
findNavController().navigateUp()
}
else{
// to change current page - on click "Next BUTTON"
val current = (binding.viewPager2.currentItem) + 1
binding.viewPager2.currentItem = current
// to update button text
if(current>= MAX_STEP -1){
binding.btnNext.text = getString(R.string.intro_get_started)//"Get Started"
binding.btnNext.contentDescription = getString(R.string.intro_get_started)//"Get Started"
}else{
binding.btnNext.text = getString(R.string.intro_next)//"Next"
binding.btnNext.contentDescription = getString(R.string.intro_next)//"Next"
}
}
}
}
companion object {
const val MAX_STEP = 3
}
}
//...............................................................................
//................................................................................
class AppIntroViewPager2Adapter : RecyclerView.Adapter<PagerVH2>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PagerVH2 {
return PagerVH2(
IntroAppDesignBinding.inflate(LayoutInflater.from(parent.context), parent, false)
)
}
//get the size of color array
override fun getItemCount(): Int = MAX_STEP // Int.MAX_VALUE
//binding the screen with view
override fun onBindViewHolder(holder: PagerVH2, position: Int) = holder.itemView.run {
with(holder) {
if (position == 0) {
bindingDesign.introTitle.text = context.getString(R.string.intro_title_1)
bindingDesign.introDescription.text = context.getString(R.string.intro_description_1)
bindingDesign.introImage.setImageResource(R.drawable.intro_ic_a_day_at_the_park)
}
if (position == 1) {
bindingDesign.introTitle.text = context.getString(R.string.intro_title_2)
bindingDesign.introDescription.text = context.getString(R.string.intro_description_2)
bindingDesign.introImage.setImageResource(R.drawable.intro_ic_directions)
}
if (position == 2) {
bindingDesign.introTitle.text = context.getString(R.string.intro_title_3)
bindingDesign.introDescription.text = context.getString(R.string.intro_description_3)
bindingDesign.introImage.setImageResource(R.drawable.intro_ic_hang_out)
}
}
}
}
class PagerVH2(val bindingDesign: IntroAppDesignBinding) : RecyclerView.ViewHolder(bindingDesign.root)
..
GET source code on Github:
..
Comments
Post a Comment