Overview
What You’ll Learn
Implementing Flutter ShowCaseView with the Basic Flutter Template
I have used Intro.js in the past to help onboard new users on React.js and Angular applications. This feature allows us to walk the user through the features in our app. While searching for a flutter equivalent I found a similar library on pub.dev, ShowCaseView:
Also, check out the video tutorial on implementing ShowCaseView in your flutter app:
Getting Started
I will create a small example app demonstrating this. First, let’s create a blank Flutter app. I will be using Android Studio but you may also use Visual Studio Code. We will use the default counter template it gives us:
main.dart
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
import 'package:flutter/material.dart';
void main() {
unApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: const Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}
First, let’s add the ShowCaseView package as a library using this command in your terminal:
1
flutter pub add showcaseview
We will “install” the package using this command in the terminal:
1
flutter pub get
Implementing ShowCaseView
For simplicity we are going to use the default code the template gives us. In the stateless MyApp widget, wrap the home parameter of the Material App to with ShowcaseWidget.
1
2
3
4
home: ShowCaseWidget(
builder: Builder(
builder: (context) => const MyHomePage(title: 'Flutter Demo Home Page')),
),
Note for this package to work correctly, the parent widget must use ShowCaseWidget.
Next lets wrap the floating action button and the counter text with “Showcase” widgets. The “Showcase” widget takes a key and description. Add these variables below the _counter variable.
1
2
3
4
5
final GlobalKey _floatingActionKey = GlobalKey();
final GlobalKey _counterKey = GlobalKey();
final String _incrementDescription = "Press this button to increment the count";
final String _counterTextDescription = "This text shows how many times you have pressed the button";
Next, let’s wrap the counter text with the Showcase widget:
1
2
3
4
5
6
7
8
Showcase(
key: _counterKey,
description: _counterTextDescription,
child: Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
),
Now, let’s wrap the floating action button with a showcase widget:
1
2
3
4
5
6
7
8
9
floatingActionButton: Showcase(
key: _floatingActionKey,
description: _incrementDescription,
child: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: const Icon(Icons.add),
),
),
Start the onboarding/tutorial
The following code will start the tutorial for the user:
1
ShowCaseWidget.of(context)?.startShowCase([_floatingActionKey, _counterKey]));
Notice we are passing the keys in the order we want the widgets to be hightlighted.
1
2
3
void _startTutorial(){
ShowCaseWidget.of(context)?.startShowCase([_floatingActionKey, _counterKey]);
}
If we want to start this tutorial automatically, we must add this code to initState like so: Let’s put this in a function:
1
2
3
4
5
@override
void initState() {
super.initState();
WidgetsBinding.instance?.addPostFrameCallback((_) => _startTutorial());
}
Alternatively, to start this on a button click. Let’s create a TextButton under the counter Showcase widget:
1
2
3
4
TextButton(
onPressed: _startTutorial,
child: const Text("Restart Tutorial")
)
This is the full source code:
main.dart
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
import 'package:flutter/material.dart';
import 'package:showcaseview/showcaseview.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: ShowCaseWidget(
builder: Builder(
builder: (context) =>
const MyHomePage(title: 'Flutter Demo Home Page')),
),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
final GlobalKey _floatingActionKey = GlobalKey();
final GlobalKey _counterKey = GlobalKey();
final String _incrementDescription =
"Press this button to increment the count";
final String _counterTextDescription =
"This text shows how many times you have pressed the button";
void _incrementCounter() {
setState(() {
_counter++;
});
}
void _startTutorial() {
ShowCaseWidget.of(context)
?.startShowCase([_floatingActionKey, _counterKey]);
}
@override
void initState() {
super.initState();
WidgetsBinding.instance?.addPostFrameCallback((_) => _startTutorial());
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text(
'You have pushed the button this many times:',
),
Showcase(
key: _counterKey,
description: _counterTextDescription,
child: Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
),
TextButton(
onPressed: _startTutorial,
child: const Text("Restart Tutorial"))
],
),
),
floatingActionButton: Showcase(
key: _floatingActionKey,
description: _incrementDescription,
child: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: const Icon(Icons.add),
),
),
);
}
}
Run the app
Run the app and this should be your result:
Congratulations, you have implemented ShowCaseView in your flutter app!
Also, check out the video tutorial on implementing ShowCaseView in your flutter app: