2024年7月15日
開発環境
OS:Windows 11
SDK:VS Code + Flutter 3.7.12
概要
アプリ内のローカルストレージに格納したhtmlファイルを画面に表示します。
WebViewウィジェットを準備する
HTMLファイルはWebViewウィジェットを通して表示します。
そのため、WebViewパッケージをインストールする必要があります。
サンプルプロジェクトを生成して動作確認してみます。
flutter create sample
webview_flutterをインストールします。
flutter pub add webview_flutter
HTMLファイルを準備する
次にHTMLファイルを準備します。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>Top Page</title>
</head>
<script>
function sendData1() {
// Flutterへデータ送信
sample.postMessage("1");
}
function sendData2() {
// Flutterへデータ送信
sample.postMessage("2");
}
</script>
<body>
<h1>Please tap a button.</h1>
<br>
<br>
<button onclick="sendData1()">Send Data 1</button>
<br>
<br>
<button onclick="sendData2()">Send Data 2</button>
</body>
</html>
ボタンが2つあるHTMLファイル(top.html)を作成しました。
プロジェクトフォルダ内に「html」フォルダを作成し、その中に作成したhtmlファイルを格納します。
次にpubspec.yamlのassets項目にhtmlファイルを定義します。
assets:
- html/top.html
WebViewウィジェット実装
main.dartにWebViewウィジェットを追加します。
ネットワーク上のurlにアクセスして表示するわけではないため、htmlのロード処理もあわせて追加する必要があります。
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:webview_flutter/webview_flutter.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
late WebViewController controller;
late Future<void> controllerInitialization;
@override
void initState() {
super.initState();
controllerInitialization = initController();
}
Future<void> initController() async {
final html = await rootBundle.loadString('html/top.html');
controller = WebViewController()
..setJavaScriptMode(JavaScriptMode.unrestricted)
..addJavaScriptChannel('sample', onMessageReceived: (result) async {
switch (result.message) {
case "1":
print("call 1.");
break;
case "2":
print("call 2.");
break;
}
})
..loadRequest(
Uri.dataFromString(
html,
mimeType: "text/html",
encoding: Encoding.getByName("utf-8"),
),
);
}
@override
Widget build(BuildContext context) {
return FutureBuilder<void>(
future: controllerInitialization,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
return Scaffold(
appBar: AppBar(title: const Text("Test Page")),
body: WebViewWidget(controller: controller),
);
} else {
return const CircularProgressIndicator();
}
},
);
}
}
※Android向けのビルドが失敗した場合はこちら↓をチェックしてみてください。
動作確認
デバッグモードで起動しました。
HTMLのテキストと2つのボタンは期待通りに表示されています。
次にボタンを押し分けてみると・・・
ターミナルに「call 1.」、「call 2.」が表示されました。
ボタン操作も処理できることが確認できました。
今回は以上です。