How to Create an Onboarding UI With Xamarin Forms

a user opens up your app for the first time, you got a chance to help him get familiar with it, how? you can show him a series of screens that explain what the app can do, that's onboarding in a nutshell.

in this tutorial, we are going to learn how to create an onboarding ui with xamarin.forms.

 note: 

this tutorial assumes you are comfortable with xamarin.forms and the model-view-model pattern.

getting started

in this tutorial, we are going to create an onboarding ui for an app called  tabia  , tabia helps his users create habits that last.

setting up the project

open  visual studio  and create a blank new xamarin.forms project, build and run the project, you should have the following screen:

xamarin.forms

detecting if the app is launched for the first time

onboarding screens are shown only if the app is launched for the first time,   xamarin.essentials   come with a class called  versiontracking  that can help with that. make sure  xamarin.essentials  package is installed in your nuget packages.

xamarin.essentials

 note: 

at the time of writing this tutorial, xamarin.essentials are already installed with the default template solution.

open  app.xaml.cs  , override  onstart  method and add the following line of code.

c#
 




 x 



1
versiontracking.track();



open  mainpage.xaml.cs  and add the following line of code in the constructor.

c#
 




xxxxxxxxxx
1



1
if(versiontracking.isfirstlaunchever) { //todo : launch onboarding page } 



now, we know when the app is launched for the first time, we will add the code to launch onboarding later on.

creating the onboarding ui

two nuget packages are necessary:

let's install the two packages.

nuget packages


nuget packages

ffimageloading needs to be initialize in each platform-specific project (  appdelegate.cs, mainactivity.cs  ).

on ios:

c#
 




xxxxxxxxxx
1



1
ffimageloading.forms.platform.cachedimagerenderer.init(); 



on android:

c#
 




xxxxxxxxxx
1



1
ffimageloading.forms.platform.cachedimagerenderer.init(enablefastrenderer: [true]/[false]); 


the ui will be created using the model-view-viewmodel pattern, let's create the model first.

create a folder called  feature  and add a new class called  onboardingmodel  . replace existing code with the following lines:

c#
 




 x 



1
namespace onboarding.feature 
2
{ 
3
   public class onboardingmodel 
4
    { 
5
       public string title { get; set; } 
6
       public string content { get; set; } 
7
       public string imageurl { get; set; } 
8
    } 
9
}



in the same folder, add a new class called  onboardingviewmodel  and add the following lines of code:

c#
 




x
100


1
using system.collections.objectmodel;
2
using system.windows.input;
3
using xamarin.forms;
4
namespace onboarding.feature
5
{
6
    public class onboardingviewmodel : mvvmhelpers.baseviewmodel
7
    {
8
        private observablecollection<onboardingmodel> items;
9
        private int position;
10
        private string skipbuttontext;
11
12
        public onboardingviewmodel()
13
        {
14
            setskipbuttontext("skip");
15
            initializeonboarding();
16
            initializeskipcommand();
17
        }
18
        private void setskipbuttontext(string skipbuttontext) =>    skipbuttontext = skipbuttontext;
19
        private void initializeonboarding()
20
        {
21
            items = new observablecollection<onboardingmodel> {
22
            new onboardingmodel {
23
             title = "welcome to \n tabia", content = "tabia helps you build habits that stick.", imageurl = "healthy_habits.svg"
24
            },
25
            new onboardingmodel {
26
             title = "reminder", content = "reminder helps you execute your habits each day.", imageurl = "time.svg"
27
            },
28
            new onboardingmodel {
29
             title = "track your progress", content = "charts help you visualize your efforts over time.", imageurl = "visual_data.svg"
30
            }
31
           };
32
        }
33
        private void initializeskipcommand()
34
        {
35
            skipcommand = new command(() =>
36
            {
37
                if (lastpositionreached())
38
                {
39
                    exitonboarding();
40
                }
41
                else
42
                {
43
                    movetonextposition();
44
                }
45
            });
46
        }
47
48
        private static void exitonboarding() => application.current.mainpage.navigation.popmodalasync();
49
50
        private void movetonextposition()
51
        {
52
            var nextposition = ++position;
53
            position = nextposition;
54
        }
55
56
        private bool lastpositionreached() => position == items.count - 1;
57
58
        public observablecollection<onboardingmodel> items
59
        {
60
            get => items;
61
            set => setproperty(ref items, value);
62
        }
63
64
        public string skipbuttontext
65
        {
66
            get => skipbuttontext;
67
            set => setproperty(ref skipbuttontext, value);
68
        }
69
70
        public int position
71
        {
72
            get => position;
73
            set
74
            {
75
                if (setproperty(ref position, value))
76
                {
77
                    updateskipbuttontext();
78
                }
79
            }
80
        }
81
82
        private void updateskipbuttontext()
83
        {
84
            if (lastpositionreached())
85
            {
86
                setskipbuttontext("got it");
87
            }
88
            else
89
            {
90
                setskipbuttontext("skip");
91
            }
92
        }
93
94
        public icommand skipcommand
95
        {
96
            get;
97
            private set;
98
        }
99
    }
100
}



 note  :

the property  items  of type  observablecollection<onboardingmodel>  will be bound to a carrousel view.
the property  imageurl  let specify the location of an image.

on ios, the images are stored in the folder  resource  .



on android, images are stored in the folder  resource -> drawable  .


add a new content page named  onboardingpage  and open up the  onboardingpage.xaml  , delete all the code and replace by the following:

xml
 




x
73



1
<?xml version="1.0" encoding="utf-8"?>
2
<contentpage xmlns="http://xamarin.com/schemas/2014/forms"
3
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
4
             xmlns:ffimageloadingsvg="clr-namespace:ffimageloading.svg.forms;assembly=ffimageloading.svg.forms"
5
             x:class="onboarding.feature.onboardingpage"
6
             xmlns:ob="clr-namespace:onboarding.feature"
7
             xmlns:ios="clr-namespace:xamarin.forms.platformconfiguration.iosspecific;assembly=xamarin.forms.core"
8
             ios:page.usesafearea="true"
9
             backgroundcolor="#ffffff">
10
    <contentpage.bindingcontext>
11
        <ob:onboardingviewmodel />
12
    </contentpage.bindingcontext>
13
    <contentpage.resources>
14
        <resourcedictionary>
15
            <color x:key="bluecolor">#071d92</color>
16
            <style targettype="label">
17
                <setter property="textcolor" value="{staticresource bluecolor}" />
18
                <setter property="horizontaltextalignment" value="center" />
19
                <setter property="horizontaloptions" value="center" />
20
            </style>           
21
        </resourcedictionary>
22
    </contentpage.resources>
23
    <contentpage.content>
24
        <grid>
25
            <grid.rowdefinitions>              
26
                <rowdefinition height="auto" />
27
                <rowdefinition height="*" />
28
                <rowdefinition height="auto" /> 
29
            </grid.rowdefinitions>
30
            <button grid.row="0"
31
                    horizontaloptions="endandexpand"
32
                    margin="0,0,20,0"
33
                    fontsize="medium"
34
                    fontattributes="bold"
35
                    backgroundcolor="transparent"
36
                    textcolor="{staticresource bluecolor}"
37
                    text="{binding skipbuttontext,}"
38
                    command="{binding skipcommand}"/>
39
            <carouselview x:name="onboardingcarousel"
40
                          grid.row="1"
41
                          itemssource="{binding items}"                          
42
                          verticaloptions="center"
43
                          position="{binding position}">
44
                 <carouselview.itemtemplate>
45
                    <datatemplate x:datatype="ob:onboardingmodel">
46
                        <contentview>
47
                        <flexlayout direction="column"
48
                                    justifycontent="spaceevenly">
49
                                <label text="{binding title}"
50
                                       fontattributes="bold"
51
                                       fontsize="title" />
52
                                <ffimageloadingsvg:svgcachedimage                                  
53
                                       source="{binding imageurl}"
54
                                       aspect="aspectfill"
55
                                       widthrequest="300" 
56
                                       flexlayout.alignself="center"/>                                
57
                                <label text="{binding content}"
58
                                       fontsize="body"/>                     
59
                            </flexlayout>
60
                            </contentview>
61
                    </datatemplate>
62
                </carouselview.itemtemplate>
63
            </carouselview>
64
            <indicatorview
65
                    grid.row="2"
66
                    indicatorview.itemssourceby="onboardingcarousel"
67
                    indicatorsshape="circle"
68
                    indicatorcolor="{staticresource bluecolor}"
69
                    selectedindicatorcolor="darkgray"
70
                    horizontaloptions="center"/>                   
71
        </grid>
72
    </contentpage.content>
73
</contentpage>



 note  :

at the time of writing this tutorial, the indicatorview is still experimental, you should add the following line in platform-specific project (  appdelegate.cs, mainactivity.cs) : 

 xamarin.forms.forms.setflags(new string[] { "indicatorview_experimental" }); 

at this point, the shared project should look like this:

showing onboarding

open up  mainpage.xaml.cs  , replace that todo comments with this line of code:

 navigation.pushmodalasync(new onboardingpage() 

build and run the project, you should see the following result:

 note  :

if you want to show the onboarding again, we need to uninstall the app from your device or simulator.

where to go from here?

you can learn more about the carrouselview  here  , and about the indicatorview  here  .

the project is available for download  here  . feel free to use it.


further reading

 13 of the best app designs: they're so (not) basic 

 introduction to xamarin.forms for android developers (part 1) 

 getting started with xamarin forms and prism 

 

 

 

 

Top