像原生 Dialog 一样将语音转为文本

Flutter speech to text like native Dialog

您好,这里有任何 Flutter 专家可以帮助解决我想要实现 Flutter 语音识别的小问题。颤动 speech_to_text:^5.4.3。插件工作正常但问题是当用户单击麦克风按钮时,我想在顶部栏上实现本地语音识别,它会出现警告对话框,如下图所示,当用户说话时,它会显示如下图所示的文本,任何人都知道 here is picture click on it

我也为此使用了自定义对话框生成器,但我的文本在下面的对话框文本检查代码中没有更新

    import 'dart:math';
    import 'package:bibleapp/Dbhelper.dart';
    import 'package:bibleapp/chapters.dart';
    import 'package:flutter/cupertino.dart';
    import 'package:flutter/material.dart';
    import 'package:speech_to_text/speech_recognition_result.dart';
    import 'package:speech_to_text/speech_to_text.dart' as stt;
    import 'package:speech_to_text/speech_to_text.dart';
    import 'package:avatar_glow/avatar_glow.dart';
    
    
    class Booknames extends StatefulWidget {
      const Booknames({Key? key}) : super(key: key);
    
      @override
      _BooknamesState createState() => _BooknamesState();
    }
    
    class _BooknamesState extends State<Booknames> {
     var booknames=['Genesis','Exodus','Leviticus','Numbers',
     'Deuteronomy','Joshua',
     'Judges','Ruth','1 Samuel','2 Samuel','1 Kings','2 Kings',
     '1 Chronicles','2 Chronicles','Ezra','Nehemiah','Esther',
     'Job','Psalms','Proverbs','Ecclesiastes','Song of Solomon','Isaiah','Jeremiah',
     'Lamentations','Ezekiel','Daniel','Hosea','Joel','Amos','Obadiah','Jonah','Micah',
     'Nahum','Habakkuk','Zephaniah','Haggai','Zechariah','Malachi','Matthew',
     'Mark','Luke','John','Acts','Romans','1 Corinthians','2 Corinthians','Galatians',
     'Ephesians','Philippians','Colossians','1 Thessalonians','2 Thessalonians','1 Timothy',
     '2 Timothy','Titus','Philemon','Hebrews','James','1 Peter',
     '2 Peter','1 John','2 John','3 John','Jude','Revelation'];
    
    
     Dbhelper dbhelper=new Dbhelper();
    
     stt.SpeechToText speechToText=stt.SpeechToText();
     bool islistening=false;
//this text i want change after listening    

String text='Example:Gensis Chapter 1 verse 5';
    
    
    
       @override
       void initState() {
         // TODO: implement initState
         super.initState();
         dbhelper.db;
         _initSpeech();
       }
    
       /// This has to happen only once per app
       void _initSpeech() async {
         speechToText.initialize();
       }
      
///this dialog when user press on mic button it show alert alert dialog button

 showAlertDialog() {
         Widget okButton = TextButton(
           child: Text("CANCEL VOICE"),
           onPressed: () => Navigator.of(context).pop(false),
         );
    
    
         AlertDialog alert = AlertDialog(
           title: Text("Search by voice"),
           content: Container(
             height: 180,
             child: Column(
               children: [
                 AvatarGlow(
                   glowColor: Colors.blue,
                   endRadius: 75,
                   duration: Duration(milliseconds: 2500),
                   repeat: true,
                   showTwoGlows: islistening,
                   repeatPauseDuration: Duration(milliseconds: 150),
                   child: Material(
                     elevation: 5,
                     shape: CircleBorder(),
                     child: CircleAvatar(
                       backgroundColor: Colors.white,
                       child: Icon(Icons.mic, color: Colors.blue, size: 30,),
                       radius: 50,
                     ),
                   ),
                 ),
                 Expanded(child: Container(
                   child: Text(text),
                 )),
               ],
             ),
           ),
           actions: [
             okButton,
           ],
         );
    
         // show the dialog
         showDialog(
           context: context,
           builder: (BuildContext context) {
             return alert;
           },
         );
       }
    
    
    
    
       @override
       Widget build(BuildContext context) {
         return Scaffold(
           appBar: AppBar(
             actions: <Widget>[
               new IconButton(
          ///when user clickec on mic button dialog and speech rcoginition methods calll
                 icon: new Icon(islistening?Icons.mic:Icons.mic_none),
                 highlightColor: Colors.pink,
                 onPressed:(){
                   setState(() {
                     showAlertDialog();
                     _listen();
                   });
                 },
               ),
    
             ],
             elevation: 0,
             title: Text('The Bible Multiversion', style: TextStyle(
                 fontSize: 20
             ),),
             centerTitle: true,
           ),
           body: Column(
             mainAxisAlignment: MainAxisAlignment.start,
             crossAxisAlignment: CrossAxisAlignment.start,
             children: [
               Expanded(
                 child: ListView.separated(
                   shrinkWrap: true,
                   itemCount: booknames.length,
                   separatorBuilder: (BuildContext context, int index) =>
                       Divider(height: 1),
                   itemBuilder: (context, index) {
                     return Column(
                       children: [
                         GestureDetector(
                           onTap: () {
                             int increment = index + 1;
    
    
                             Navigator.push(
                               context,
                               PageRouteBuilder(
                                 pageBuilder: (context, animation1, animation2) =>
                                     chapters(increment, booknames[index]),
                                 transitionDuration: Duration(seconds: 0),
    
                               ),
                             );
                             // Navigator.push(
                             //   context,
                             //   MaterialPageRoute(builder: (context) =>  chapters(increment)),
                             // );
                           },
                           child: ListTile(
                             leading: CircleAvatar(
                               radius: 20,
                               backgroundColor: Colors.primaries[Random().nextInt(
                                   Colors.primaries.length)],
                               child: Text(
                                 booknames[index].substring(0, 1), style: TextStyle(
                                   fontSize: 17,
                                   fontWeight: FontWeight.bold,
                                   color: Colors.white
                               ),),
                             ),
    
                             title: Text(
                               booknames[index], style: TextStyle(
                                 color: Colors.black,
                                 fontSize: 20
                             ),
    
                             ),
    
    
                           ),
                         ),
    
                       ],
    
                     );
                   },
    
                 ),
               ),
             ],
    
           ),
         );
       }

//this voice listener method
     void _listen() async {
       if (!islistening) {
         bool available = await speechToText.initialize(
           onStatus: (val) => print('onStatus: $val'),
           onError: (val) => print('onError: $val'),
         );
         if (available) {
    
    
           setState(() {
             islistening=true;
           });
           speechToText.listen(
             onResult: (result)=>setState(() {

               //this text is not updating in dialog
               text=result.recognizedWords;
//but this print method continues printing spkoen word in console

print('result.recognizedWords')
    
    
             })
           );
    
    
         }
       } else {
         setState(() => islistening = false
    
         );
         speechToText.stop();
    
       }
     }
    }

我认为这是一个常见问题,setState 对对话框不起作用,因为对话框不是树的一部分。

这是showDialog()的文档:

/// This function takes a `builder` which typically builds a [Dialog] widget.
/// Content below the dialog is dimmed with a [ModalBarrier]. The widget
/// returned by the `builder` does not share a context with the location that
/// `showDialog` is originally called from. Use a [StatefulBuilder] or a
/// custom [StatefulWidget] if the dialog needs to update dynamically.

可以使用StatefulBuilder,参考How to refresh an AlertDialog in Flutter?