👌

Flutter WindowsでWebViewを使う方法②

2023/09/27に公開

はじめに

前回の続きとして、webview_windowsを使ってJavaScriptのメソッドを呼び出す、またはその結果を受け取る方法についてを書こうと思います。

やりたいこと

やる前に、まずは仕様を整理します。

  • Flutterで何かのJavaScript処理を実行し、その結果をWebViewに反映

  • WebViewから何かのデータをFlutterに送信し、その結果をFlutterで表示

簡単なことですね、さっそく始めましょう。

実装

FlutterでJavaScriptを使う

WebviewController.executeScriptというAPIを利用することで、JavaScriptの実行が可能です。

  Future<void> _initWebView() async {
    // 前回の実装
    if (context.mounted) {
      setState(() {});
    }

    // WebViewを表示して1秒後、Zenn Topicのタイトルを「JavaScript Method Test」に変える
    Future.delayed(
      const Duration(seconds: 1),
      () => _webviewController.executeScript(
        '''
        var elems = document.getElementsByClassName("TopicHeader_title__INUvl");
        elems[0].innerHTML = "JavaScript Method Test";
        ''',
      ),
    );
  }

成果物①

ed1

JavaScriptからデータをFlutterに渡す

まずはデータを渡す処理ですね。

  Future<void> _initWebView() async {
    // 前回の実装
    if (context.mounted) {
      setState(() {});
    }

    // postMessageを使ってHTML文字列を送る
    Future.delayed(
      const Duration(seconds: 1),
      () => _webviewController.executeScript(
        '''
        var elems = document.getElementsByClassName("TopicHeader_title__INUvl");
        window.chrome.webview.postMessage(elems[0].outerHTML);
        ''',
      ),
    );
  }

そしてはデータを受け取る処理です。

  Future<void> _initWebView() async {
    // 前回の実装
    if (context.mounted) {
      setState(() {});
    }

    // 受け取ったデータをダイアログで表示する
    _webviewController.webMessage.listen(
      (dynamic event) => showDialog<void>(
        context: context,
        builder: (_) => AlertDialog(
          title: Text('$event'),
        ),
      ),
    );
  }

成果物②

ed2

もちろん、複数のデータを一気に送ることも可能です。

  Future<void> _initWebView() async {
    // 前回の実装
    if (context.mounted) {
      setState(() {});
    }

    // JSON形式でouterHTMLとinnerHTMLを同時に渡す
    Future.delayed(
      const Duration(seconds: 2),
      () => _webviewController.executeScript(
        '''
        var elems = document.getElementsByClassName("TopicHeader_title__INUvl");
        var outerHTML = JSON.stringify(elems[0].outerHTML);
        var innerHTML = JSON.stringify(elems[0].innerHTML);
        var jsonString = `{"outerHTML": \${outerHTML}, "innerHTML": \${innerHTML}}`;
        window.chrome.webview.postMessage(JSON.parse(jsonString));
        ''',
      ),
    );

    _webviewController.webMessage.listen((dynamic event) {
      if (event is! Map) {
        return;
      }

      // Key–valueなので、仕様に合わせてお好きな形にできる
      final children = <Widget>[];
      for (var entry in event.entries) {
        children.add(
          ListTile(
            title: Text(entry.key),
            subtitle: Text(entry.value),
          ),
        );
      }
      showDialog<void>(
        context: context,
        builder: (_) => AlertDialog(
          title: Column(children: children),
        ),
      );
    });
  }

成果物③

ed3

さいごに

今回は、webview_windowsでJavaScriptの使い方についてを紹介しました。

このように書けば、必要最低限の実装はできるかなと思います。

他にも様々なテクニックがあるのですが、ご参考になれば幸いです。

GitHubで編集を提案

Discussion