Skip to main content
RapidDev - Software Development Agency
flutterflow-tutorials

How to Build a Voice Controlled User Interface in FlutterFlow

Build a voice-controlled interface using a Custom Action with the speech_to_text package that listens for spoken commands, parses keywords to map them to app actions like navigation and search, and provides visual feedback during listening. A command map routes keywords to specific actions (navigate home, search for X, open settings, go back). Animated waveform and pulsing indicators show listening state. Fallback suggestion chips appear when a command is not recognized so users learn the available voice vocabulary.

What you'll learn

  • How to integrate speech_to_text for voice input via a Custom Action
  • How to parse spoken transcripts into actionable commands with keyword matching
  • How to provide visual feedback during listening with animated indicators
  • How to handle unrecognized commands with suggestion chips as fallback
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Beginner7 min read20-30 minFlutterFlow Pro+ (Custom Actions require code)March 2026RapidDev Engineering Team
TL;DR

Build a voice-controlled interface using a Custom Action with the speech_to_text package that listens for spoken commands, parses keywords to map them to app actions like navigation and search, and provides visual feedback during listening. A command map routes keywords to specific actions (navigate home, search for X, open settings, go back). Animated waveform and pulsing indicators show listening state. Fallback suggestion chips appear when a command is not recognized so users learn the available voice vocabulary.

Adding Voice Commands to Your FlutterFlow App

Voice control makes apps accessible and hands-free. This tutorial integrates the speech_to_text package to listen for spoken commands, maps keywords to navigation and search actions, shows animated visual feedback while listening, and gracefully handles unrecognized commands with suggestion chips.

Prerequisites

  • FlutterFlow project with multiple pages to navigate between
  • Microphone permission configured in your app settings
  • Basic understanding of Custom Actions in FlutterFlow
  • speech_to_text package added to pubspec dependencies

Step-by-step guide

1

Set up the speech_to_text Custom Action for voice input

Create a Custom Action called startListening that initializes the SpeechToText instance, checks availability, and starts listening. The action takes an Action Parameter callback onResult that returns the recognized transcript string. On initialization, call speech.initialize() to request microphone permission. When the user activates listening, call speech.listen() with a localeId matching your app's language. The onResult callback fires with the final recognized text when the user stops speaking or after a silence timeout.

start_listening_action.dart
1// Custom Action: startListening
2import 'package:speech_to_text/speech_to_text.dart' as stt;
3
4Future<String> startListening() async {
5 final speech = stt.SpeechToText();
6 bool available = await speech.initialize(
7 onStatus: (status) => print('Status: $status'),
8 onError: (error) => print('Error: $error'),
9 );
10 if (!available) return 'Speech recognition not available';
11
12 String result = '';
13 await speech.listen(
14 onResult: (val) {
15 if (val.finalResult) {
16 result = val.recognizedWords;
17 }
18 },
19 listenFor: const Duration(seconds: 10),
20 pauseFor: const Duration(seconds: 3),
21 localeId: 'en_US',
22 );
23 // Wait for result
24 await Future.delayed(const Duration(seconds: 4));
25 await speech.stop();
26 return result;
27}

Expected result: The Custom Action listens for speech input and returns the recognized transcript as a string.

2

Build the command parser to map keywords to actions

Create a Custom Function called parseCommand that takes the transcript string and returns a command name. Use contains() checks on the lowercased transcript for fuzzy matching: if it contains 'home' return 'navigate_home', if it contains 'search' extract the query text after the keyword and return 'search:query', if it contains 'settings' return 'navigate_settings', if it contains 'back' return 'go_back'. If no keyword matches, return 'unknown'. This approach handles natural variations like 'take me home' or 'go to settings' instead of requiring exact phrases.

parse_command.dart
1// Custom Function: parseCommand
2String parseCommand(String transcript) {
3 final text = transcript.toLowerCase().trim();
4
5 if (text.contains('home')) return 'navigate_home';
6 if (text.contains('settings')) return 'navigate_settings';
7 if (text.contains('profile')) return 'navigate_profile';
8 if (text.contains('back')) return 'go_back';
9 if (text.contains('search')) {
10 final query = text.replaceAll(
11 RegExp(r'.*search\s*(for)?\s*'), ''
12 ).trim();
13 return query.isNotEmpty ? 'search:$query' : 'search:';
14 }
15 return 'unknown';
16}

Expected result: The parser converts natural speech like 'take me home' into structured command strings like navigate_home.

3

Execute commands with an Action Flow dispatcher

In the page where voice control is active, after the startListening action returns a transcript, pass it to parseCommand. Then use Conditional Actions to execute the result: if command equals 'navigate_home', use Navigate To action to the HomePage. If command equals 'navigate_settings', navigate to SettingsPage. If command starts with 'search:', extract the query and set the search TextField value plus trigger the search. If command equals 'go_back', use Navigator Pop. If command equals 'unknown', update a Page State variable showSuggestions to true and display a SnackBar with the message 'Command not recognized'.

Expected result: Voice commands trigger real app actions like navigation, search, and back navigation.

4

Add visual feedback with a pulsing listening indicator

Add a Stack at the center of the screen (or overlay via a global Stack) with a Container that is visible only when Page State isListening equals true. Inside the Container, add three concentric circles with scale animations (use FlutterFlow's built-in animations: scale from 1.0 to 1.5, infinite loop, different delays per circle to create a ripple effect). Add a microphone Icon at the center. Below the circles, add a Text widget showing 'Listening...' that updates to show the partial transcript as the user speaks. This gives clear visual feedback that the app is actively processing voice input.

Expected result: An animated pulsing indicator appears while the app is listening for voice commands.

5

Show suggestion chips when a command is not recognized

When the parseCommand function returns 'unknown', display a Wrap widget with tappable chips showing available commands: 'Go Home', 'Search', 'Open Settings', 'Go Back', 'Open Profile'. Each chip is a Container with rounded corners and an InkWell. Tapping a chip executes that command directly (same as if the user had spoken it). Use Conditional Visibility on the Wrap so it appears only when showSuggestions is true. Add a dismiss timer or close button so the suggestions disappear after 5 seconds or on the next voice activation.

Expected result: Unrecognized voice commands show tappable suggestion chips that teach users the available voice vocabulary.

Complete working example

FlutterFlow Voice Controlled UI
1CUSTOM ACTION: startListening
2 Initialize SpeechToText
3 Check availability + request mic permission
4 Listen for up to 10 seconds, 3-second silence pause
5 Return final recognized transcript
6
7CUSTOM FUNCTION: parseCommand(transcript)
8 Lowercase + trim transcript
9 Contains 'home' 'navigate_home'
10 Contains 'settings' 'navigate_settings'
11 Contains 'profile' 'navigate_profile'
12 Contains 'back' 'go_back'
13 Contains 'search' 'search:{extracted_query}'
14 No match 'unknown'
15
16PAGE STATE:
17 isListening: bool (default false)
18 showSuggestions: bool (default false)
19 currentTranscript: String
20
21APPBAR:
22 IconButton (microphone icon)
23 On tap set isListening = true
24 startListening Custom Action
25 set isListening = false
26 parseCommand(transcript)
27 Conditional Actions based on command result:
28 navigate_home Navigate to HomePage
29 navigate_settings Navigate to SettingsPage
30 navigate_profile Navigate to ProfilePage
31 go_back Navigator Pop
32 search:{query} Set search field + trigger search
33 unknown showSuggestions = true + SnackBar
34
35LISTENING OVERLAY (Conditional: isListening == true):
36 Stack:
37 Three Containers (concentric circles)
38 Scale animation 1.01.5, loop, staggered delays
39 Icon (microphone, center)
40 Text (currentTranscript, updates live)
41
42SUGGESTION CHIPS (Conditional: showSuggestions == true):
43 Wrap:
44 Chip 'Go Home' execute navigate_home
45 Chip 'Search' execute search
46 Chip 'Settings' execute navigate_settings
47 Chip 'Go Back' execute go_back
48 Chip 'Profile' execute navigate_profile
49 Auto-dismiss after 5 seconds

Common mistakes when building a Voice Controlled User Interface in FlutterFlow

Why it's a problem: Trying to match exact spoken phrases like 'navigate home' instead of fuzzy keyword matching

How to avoid: Use contains() checks for key words (home, settings, search, back) rather than exact phrase matching. This handles natural speech variation.

Why it's a problem: Not showing any visual indicator while the app is listening

How to avoid: Show an animated pulsing indicator and display the partial transcript in real-time so users see their words being recognized.

Why it's a problem: Not handling the case where speech recognition is unavailable

How to avoid: Check speech.initialize() return value. If false, show a SnackBar explaining that speech recognition is not available on this device and hide the microphone button.

Best practices

  • Use fuzzy keyword matching with contains() instead of exact phrase matching
  • Show a pulsing visual indicator and live transcript while listening
  • Display suggestion chips for unrecognized commands to teach the vocabulary
  • Keep the command vocabulary simple and discoverable (5-10 commands maximum)
  • Add a microphone button in the AppBar for consistent access across pages
  • Set a reasonable listening timeout (10 seconds) to avoid indefinite listening

Still stuck?

Copy one of these prompts to get a personalized, step-by-step explanation.

ChatGPT Prompt

Build a voice-controlled interface for a FlutterFlow app using speech_to_text. I need a Custom Action for listening, a command parser that maps keywords to navigation actions (home, settings, search, back), visual feedback with a pulsing listening indicator, and fallback suggestion chips when a command is not recognized. Include the Dart code for the listener and parser.

FlutterFlow Prompt

Add a microphone IconButton to the AppBar. When tapped, show a centered overlay with three concentric circles animating with scale pulse and a microphone icon in the center. Below the circles show a Text widget that updates with the recognized speech.

Frequently asked questions

Which languages does speech_to_text support?

The speech_to_text package supports all languages available on the device's speech engine. Pass the localeId parameter (e.g., 'en_US', 'es_ES', 'fr_FR') to specify the language. Call speech.locales() to get the list of available locales on the current device.

Can I add custom commands for my specific app?

Yes. Extend the parseCommand function with additional contains() checks for your domain-specific keywords. For example, add 'cart' for e-commerce or 'appointments' for scheduling apps.

Does voice control work on both iOS and Android?

Yes. The speech_to_text package supports both platforms. iOS requires the NSMicrophoneUsageDescription key in Info.plist. Android requires RECORD_AUDIO permission in the manifest.

How do I handle noisy environments?

Set a confidence threshold. The SpeechRecognitionResult includes a confidence score between 0 and 1. Only act on results above 0.7 confidence. Below that, show the transcript and ask the user to confirm.

Can I keep the app always listening for a wake word?

Continuous listening drains battery significantly. Instead, use a tap-to-speak pattern with the microphone button. For always-on mode, consider a lightweight wake word detector that only activates full speech recognition after the trigger word.

Can RapidDev help build voice-enabled apps?

Yes. RapidDev can integrate speech recognition, natural language processing, and voice-controlled navigation into FlutterFlow apps with custom command vocabularies and multi-language support.

RapidDev

Talk to an Expert

Our team has built 600+ apps. Get personalized help with your project.

Book a free consultation

Need help with your project?

Our experts have built 600+ apps and can accelerate your development. Book a free consultation — no strings attached.

Book a free consultation

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.