intro
A step-by-step wizard, which can help you to introduce your product or to demonstrate the usage of your application.
Features
- Step by step demonstration
- Control the demo flow
- Highlight the target widget
- Automatically calculates the location and alignment of intro card
- Customizable style and behavior
- Supports nesting of multiple demo flow
- Link between different pages or dialogs
- Full platform support
Demo
Getting started
Add this package to your project.
flutter pub add intro
Import it in your code.
import 'package:intro/intro.dart';
Usage
-
Register the
Intro
widget at the earliest possible widget tree node.Provide a
IntroController
that has specified thestepCount
. ThestepCount
refers to the total number of steps in the demo flow.
runApp(Intro(
controller: IntroController(stepCount: 5),
child: MaterialApp(
home: HomePage(),
),
));
- Wrap the
IntroStepTarget
widget around each of your target widgets that you need to introduce.
IntroStepTarget(
step: step,
controller: Intro.of(context).controller,
cardContents: TextSpan(
text: "The introductory text of this step.",
),
child: targetWidget,
);
- Start the demo flow at the right time.
Intro.of(context).controller.start(context);
Decoration for intro card
Provid a IntroCardDecoration
object in the cardDecoration
field of the IntroStepTarget
widget (specific step target) or the Intro
widget (global) to describe the style or behavior for intro card.
Globally effective:
Intro(
cardDecoration: IntroCardDecoration(
// TODO:
// Some attributes that need to be specifically specified.
// For missing attributes , they will use its default value.
),
// ...
);
Only effective for specific step:
IntroStepTarget(
cardDecoration: IntroCardDecoration(
// TODO:
// Some attributes that need to be specifically specified.
// For missing attributes , they will use global value (be specified in `Intro`).
),
// ...
);
Attributes for IntroCardDecoration
:
Decoration for highlighted widget
Provid a IntroHighlightDecoration
object in the highlightDecoration
field of the IntroStepTarget
widget (specific step target) or the Intro
widget (global) to describe the style for highlighted widget.
Globally effective:
Intro(
highlightDecoration: IntroHighlightDecoration(
// TODO:
// Some attributes that need to be specifically specified.
// For missing attributes , they will use its default value.
),
// ...
);
Only effective for specific step:
IntroStepTarget(
highlightDecoration: IntroHighlightDecoration(
// TODO:
// Some attributes that need to be specifically specified.
// For missing attributes , they will use global value (be specified in `Intro`).
),
// ...
);
Attributes for IntroHighlightDecoration
:
Controller
You can control the demo flow through the IntroController
instance.
Create a IntroController instance:
You must specify a total number of steps, and other callback events are optional.
IntroController(
stepCount: 5,
onWillPrevious: (currentStep) {
// This callback is called when the demo flow is about to jump to the previous step.
// You can return `false` if you want to prevent it from taking effect.
},
onWillNext: (currentStep) {
// This callback is called when the demo flow is about to jump to the next step.
// You can return `false` if you want to prevent it from taking effect.
},
onWillClose: (currentStep) {
// This callback is called when the demo flow is about to close.
// You can return `false` if you want to prevent it from taking effect.
},
);
Get the instance:
You can define the controller instance as a global variable to make it easier to use throughout your program. Or, you can get the controller instance through Intro.of(context).controller
.
final controller = Intro.of(context).controller;
Get total number of steps:
controller.stepCount;
Get current status:
controller.isOpened;
Start, close and destroy:
Start this demo flow.
controller.start(context);
You can specify a initial step through initStep
parameter.
controller.start(context, initStep: 3);
Stop this demo flow.
controller.close();
Destroy this demo flow. Note that it can never be used again when it destroyed.
controller.dispose();
Jump step:
Jump to next step. It's equivalent to close()
if called at the last step.
controller.next();
Jump back previous step.
controller.previous();
Jump to specific step.
controller.jumpTo(5);
Manually refresh.
controller.refresh();
Customized intro card
If you don't like the default intro card style, you can customize it through IntroStepTarget.custom
constructor.
IntroStepTarget.custom(
step: step,
controller: controller,
cardDecoration: IntroCardDecoration(...),
cardBuilder: (BuildContext context, IntroParams params, IntroCardDecoration decoration) {
// Build your card widget.
// You can use the `params` to get more information or to implement more functionality.
// You can also use the `decoration` to decorate your card widget. It was defined above or by `Intro` widget.
return ...;
},
child: child,
);
Attributes for IntroParams
:
Event-handling
You can do something (such as open a page, pop a dialog, update widget, load resources etc.) at the right time.
- There are five event-handling callbacks are provided.
- They are defined in the
IntroStepTarget
widget. - These callbacks can be synchronous or asynchronous.
IntroStepTarget(
onTargetLoad: () {
// It will be called when the target widget was built.
},
onTargetDispose: () {
// It will be called when the target widget was disposed.
},
onHighlightTap: () {
// It will be called when tap the highlighted widget.
},
onStepWillActivate: (int fromStep) {
// It will be called when the demo flow reaches the current step.
// The current step is finally activated only when this callback execution is complete.
// The `fromStep` tells you from which step it jumped to the current step.
// In particular, the value of `fromStep` is '0' means that this is the beginning.
},
onStepWillDeactivate: (int willToStep) {
// It will be called when the demo flow leaves the current step.
// The current step is finally deactivated only when this callback execution is complete.
// The `willToStep` tells you which step it will to jump to.
// In particular, the value of `willToStep` is '0' means that this is the ending.
},
// ...
);
Nested
You can have multiple demo flows in your program. The same target widget may be used in different demo flow.
Step:
-
Define each controller.
In this case, you may not be able to get the
IntroController
exactly fromIntro.of(context).controller
. So, it's a good idea to save each controller separately beforehand.
final controller1 = IntroController(stepCount: 5);
final controller2 = IntroController(stepCount: 3);
- Register echo
Intro
widget. Each one uses a separate controller.
Intro(
controller: controller1,
child: Intro(
controller: controller2,
child: MyApp(),
),
);
-
Bind the step target widgets for each demo flow separately.
If a target widget is used by multiple demo flow simultaneously, it can be nested build with two
IntroStepTarget
.
IntroStepTarget(
controller: controller1,
step: 1,
// ...
child: IntroStepTarget(
controller: controller2,
step: 3,
// ...
child: targetChild,
),
);
- Perform operations on each controller individually.
Top Layer
The topLayerBuilder
of Intro
is provided for you to create custom widgets at the top layer. For example, you can build a global exit button.
Intro(
topLayerBuilder: (context, controller) {
return Padding(
padding: const EdgeInsets.only(top: 20, left: 20),
child: TextButton(
onPressed: controller.close,
child: const Text("Exit"),
),
);
},
// ...
);
Other
Change barrier color or animation duration.
Intro(
barrierColor: Colors.black87,
animationDuration: Duration(milliseconds: 500),
// ...
);
To see the full demonstration or more advanced features, read the example code please.