FlutterでWebviewを使いたくて、調査してみました。その時によく目に入ってるライブラリーは flutter_webview_pluginと webview_flutterです。webview_flutterは公式の製品ですが、ドキュメントの情報は flutter_webview_plugin より少ないですし、プレビュー公開の状態ですので、充実できたら、使っても良いと思いますが、今回はドキュメント情報が多い flutter_webview_plugin を利用して、WebVeiwからFlutter側に処理を実行させる方法を試してみました。
ライブラリーの紹介はこちら。
導入する際に、IOSでも正常に機能するため、ios/Runner/Info.plist
にkeyを追加する。
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
<key>NSAllowsArbitraryLoadsInWebContent</key>
<true/>
</dict>
使う時には、WebviewScaffold
を作成して、url
とappBar
の属性を設定すれば指定しているURLのウェブページが表示されます。
基本例
class WebViewSample extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new WebviewScaffold(
url: "https://www.google.com/",
appBar: new AppBar(
title: const Text('WebView Sample'),
),
javascriptChannels: jsChannels,
withJavascript: true,
withLocalStorage: true,
hidden: true,
initialChild: Container(
color: Colors.redAccent,
child: const Center(
child: Text('Waiting.....'),
),
),
);
}
}
他の細かい弄りたい場合、用意している属性を設定すれば色々調整ができます。
withJavascript
Javascriptを使いたいなら、true
に設定します。
withLocalStorage
ローカルストレージを使いたい場合、true
に設定します。
hidden
true
に設定すると、ページはローディングになっている時に、円型のプログレスバーが表示されます。
initialChild
設定するとページはローディングになっている時に自前の画面を表示するもできます。
withZoom
Zoomの機能の設定
また、他にも色々ありますので、こちらを参考していただければと思います。
イベントの監視はできます。
使用例
final flutterWebviewPlugin = new FlutterWebviewPlugin();
flutterWebviewPlugin.onUrlChanged.listen((String url) {
...
});
flutterWebviewPlugin.onScrollYChanged.listen((double offsetY) { // latest offset value in vertical scroll
// compare vertical scroll changes here with old value
});
flutterWebviewPlugin.onScrollXChanged.listen((double offsetX) { // latest offset value in horizontal scroll
// compare horizontal scroll changes here with old value
});
FlutterWebviewPlugin
のインスタンスを作成して、インスタンスで各種イベントの監視ができます。
注意:
flutterWebviewPlugin.dispose()
でwebviewの廃棄を忘れないように
FlutterWebviewPlugin
のインスタンスでwebviewの表示を制御できます。
flutterWebviewPlugin.hide();
flutterWebviewPlugin.show();
flutterWebviewPlugin.close();
flutterWebviewPlugin.launch(url, hidden: true);
javascriptとFlutterのコミュニケーションは必要になる場合、javascriptChannels
属性を設定します。
また、withJavascript
もtrue
に設定します。
今回の例は、javascriptから文字列をFlutterに渡して、print関数でFlutter側のコンソールに文字列を出力してみます。
そのため、javascriptChannels
でjavascript側で使えるチャンネルを設定し、チャンネル経由でFlutterの処理を実行します。
javascriptChannels
に配列を設定しますので、複数チャンネルの設定ができます。
今回は一つのチェンネル(名前はPrint
)を設定します。中の処理も単にもらったmessage
の文字列を出力するだけです。
final jsChannels = [
JavascriptChannel(
name: 'Print',
onMessageReceived: (JavascriptMessage message) {
print(message.message);
}
)
].toSet();
class WebViewSample extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new WebviewScaffold(
url: "https://www.mysite.com/",
appBar: new AppBar(
title: const Text('WebView Sample'),
),
javascriptChannels: jsChannels,
withJavascript: true,
withLocalStorage: true,
initialChild: Container(
color: Colors.redAccent,
child: const Center(
child: Text('Waiting.....'),
),
),
);
}
}
Webページのjavascript
if (typeof Print !== 'undefined') {
Print.postMessage('Hello world being called from Javascript code')
console.log('running inside a Flutter webview')
} else {
console.log('not running inside a Flutter webview')
}
Print
が定義しているなら、postMessage
で文字列をFlutter側に送る。
上記のコードはページのロード完了したら実行します。
Flutterアプリでwebviewを起動したら、コンソールには下記のような文字列が表示されます。
flutter_webview_pluginを使ってみた感想はかなり便利で、使い方も簡単ですし、途中に何か不具合とか今のところは発生していません。品質はすごく良いと感じました。ただ、作成したwebviewのUIは一番上に表示されますので、FlutterのDialogやToastなどの表示が隠されるみたいです。その時には、hide
とshow
を使って一時的にwebviewの表示・非表示にしてもいいかもしれません。webview_flutterではそのように問題はないみたいですし、公式のライブラリーでもあるし、色々便利の機能が出てくるではないかと期待していますので、flutter_webview_pluginとwebview_flutterを組み合わせて使う方は良い方法かもしれません。