はじめに
皆さんはFlutter触ってますか?
Googleが開発しているモバイル向けクロスプラットフォーム,かつWebまでかけちゃうぜ!!ってことで注目しいましたが,思ったとおりにできることも増えてきて,「もうアプリはFlutterで良いじゃん」も近いのかなと思っている今日このごろ.
今回はLocal(端末)に保存したHtml, Css の Web View 表示で手間取ったのでまとめていきます.
Web Viewって?
アプリ内でWebページを表示できる機能です.
アプリによってはWeb Viewだけで実装しているようなのもちらほら...
そんなわけで結構普通に必要な機能です.
今回は端末内に保存したHtmlを表示させることが目的です.
Flutterではこちらのパッケージを使うことで実装できます.
環境
$ flutter doctor
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, v1.12.13+hotfix.5, on Mac OS X 10.15.4 19E287, locale ja-JP)
[✓] Android toolchain - develop for Android devices (Android SDK version 29.0.2)
[✓] Xcode - develop for iOS and macOS (Xcode 11.4.1)
[✓] Android Studio (version 3.6)
[!] IntelliJ IDEA Ultimate Edition (version 2020.1.1)
✗ Flutter plugin not installed; this adds Flutter specific functionality.
✗ Dart plugin not installed; this adds Dart specific functionality.
[✓] Connected device (1 available)
導入&問題発生
いつもどおりパッケージを入れて導入しました.
HTMLも/assets/html/view.htmlに配置して,pubspecに追記.
dependencies:
flutter:
sdk: flutter
webview_flutter: ^0.3.21
cupertino_icons: ^0.1.2
dev_dependencies:
flutter_launcher_icons: ^0.7.5
flutter_test:
sdk: flutter
pedantic_mono: any
flutter:
uses-material-design: true
assets:
- assets/icon/
- assets/html/
flutter_icons:
android: true
ios: true
image_path: 'assets/icon/icon.png'
adaptive_icon_foreground: 'assets/icon/icon_foreground.png'
adaptive_icon_background: "#ffa103"
iOSでの設定のために /iOS/Runner/info.plist に追記
<key>io.flutter.embedded_views_preview</key>
Mainをこちらを参考に書く.
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:webview_flutter/webview_flutter.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
final String pageTitle = 'Web View Local';
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Web View',
theme: ThemeData(
primarySwatch: Colors.amber,
),
home: WebViewPage(title: pageTitle),
);
}
}
class WebViewPage extends StatefulWidget {
const WebViewPage({Key key, this.title}) : super(key: key);
final String title;
@override
_WebViewState createState() => _WebViewState();
}
class _WebViewState extends State<WebViewPage> {
WebViewController _controller;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: WebView(
onWebViewCreated: (WebViewController webViewController) async {
// 生成されたWebViewController情報を取得する
_controller = webViewController;
// HTMLファイルのURL(ローカルファイルの情報)をControllerに追加する処理
await _loadHtmlFromAssets();
},
// javascriptを有効化
javascriptMode: JavascriptMode.unrestricted,
),
);
}
/// HTMLファイルを読み込む処理(非同期)
Future _loadHtmlFromAssets() async {
//HTMLファイルを読み込んでHTML要素を文字列で返す
final fileText = await rootBundle.loadString('assets/html/view.html');
await _controller.loadUrl( Uri.dataFromString(
fileText,
mimeType: 'text/html',
encoding: Encoding.getByName('utf-8')
).toString());
}
}
これでDebugしてみたのですが... 動かない!! Androidだけ!!
問題解決
そこでふと思い出したのですが,前にFlutterに学習済みモデル(.tflite)を入れた時,Androidに拡張子を認識させる呪文を唱えた気がします.
そこで物は試しにと /android/app/src/build.gradle に
:
:
buildTypes {
release {
// TODO: Add your own signing config for the release build.
// Signing with the debug keys for now, so `flutter run --release` works.
signingConfig signingConfigs.debug
}
}
//ここを追記
aaptOptions {
noCompress "html"
}
}
と書いてみると,表示された!!
どうやらapk作成の際に中に html が取り込まれてしまっていたみたいです.
無事解決!!
おわりに
ということでなんとか問題は解決しました.
ちなみに別ファイルに分けていたcssを読み込んでくれない,などのトラブルは有りましたが,これもinline表記することで解決しました.
めでたしめでたし!!
参考資料(ありがとうございます!!)
【Flutter】WebViewを使ってWebサイトとローカルHTMLファイルを表示させる方法
Google公式Flutter用WebViewプラグインを一通り使ってみた
Loading Local Assets in WebView in Flutter