Flutter Flows made easy!
Usage
Define a Flow State
The flow state will be the state which drives the flow. Each time this state changes, a new navigation stack will be generated based on the new flow state.
Flutter Flows made easy! A Flutter package which simplifies flows with a flexible, declarative API.
class Profile { const Profile({this.name, this.age, this.weight}); final String? name; final int? age; final int? weight; Profile copyWith({String? name, int? age, int? weight}) { return Profile( name: name ?? this.name, age: age ?? this.age, weight: weight ?? this.weight, ); } }
Create a FlowBuilder
FlowBuilder
is a widget which builds a navigation stack in response to changes in the flow state. onGeneratePages
will be invoked for each state change and must return the new navigation stack as a list of pages.
FlowBuilder<Profile>( state: const Profile(), onGeneratePages: (profile, pages) { return [ MaterialPage(child: NameForm()), if (profile.name != null) MaterialPage(child: AgeForm()), ]; }, );
Update the Flow State
The state of the flow can be updated via context.flow<T>().update
.
class NameForm extends StatefulWidget { @override _NameFormState createState() => _NameFormState(); } class _NameFormState extends State<NameForm> { var _name = ''; void _continuePressed() { context.flow<Profile>().update((profile) => profile.copyWith(name: _name)); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('Name')), body: Center( child: Column( children: <Widget>[ TextField( onChanged: (value) => setState(() => _name = value), decoration: InputDecoration( labelText: 'Name', hintText: 'John Doe', ), ), RaisedButton( child: const Text('Continue'), onPressed: _name.isNotEmpty ? _continuePressed : null, ) ], ), ), ); } }
Complete the Flow
The flow can be completed via context.flow<T>().complete
.
class AgeForm extends StatefulWidget { @override _AgeFormState createState() => _AgeFormState(); } class _AgeFormState extends State<AgeForm> { int? _age; void _continuePressed() { context .flow<Profile>() .complete((profile) => profile.copyWith(age: _age)); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('Age')), body: Center( child: Column( children: <Widget>[ TextField( onChanged: (value) => setState(() => _age = int.parse(value)), decoration: InputDecoration( labelText: 'Age', hintText: '42', ), keyboardType: TextInputType.number, ), RaisedButton( child: const Text('Continue'), onPressed: _age != null ? _continuePressed : null, ) ], ), ), ); } }
FlowController
A FlowBuilder
can also be created with a custom FlowController
in cases where the flow can be manipulated outside of the sub-tree.
class MyFlow extends StatefulWidget { @override State<MyFlow> createState() => _MyFlowState(); } class _MyFlowState extends State<MyFlow> { late FlowController<Profile> _controller; @override void initState() { super.initState(); _controller = FlowController(const Profile()); } @override Widget build(BuildContext context) { return FlowBuilder( controller: _controller, onGeneratePages: ..., ); } @override dispose() { _controller.dispose(); super.dispose(); } }
Download Flutter Flows package source code on GitHub
https://github.com/felangel/flow_builder
Provides the list of the opensource Flutter apps collection with GitHub repository.