Navigating between screens (Flutter)¶
If your Flutter app has several screens, you can add voice commands to navigate through the app. For example, if the app shows a list of products, you may let the user open product details and then go back to the products list with voice. In this tutorial, we will add a new screen to our simple Flutter app and create voice commands to navigate between the app screens.
YouTube
If you are a visual learner, watch this tutorial on Alan AI YouTube Channel.
What you will learn¶
How to send commands to a Flutter app
How to handle commands on the Flutter app side
How to navigate between screens of a Flutter app with voice
What you will need¶
To go through this tutorial, make sure the following prerequisites are met:
You have completed the following tutorial: Building a voice agent for a Flutter app.
You have set up the Flutter environment and it is functioning properly. For details, see Flutter documentation.
The device on which you are planning to test drive the Flutter app is connected to the Internet. The Internet connection is required to let the Flutter app communicate with the dialog script run in the Alan AI Cloud.
Step 1: Add a new screen to the Flutter app¶
Note
This step is required if you are using the Flutter app created in the previous tutorial. You can also use your own app with several screens. In this case, skip this step and go to step 2.
In the Building a voice assitant for a Flutter app tutorial, we have created a single-screen Flutter app with the Alan AI button. Now let’s add a new screen to this app.
Open the app, go to the
main.dart
file and add the code for the second screen:/// Add the second screen class SecondPage extends StatefulWidget { const SecondPage({Key? key}) : super(key: key); @override _SecondPageState createState() => _SecondPageState(); } class _SecondPageState extends State<SecondPage> { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text("Flutter Demo Second Page"), ), body: Center( child: ElevatedButton( child: Text("Go back"), onPressed: () { Navigator.pop(context); } ), ), ); } }
In the
MaterialApp
constructor, define the app routes:class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', theme: ThemeData( primarySwatch: Colors.blue, ), home: MyHomePage(title: 'Flutter Demo Home Page'), /// Define the app routes initialRoute: '/', routes: { '/second': (context) => const SecondPage(), } ); } }
The second screen contains only one button that brings us back to the home screen. Let’s also add a button to the home screen to navigate to the second screen. To the body of the home screen, add the following button code:
@override Widget build(BuildContext context) { return Scaffold( body: Center( child: Column( children: <Widget>[ Text( '$_counter', style: Theme.of(context).textTheme.headline4, ), /// Add a button ElevatedButton( child: Text("Open the second screen"), onPressed: () { Navigator.pushNamed(context, '/second'); } ), ], ), ), ); }
You can test it: run the app. Now our app has two screens, and we can navigate between them. Tap the Open the second screen
and Go back
buttons to go to the second screen and back.
Step 2: Add voice commands for navigation¶
We need to add new commands to the dialog to navigate between screens with voice. In Alan AI Studio, open the project and in the code editor, add the following intents:
intent('Open the second screen', p => {
p.play({command: 'forward'});
p.play('Opening the second screen');
});
intent('Go back', p => {
p.play({command: 'back'});
p.play('Going back');
});
Now, when we say one of these commands to the app, two things happen:
Alan AI sends the command provided in the intent to the Flutter app. To send the command, we need to specify a JSON object in the
p.play
function. In this tutorial, the object contains the command name.The AI agent plays back the action confirmation to us.
Step 3: Handle commands on the app side¶
When we say Open the second screen
or Go back
, Alan AI sends a command to the Flutter app. We need to handle this command on the app side and make sure an appropriate action is performed. To do this, we
will add a handler in the app.
In the
main.dart
file, update the onCommand handler:class _MyHomePageState extends State<MyHomePage> { _MyHomePageState() { AlanVoice.addButton( "976d23299e2cfbc77d43485dbc3cb44a2e956eca572e1d8b807a3e2338fdd0dc/stage", buttonAlign: AlanVoice.BUTTON_ALIGN_LEFT); /// Update the onCommand handler AlanVoice.onCommand.add((command) => _handleCommand(command.data)); } }
To the
_MyHomePageState
class, add the_handleCommand()
function to handle commands passed from the dialog script:void _handleCommand(Map<String, dynamic> command) { switch(command["command"]) { case "forward": Navigator.pushNamed(context, '/second'); break; case "back": Navigator.pop(context); break; default: debugPrint("Unknown command"); } }
Here is how it works: when the Flutter app receives some command from the dialog script, _handleCommand
is invoked. If the sent command is forward
, the second screen is open. If the sent command is back
,
we are brought to the home screen in the app.
You can test it: run the app on the device, tap the Alan AI button and say: Open the second screen
. Then say Go back
.
What’s next?¶
Have a look at the next tutorial: Passing the app state to the dialog script.