Issue
I have a program that translates a text into speech, in flutter, so far so good, the question is How to make the program show a text that says the status of "playing" and "not playing" in the program, that is, while the voice is playing, the "playing" status is displayed.
I would really appreciate your response.
This is my code:
import 'package:flutter/material.dart';
import 'package:flutter_tts/flutter_tts.dart';
class TextVoicePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: TextVoice(),
);
}
}
class TextVoice extends StatefulWidget {
@override
_Speak createState() => _Speak();
}
class _Speak extends State<TextVoice> {
final FlutterTts flutterTts = FlutterTts();
@override
Widget build(BuildContext context) {
bool speaking = false;
TextEditingController textEditingController = TextEditingController();
Future _speak(String text) async {
await flutterTts.setLanguage("es-MX");
await flutterTts.setPitch(1);
await flutterTts.speak(text);
}
Future _stop() async {
await flutterTts.stop();
}
return Scaffold(
body: Stack(
children: <Widget>[
Padding(
padding: EdgeInsets.all(30.0),
child: TextFormField(
controller: textEditingController,
),
),
],
),
floatingActionButtonLocation:
FloatingActionButtonLocation.miniCenterDocked,
floatingActionButton: Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
FloatingActionButton(
backgroundColor: Colors.green,
foregroundColor: Colors.white,
heroTag: "btn",
onPressed: () => _speak(textEditingController.text),
child: Icon(Icons.play_arrow),
),
SizedBox(
width: 130,
),
FloatingActionButton(
foregroundColor: Colors.white,
backgroundColor: Colors.red,
heroTag: "btn2",
onPressed: () => _stop(),
child: Icon(Icons.stop),
)
],
),
));
}
}
Solution
I've made some changes to the code and added the behavior you were looking for. I'll enumerate the changes:
1- Moved the variables speaking and textEditingController as attributes of the class, as this is the correct place to define them.
2- I included an initState() to initialize textEditingController and, as I found in flutter_tts documentation, I added two handler methods to make the switch of the text from "Playing" to "Not playing".
3- Also added a dispose() method too. Mainly because TextEditingController should be disposed when the widget lifecycle ends (you could read more about Flutter lifecycle in the official documentation or in this great article).
4- I wrapped the Stack with a Column and appended a SizedBox with a Text to display the status (I think that the Stack widget may not be the best option to use in this situation. I would switch it to a simple Container maybe).
5- Finally, I moved _speak and _stop methods out of the build function, and placed them as methods of the class.
You might also want to take a look at the official flutter documentation about the use of setState.
I've pointed out the changes in the code below:
import 'package:flutter/material.dart';
import 'package:flutter_tts/flutter_tts.dart';
class TextVoicePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: TextVoice(),
);
}
}
class TextVoice extends StatefulWidget {
@override
_Speak createState() => _Speak();
}
class _Speak extends State<TextVoice> {
final FlutterTts flutterTts = FlutterTts();
///1
bool speaking = false;
TextEditingController textEditingController;
@override ///2
void initState() {
textEditingController = TextEditingController();
flutterTts.setStartHandler(() {
///This is called when the audio starts
setState(() {
speaking = true;
});
});
flutterTts.setCompletionHandler(() {
///This is called when the audio ends
setState(() {
speaking = false;
});
});
super.initState();
}
@override ///3
void dispose() {
textEditingController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
Stack(
children: <Widget>[
Padding(
padding: EdgeInsets.all(30.0),
child: TextFormField(
controller: textEditingController,
),
),
],
),
SizedBox( ///4
child: Text(
speaking ? "Playing" : "Not playing"
),
)
],
),
floatingActionButtonLocation:
FloatingActionButtonLocation.miniCenterDocked,
floatingActionButton: Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
FloatingActionButton(
backgroundColor: Colors.green,
foregroundColor: Colors.white,
heroTag: "btn",
onPressed: () => _speak(textEditingController.text),
child: Icon(Icons.play_arrow),
),
SizedBox(
width: 130,
),
FloatingActionButton(
foregroundColor: Colors.white,
backgroundColor: Colors.red,
heroTag: "btn2",
onPressed: () => _stop(),
child: Icon(Icons.stop),
)
],
),
));
}
///5
Future _speak(String text) async {
await flutterTts.setLanguage("es-MX");
await flutterTts.setPitch(1);
await flutterTts.speak(text);
}
Future _stop() async {
await flutterTts.stop();
}
}
Answered By - Rodrigo Cardozo
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.