像原生 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?
您好,这里有任何 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?