Flutter:如何在WebView(WebViewWidget)中选择文本,并在函数中使用它做一些事情?

xoefb8l8  于 2023-02-16  发布在  Flutter
关注(0)|答案(1)|浏览(162)

我希望我的应用的用户能够在WebViewWidget中选择文本(单词,但也可以是整句话),并(通过TTS)向他们播放该文本的音频。我只希望它能与u n d e r l i n e d文本(或以任何其他方式突出显示并与其他文本区分开来的文本)一起使用。
这是我的Widget树的一部分,我在这里测试了一些gestureRecognizers(请阅读评论):

child: GestureDetector(
  //gestureRecognizers of WebViewWidget don't do anything without this GestureDetector,
  //see: https://stackoverflow.com/questions/58811375/tapgesturerecognizer-not-working-in-flutter-webview#answer-59298134
  onTap: () => print('this line doesnt get printed'),
  child: WebViewWidget(
    controller: _controller,
    gestureRecognizers: {
      Factory<LongPressGestureRecognizer>(() => LongPressGestureRecognizer()
        ..onLongPress = () {
          print('onLongPress');
        }
        ..onLongPressStart = (LongPressStartDetails details) {
          print('onLongPressStart, ${details.globalPosition}, ${details.localPosition}');
        }),
      Factory<TapGestureRecognizer>(() => TapGestureRecognizer()
        ..onTap = () {
          print('onTap'); //this doesn't get printed at all
        }
        ..onTapDown = (TapDownDetails details) {
          //comment: this doesn't get printed unless I tap for a little long time (not as long as longPress)
          print('onTapDown, details: $details');
          /*TODO: I want to get a text selection and play audio (with tts)
             String selectedText = ...?
             TTSHelper.speak(text: selectedText);
           */
        }),
    },
  ),
),

另一种可能解决我所需问题的方法

我有一个初始化函数,在那里我从firestore中获取html(没有html,body & head标签...),并将其与一些自定义CSS沿着 Package 在html,body & head标签中。
如果没有办法用Dart代码实现我的目标,也许有一种方法可以让我在html中添加JavaScript,这样下划线的单词/句子就可以通过TTS播放音频,或者至少可以以某种方式将文本发送到我的Dart代码中?

String _prepareHTML(String content) {
    return """<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
  body {background-color: ${getCSSColor(context, CustomColors.mainAppBG)};}
  h1, h2, h3, h4, h5, h6 {color: ${getCSSColor(context, CustomColors.blueWhiteText)};}
  p {color: ${getCSSColor(context, CustomColors.text)};}
  table { 
    width: 100%;
    table-layout: fixed;
    word-wrap: break-word;
  }
  table, tr, th, td {
    color: ${getCSSColor(context, CustomColors.text)};
    border: 1px solid ${getCSSColor(context, CustomColors.text)};
    border-collapse: collapse;
  }
  th, td {
    padding: 6px 12px;
    font-weight: bold;
    font-size: 1.25em;
  }
</style>
</head>
<body>
  $content
</body>
</html>""";
  }
c0vxltue

c0vxltue1#

我认为你可以通过使用一些javascript和WebViewWidget来实现你想要的。总体思路如下:

var controller = WebViewController();
controller.addJavascriptChannel(
  JavascriptChannel(
    name: 'underlinedTextSelectChannel',
    onMessageReceived: (message) {
      var data = json.decode(message.message);
      var text = data.text as String;

      TTSHelper.speak(text: selectedText);
    }
  )
)

...

var html = """
<html>
...
<body>
  $content
  # Within content:
  This is some text <p class="underlined-text">Say this!</p> Don't say this.
  <script>
    var underlinedTexts = document.querySelectorAll('.underlined-text');
    for(var t of underlinedTexts) {
      t.addEventListener('onClick', (e) => {
        underlinedTextSelectChannel.postMessage(JSON.stringify({
        text: e.target.innerText
       }))
      })
    }
  </script>
</body>
</html>
"""

相关问题