Build an onboarding experience for your mobile apps with Flutter - Part 1: Building the screens
You will need Dart and Flutter set up on your machine.
Introduction
In this tutorial series, we’ll be building a nice app intro with Flutter exploiting the onboarding technique. Onboarding is a great way to introduce your app to newcomers, to help them quickly adapt to the new conditions so that they can get the most out of your app. In UX design, onboarding is a set of techniques and interactions aimed at comforting users and giving the initial introduction of the product. The Material Design guide states:
Onboarding is one point in a longer journey that begins in the app store and ends with the user taking the first key retention-correlated action in your app.
We can consider onboarding to be a useful UX technique to present your product to potential users, it is defined as a way of making someone familiar with an app. Your apps may not be self-explanatory so they surely need to include onboarding.
Now that you know what onboarding is, we’ll dive into this tutorial. I’ll show you how to build a nice onboarding experience for your mobile app using the Flutter framework.
Demo
This is the final result of the tutorial. Nice isn’t it ? 😎 You will be able to achieve that at the end of the tutorial.
Prerequisites
This tutorial assumes a little knowledge of Flutter or Dart. JavaScript knowledge will be helpful as well, especially ES6 features.
You should have:
- Visual Studio Code editor installed on your machine if you haven’t yet. We’ll use it in our tutorial.
- Visual Studio Code Flutter plugin
- An emulator or physical device (for app testing/debugging purpose)
- Flutter and Dart installed on your machine. Kindly refer to this link for more information about their installation. It will guide you through the installation of Flutter SDK on your machine as well as the Dart language
Project setup
Open your code editor and hit ctrl+shift+p
or cmd+shift+p
to create a new project, and give it a name, or simply run flutter create your_project_name
in your terminal to quickly create a new project. After that, you’ll end up with a fresh Flutter project.
Head over to the pubspec.yaml
file and amend it like the following:
//../pubspec.yaml
name: flutter_slides
description: A new Flutter project.
# The following defines the version and build number for your application.
# A version number is three numbers separated by dots, like 1.2.43
# followed by an optional build number separated by a +.
# Both the version and the builder number may be overridden in flutter
# build by specifying --build-name and --build-number, respectively.
# Read more about versioning at semver.org.
version: 1.0.0+1
environment:
sdk: ">=2.0.0-dev.68.0 <3.0.0"
dependencies:
flutter:
sdk: flutter
transformer_page_view:
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^0.1.2
dev_dependencies:
flutter_test:
sdk: flutter
# For information on the generic Dart part of this file, see the
# following page: https://www.dartlang.org/tools/pub/pubspec
# The following section is specific to Flutter.
flutter:
# The following line ensures that the Material Icons font is
# included with your application, so that you can use the icons in
# the material Icons class.
uses-material-design: true
# To add assets to your application, add an assets section, like this:
assets:
- assets/slide_1.png
- assets/slide_2.png
- assets/slide_3.png
- assets/slide_4.png
# - images/a_dot_ham.jpeg
# An image asset can refer to one or more resolution-specific "variants", see
# https://flutter.io/assets-and-images/#resolution-aware.
# For details regarding adding assets from package dependencies, see
# https://flutter.io/assets-and-images/#from-packages
# To add custom fonts to your application, add a fonts section here,
# in this "flutter" section. Each entry in this list should have a
# "family" key with the font family name, and a "fonts" key with a
# list giving the asset and other descriptors for the font. For
# example:
fonts:
- family: Quicksand
fonts:
- asset: assets/Quicksand-Bold.ttf
weight: 700
# - asset: fonts/Schyler-Italic.ttf
# style: italic
# - family: Trajan Pro
# fonts:
# - asset: fonts/TrajanPro.ttf
# - asset: fonts/TrajanPro_Bold.ttf
# weight: 700
#
# For details regarding fonts from package dependencies,
# see https://flutter.io/custom-fonts/#from-packages
In the dependencies section of the file, we’ve added the transformer_page_view
dependency, a page transformer plugin for Flutter. This will help us to build our onboarding screens with no hassle.
Create an assets
directory into the root of your Flutter project. You can find the content of this folder at this link.
Don’t forget to run
flutter packages get
in your terminal to install your dependencies.
Building the onboarding experience
As you may have noticed in the demo, we have four screens, each one has two text views, an image and carousel indicators. These screens present and describe our app to our users in order to make them feel comfortable with it, especially to not make them disoriented.
We’ll focus first on building the screens in the first part of the series, as stated in the title
Building the screens
Here’s the code for the screens. Kindly paste it in your main.dart
file.
//..lib/main.dart
import 'package:flutter/material.dart';
import 'package:transformer_page_view/transformer_page_view.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
theme: ThemeData(
// This is the theme of your application.
//
// Try running your application with "flutter run". You'll see the
// application has a blue toolbar. Then, without quitting the app, try
// changing the primarySwatch below to Colors.green and then invoke
// "hot reload" (press "r" in the console where you ran "flutter run",
// or simply save your changes to "hot reload" in a Flutter IDE).
// Notice that the counter didn't reset back to zero; the application
// is not restarted.
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
final String title;
MyHomePage({this.title});
MyHomePageState createState() {
return new MyHomePageState();
}
}
class MyHomePageState extends State<MyHomePage> {
int _slideIndex = 0;
final List<String> images = [
"assets/slide_1.png",
"assets/slide_2.png",
"assets/slide_3.png",
"assets/slide_4.png"
];
final List<String> text0 = [
"Welcome in your app",
"Enjoy teaching...",
"Showcase your skills",
"Friendship is great"
];
final List<String> text1 = [
"App for food lovers, satisfy your taste",
"Find best meals in your area, simply",
"Have fun while eating your relatives and more",
"Meet new friends from all over the world"
];
final IndexController controller = IndexController();
Widget build(BuildContext context) {
TransformerPageView transformerPageView = TransformerPageView(
pageSnapping: true,
onPageChanged: (index) {
setState(() {
this._slideIndex = index;
});
},
loop: false,
controller: controller,
transformer: new PageTransformerBuilder(
builder: (Widget child, TransformInfo info) {
return new Material(
color: Colors.white,
elevation: 8.0,
textStyle: new TextStyle(color: Colors.white),
borderRadius: new BorderRadius.circular(12.0),
child: new Container(
alignment: Alignment.center,
color: Colors.white,
child: Padding(
padding: const EdgeInsets.all(18.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
new ParallaxContainer(
child: new Text(
text0[info.index],
style: new TextStyle(
color: Colors.blueGrey,
fontSize: 34.0,
fontFamily: 'Quicksand',
fontWeight: FontWeight.bold),
),
position: info.position,
opacityFactor: .8,
translationFactor: 400.0,
),
SizedBox(
height: 45.0,
),
new ParallaxContainer(
child: new Image.asset(
images[info.index],
fit: BoxFit.contain,
height: 350,
),
position: info.position,
translationFactor: 400.0,
),
SizedBox(
height: 45.0,
),
new ParallaxContainer(
child: new Text(
text1[info.index],
textAlign: TextAlign.center,
style: new TextStyle(
color: Colors.blueGrey,
fontSize: 28.0,
fontFamily: 'Quicksand',
fontWeight: FontWeight.bold),
),
position: info.position,
translationFactor: 300.0,
),
SizedBox(
height: 55.0,
),
],
),
),
),
);
}),
itemCount: 4);
return Scaffold(
backgroundColor: Colors.white,
body: transformerPageView,
);
}
}
First, we import the material library so that we can use the MaterialApp
widget inside our app. We’ve also imported our transformer_page_view_dependency
. Now inside our main
function, we have our MyApp
widget returning the MaterialApp
widget defining our app title, our app theme, and our MyHomePage
widget.
The MyHomePage
widget is a stateful widget as it has to manage its own state through some data. MyHomePageState
is intended to handle the state of MyHomePage
as you can see. Then, we defined four variables:
-
_slideIndex
: initialized to 0, this variable is used to keep track of the current index of our slide -
images
: an array of images to use in our screens -
text0
and text1: arrays of texts to describe our screens -
controller
: an object ofIndexController
to get some useful info about indexes of screens and to control them.
Next, we declared our transformerPageView
object of type TransformerPageView
to build our well said screens, and to control their behavior. This object has some useful properties to control our page view behavior. We’ll take a look at some of them:
-
onPageChanged
: called with the new index when the user swiped, we overrided the_slideIndex
with the new current index each time the user swiped -
loop
: whether to loop or not, we set it to false -
controller
: the index controller -
transformer
: the most important property of this widget, it returns atransformed
widget that based on the widget parameter. The returned widget as it happens is the current screen presented to the user, just aMaterial
widget wrapping two texts widget and an image asset. We wrapped each of these widgets inside aParallaxContainer
to mimic a parallax effect on screens swiping. -
itemCount
: number of total items/screens.
So here are the four screens you should have if you have followed along 🙃 .
Just execute this command: flutter run
in your terminal to run your app running with a smooth transition between screens 😎 .
In the next part of the tutorial, we’ll add carousel indicators to the slides to make it more user friendly.
Conclusion
In this first part of this tutorial series, you’ve learnt what onboarding is, then we’ve put this knowledge into practice by building the screens of our app intro. This is just the first steps of a beautiful journey 😉 . Follow me in the second part to see how we can polish the app with the carousel indicators and get more control over the app. Here is the code for the first part of the series.
5 March 2019
by Ethiel Adiassa