播放或不播放文本到语音

Playing or not playing in text to speech

我有一个将文本翻译成语音的程序,在 flutter 中,到目前为止一切顺利,问题是如何让程序显示一段文本,说明“正在播放”和“未播放”的状态程序,即在播放语音的同时,显示“正在播放”状态。

非常感谢您的回复。

这是我的代码:

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),
              )
            ],
          ),
        ));
  }
}

我对代码进行了一些更改并添加了您正在寻找的行为。我将列举这些变化:

1- 移动变量 speakingtextEditingController 作为 class 的属性,因为这是正确的位置定义它们。

2- 我包含了一个 initState() 来初始化 textEditingController 并且,正如我在 flutter_tts 文档中发现的那样,我添加了两个处理程序方法来将文本从“播放”切换到“不播放”。

3- 还添加了 dispose() 方法。主要是因为 TextEditingController 应该在 widget 生命周期结束时被释放(你可以在官方文档或 in this great article 中阅读更多关于 Flutter 生命周期的信息)。

4- 我用 Column 包装了 Stack,并附加了一个带有 Text 的 SizedBox 来显示状态(我认为 Stack 小部件可能不是在这种情况下使用的最佳选择。我会把它切换到可能是简单的容器)。

5- 最后,我将 _speak_stop 方法移出构建函数,并将它们作为 class.

你可能还想看看关于setState.

使用的flutter官方文档

我已经在下面的代码中指出了变化:

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();
  }
}

我对代码进行了一些更改并添加了您正在寻找的行为。我将列举这些变化:

1- 移动变量 speakingtextEditingController 作为 class 的属性,因为这是正确的位置定义它们。

2- 我包含了一个 initState() 来初始化 textEditingController 并且,正如我在 flutter_tts 文档中发现的那样,我添加了两个处理程序方法来将文本从“播放”切换到“不播放”。

3- 还添加了 dispose() 方法。主要是因为 TextEditingController 应该在 widget 生命周期结束时被释放(你可以在官方文档或 in this great article 中阅读更多关于 Flutter 生命周期的信息)。

4- 我用 Column 包装了 Stack,并附加了一个带有 Text 的 SizedBox 来显示状态(我认为 Stack 小部件可能不是在这种情况下使用的最佳选择。我会把它切换到可能是简单的容器)。

5- 最后,我将 _speak_stop 方法移出构建函数,并将它们作为 class.

你可能还想看看关于setState.

使用的flutter官方文档

我已经在下面的代码中指出了变化:

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();
  }
}

您可以为您的 flutter 应用程序配置 FlutterToast 小部件,并且根据您的状态,您可以向您的 flutter 应用程序发送消息作为 toast。

add dependency fluttertoast: ^8.0.8

示例代码:

Fluttertoast.showToast(
    msg: 'Playing',
    toastLength: Toast.LENGTH_SHORT,
    gravity: ToastGravity.CENTER,
    timeInSecForIosWeb: 4,
    textColor: const Color.fromRGBO(0, 0, 0, 1),
    webPosition: "center",
    webBgColor: "linear-gradient(to right, #5aff15, #5aff15)",
    backgroundColor: const Color.fromRGBO(90,255,21,1),
  );