👌
Flutter WindowsでWebViewを使う方法②
はじめに
前回の続きとして、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";
''',
),
);
}
成果物①
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'),
),
),
);
}
成果物②
もちろん、複数のデータを一気に送ることも可能です。
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),
),
);
});
}
成果物③
さいごに
今回は、webview_windowsでJavaScriptの使い方についてを紹介しました。
このように書けば、必要最低限の実装はできるかなと思います。
他にも様々なテクニックがあるのですが、ご参考になれば幸いです。
Discussion