Onboarding screen in Android Application
How to make an Onboarding screen in an Android Application - Using Android Studio and Java

An onboarding screen is like a walkthrough to introduce what an app does to a user and how to use it. An onboarding screen needs to be designed in the most simple, welcoming, and user-friendly way possible.
The onboarding screen is important as it helps the user understand why they are using the application and how it will benefit them. This will increase user engagement with the application. Furthermore, it also increases the user experience with the application.
We will be building a basic onboarding screen in this tutorial, as shown below.

There are many libraries that help implement the onboarding screen. In this tutorial, we will be implementing a basic onboarding screen (consisting of 3 intro screens) using ViewPager and SharedPreferences.
GitHub: https://github.com/iamvs-2002/App_Intro
First of all, we design the onboarding screen.
Add the colors in colors.xml as shown below.
<!-- Screens background color-->
<color name="bg_screen1">#f64c73</color>
<color name="bg_screen2">#20d2bb</color>
<color name="bg_screen3">#3395ff</color>
<color name="bg_screen4">#c873f4</color>
<!-- dots inactive colors -->
<color name="dot_dark_screen1">#d1395c</color>
<color name="dot_dark_screen2">#14a895</color>
<color name="dot_dark_screen3">#2278d4</color>
<color name="dot_dark_screen4">#a854d4</color>
<!-- dots active colors -->
<color name="dot_light_screen1">#f98da5</color>
<color name="dot_light_screen2">#8cf9eb</color>
<color name="dot_light_screen3">#93c6fd</color>
<color name="dot_light_screen4">#e4b5fc</color>
<array name="array_dot_active">
<item>@color/dot_light_screen1</item>
<item>@color/dot_light_screen2</item>
<item>@color/dot_light_screen3</item>
<item>@color/dot_light_screen4</item>
</array>
<array name="array_dot_inactive">
<item>@color/dot_dark_screen1</item>
<item>@color/dot_dark_screen2</item>
<item>@color/dot_dark_screen3</item>
<item>@color/dot_dark_screen4</item>
</array>
One may add more screens, but we are considering only three intro screens here.
Let's assume that the launcher activity is WelcomeActivity, which is shown only on the first-time launch, and the second activity is MainActivity.
The app flow is : WelcomeActivity -> MainActivity
First, we design activity_welcome.xml.
activity_welcome.xml consists of a Button for the next screen, another Button to skip the onboarding screen, a dots layout - to keep track of which screen the user is on, and a ViewPager to hold the screens, as shown below.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:showIn="@layout/activity_welcome">
<androidx.viewpager.widget.ViewPager
android:id="@+id/view_pager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<LinearLayout
android:id="@+id/layoutDots"
android:layout_width="match_parent"
android:layout_height="@dimen/dots_height"
android:layout_alignParentBottom="true"
android:layout_marginBottom="@dimen/dots_margin_bottom"
android:gravity="center"
android:orientation="horizontal">
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:alpha=".5"
android:layout_above="@id/layoutDots"
android:background="@android:color/white" />
<Button
android:id="@+id/btn_next"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:background="@null"
android:text="@string/next"
android:textColor="@android:color/white"
android:layout_alignParentEnd="true" />
<Button
android:id="@+id/btn_skip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:background="@null"
android:text="@string/skip"
android:textColor="@android:color/white"
android:layout_alignParentStart="true" />
</RelativeLayout>
Create a new layout resource file for every intro screen. Let the intro screens be - screen1.xml, screen2.xml, and screen3.xml. Each screen consists of an ImageView (which may be replaced by a VideoView or some view for animation, etc.), a TextView for the title, and another TextView for the description. All the screens have a similar code as shown below, with different ids for attributes.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/bg_screen1">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:gravity="center_horizontal"
android:orientation="vertical">
<ImageView
android:layout_width="@dimen/img_width_height"
android:layout_height="@dimen/img_width_height"
android:src="@drawable/screen1" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/slide_1_title"
android:textColor="@android:color/white"
android:textSize="@dimen/slide_title"
android:textStyle="bold" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:paddingLeft="@dimen/desc_padding"
android:paddingRight="@dimen/desc_padding"
android:text="@string/slide_1_desc"
android:textAlignment="center"
android:textColor="@android:color/white"
android:textSize="@dimen/slide_desc"
android:gravity="center_horizontal" />
</LinearLayout>
</RelativeLayout>
Copy the image files to the drawable folder and use them accordingly in sceenx.xml, where x = 1,2,3...
Declare the strings used in the strings.xml as shown below.
<string name="next">NEXT</string>
<string name="skip">SKIP</string>
<string name="start">GOT IT</string>
<string name="slide_1_title">Screen 1</string>
<string name="slide_1_desc">Description Screen 1</string>
<string name="slide_2_title">Screen 2</string>
<string name="slide_2_desc">Description Screen 2</string>
<string name="slide_3_title">Screen 3</string>
<string name="slide_3_desc">Description Screen 3</string>
<string name="play_again_desc">To see the welcome slider again, goto Settings -> apps -> welcome slider -> clear data</string>
<string name="play_again">Play Again</string>
Now, create a dimens.xml file to declare all the margins.
<resources>
<!-- Default screen margins, per the Android Design guidelines. -->
<dimen name="activity_horizontal_margin">16dp</dimen>
<dimen name="activity_vertical_margin">16dp</dimen>
<dimen name="fab_margin">16dp</dimen>
<dimen name="dots_height">30dp</dimen>
<dimen name="dots_margin_bottom">20dp</dimen>
<dimen name="img_width_height">120dp</dimen>
<dimen name="slide_title">26sp</dimen>
<dimen name="slide_desc">16sp</dimen>
<dimen name="desc_padding">40dp</dimen>
</resources>
One may change the screen layouts/designs as per the application/ user need.
Now, the design of the onboarding screen is complete. Let us move to the backend.
First, we implement a way to check if it is a first-time launch of the application, as the onboarding screen should be displayed only on the first-time launch.
SharedPreferences are used to check the first-time launch of the application.
We create a Preferences class, as shown below.
package com.example.appintro;
import android.content.Context;
import android.content.SharedPreferences;
public class Preferences {
SharedPreferences pref;
SharedPreferences.Editor editor;
Context _context;
// shared pref mode
int PRIVATE_MODE = 0;
// Shared preferences file name
private static final String PREF_NAME = "welcome";
private static final String IS_FIRST_TIME_LAUNCH = "IsFirstTimeLaunch";
public Preferences(Context context) {
this._context = context;
pref = _context.getSharedPreferences(PREF_NAME, PRIVATE_MODE);
editor = pref.edit();
}
public void setFirstTimeLaunch(boolean isFirstTime) {
editor.putBoolean(IS_FIRST_TIME_LAUNCH, isFirstTime);
editor.commit();
}
public boolean isFirstTimeLaunch() {
return pref.getBoolean(IS_FIRST_TIME_LAUNCH, true);
}
}
Inside the WelcomeActivity.java, we will check for the first-time app launch using isFirstTimeLaunch() method. MainActivity will be launched if it returns true, skipping the intro activity.
private Preferences preferences;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Checking for first time launch - before calling setContentView()
preferences = new Preferences(this);
if (!preferences.isFirstTimeLaunch()) {
launchHomeScreen();
finish();
}
setContentView(R.layout.activity_welcome);
}
private void launchHomeScreen() {
preferences.setFirstTimeLaunch(false);
startActivity(new Intent(WelcomeActivity.this, MainActivity.class));
finish();
}
In the launchHomeScreen() method, we set IS_FIRST_TIME_LAUNCH to false, so that when the app is launched again, prefManager.isFirstTimeLaunch() method would return false, and hence the user is directed to MainActivity, skipping the intro activity.
We will make the notification bar transparent as shown below. The changeStatusBarColor() method will be called in the onCreate() method in WelcomeActivity.java.
private void changeStatusBarColor() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
Window window = getWindow();
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.setStatusBarColor(Color.TRANSPARENT);
}
}
Now create a MyViewPagerAdapter class that the ViewPager can use to display the onboarding screens.
public class MyViewPagerAdapter extends PagerAdapter {
private LayoutInflater layoutInflater;
public MyViewPagerAdapter() {
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
layoutInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = layoutInflater.inflate(layouts[position], container, false);
container.addView(view);
return view;
}
@Override
public int getCount() {
return layouts.length;
}
@Override
public boolean isViewFromObject(View view, Object obj) {
return view == obj;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
View view = (View) object;
container.removeView(view);
}
}
getCount() method returns the number of onboarding screens.
Declare everything (all the attributes and elements) inside the WelcomeActivity.
private ViewPager viewPager;
private MyViewPagerAdapter myViewPagerAdapter;
private LinearLayout dotsLayout;
private TextView[] dots;
private int[] layouts;
private Button btnSkip, btnNext;
The layouts array contains the layouts of all welcome sliders/screens - screen1xml, screen2.xml, and screen3.xml.
viewPager = (ViewPager) findViewById(R.id.view_pager);
dotsLayout = (LinearLayout) findViewById(R.id.layoutDots);
btnSkip = (Button) findViewById(R.id.btn_skip);
btnNext = (Button) findViewById(R.id.btn_next);
// layouts of all welcome sliders
// add few more layouts if you want
layouts = new int[]{
R.layout.screen1,
R.layout.screen2,
R.layout.screen3};
Add onClickListener to btnSkip and btnNext as shown below.
btnSkip.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
launchHomeScreen();
}
});
btnNext.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// checking for last page
// if last page home screen will be launched
int current = getItem(+1);
if (current < layouts.length) {
// move to next screen
viewPager.setCurrentItem(current);
} else {
launchHomeScreen();
}
}
});
btnSkip directly skips the intro screen and launches the MainActivity. btnNext checks if it's the last page and then launches the MainActivity; else, it just moves to the next page.
getItem() method returns the index of the next ith page from the current page.
private int getItem(int i) {
return viewPager.getCurrentItem() + i;
}
addBottomDots() method sets the bottom dots - active and inactive depending upon the current page.
private void addBottomDots(int currentPage) {
dots = new TextView[layouts.length];
int[] colorsActive = getResources().getIntArray(R.array.array_dot_active);
int[] colorsInactive = getResources().getIntArray(R.array.array_dot_inactive);
dotsLayout.removeAllViews();
for (int i = 0; i < dots.length; i++) {
dots[i] = new TextView(this);
dots[i].setText(Html.fromHtml("•"));
dots[i].setTextSize(35);
dots[i].setTextColor(colorsInactive[currentPage]);
dotsLayout.addView(dots[i]);
}
if (dots.length > 0)
dots[currentPage].setTextColor(colorsActive[currentPage]);
}
ViewPager.OnPageChangeListener viewPagerPageChangeListener = new ViewPager.OnPageChangeListener() {
@Override
public void onPageSelected(int position) {
addBottomDots(position);
// changing the next button text 'NEXT' / 'GOT IT'
if (position == layouts.length - 1) {
// last page. make button text to GOT IT
btnNext.setText(getString(R.string.start));
btnSkip.setVisibility(View.GONE);
} else {
// still pages are left
btnNext.setText(getString(R.string.next));
btnSkip.setVisibility(View.VISIBLE);
}
}
@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
@Override
public void onPageScrollStateChanged(int arg0) {
}
};
Intially call addBottomDots(0); inside onCreate() method in WelcomeActivity.java.
Initialize myViewPagerAdapter and add onPageChangeListener as shown below.
myViewPagerAdapter = new MyViewPagerAdapter();
viewPager.setAdapter(myViewPagerAdapter);
viewPager.addOnPageChangeListener(viewPagerPageChangeListener);
Now, run the app. In this way, we can easily create a simple Onboarding screen using ViewPager and SharedPreferences.
The complete code can be found here.

