DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Because the DevOps movement has redefined engineering responsibilities, SREs now have to become stewards of observability strategy.

Apache Cassandra combines the benefits of major NoSQL databases to support data management needs not covered by traditional RDBMS vendors.

The software you build is only as secure as the code that powers it. Learn how malicious code creeps into your software supply chain.

Generative AI has transformed nearly every industry. How can you leverage GenAI to improve your productivity and efficiency?

Related

  • Handle Sensitive Data Securely With Skyflow
  • Create a Beautiful Login Form With Angular Material
  • Validation Forms in Vue.js Apps Using Vuelidate library
  • Exploring Intercooler.js: Simplify AJAX With HTML Attributes

Trending

  • How To Introduce a New API Quickly Using Quarkus and ChatGPT
  • The Evolution of Scalable and Resilient Container Infrastructure
  • Supervised Fine-Tuning (SFT) on VLMs: From Pre-trained Checkpoints To Tuned Models
  • Modern Test Automation With AI (LLM) and Playwright MCP
  1. DZone
  2. Coding
  3. Frameworks
  4. How to Create an Onboarding UI With Xamarin Forms

How to Create an Onboarding UI With Xamarin Forms

This tutorial assumes you are comfortable with Xamarin.Forms and the Model-View-Model pattern.

By 
Patrick Tshibanda user avatar
Patrick Tshibanda
·
Updated Apr. 23, 20 · Tutorial
Likes (5)
Comment
Save
Tweet
Share
13.7K Views

Join the DZone community and get the full member experience.

Join For Free

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 

xamarin.forms app xamarin Form (document)

Published at DZone with permission of Patrick Tshibanda. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • Handle Sensitive Data Securely With Skyflow
  • Create a Beautiful Login Form With Angular Material
  • Validation Forms in Vue.js Apps Using Vuelidate library
  • Exploring Intercooler.js: Simplify AJAX With HTML Attributes

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!