「Flutter アプリに WebView を追加する」はwebview_flutter4.0.0以降に対応していない
詳しく調べた訳ではないのでおそらくです。
Flutter アプリに WebView を追加する
実際のコード
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:path_provider/path_provider.dart';
import 'package:webview_flutter/webview_flutter.dart';
const request = '''
var req = new XMLHttpRequest();
req.open('GET', "https://api.ipify.org/?format=json");
req.onload = function() {
if (req.status == 200) {
let response = JSON.parse(req.responseText);
SnackBar.postMessage("IP Address: " + response.ip);
} else {
SnackBar.postMessage("Error: " + req.status);
}
}
req.send();''';
const addCookie = '''var date = new Date();
date.setTime(date.getTime()+(30*24*60*60*1000));
document.cookie = "FirstName=John; expires=" + date.toGMTString();''';
const removeCookie =
'''document.cookie = "FirstName=; expires=Thu, 01 Jan 1970 00:00:00 UTC";''';
const String kExamplePage = '''
<!DOCTYPE html>
<html lang="en">
<head>
<title>Load file or HTML string example</title>
</head>
<body>
<h1>Local demo page</h1>
<p>
This is an example page used to demonstrate how to load a local file or HTML
string using the <a href="https://pub.dev/packages/webview_flutter">Flutter
webview</a> plugin.
</p>
</body>
</html>
''';
class WebView extends StatelessWidget {
WebView({super.key});
static final url = Uri(
scheme: 'https',
host: 'flutter.dev',
);
final loadPercentage = ValueNotifier(0);
@override
Widget build(BuildContext context) {
var controller = WebViewController();
void createJavascriptChannels(JavaScriptMessage message) {
ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(content: Text(message.message)));
}
controller
..setJavaScriptMode(JavaScriptMode.unrestricted)
..addJavaScriptChannel('SnackBar',
onMessageReceived: createJavascriptChannels)
..setNavigationDelegate(NavigationDelegate(
onPageStarted: (url) => {},
onProgress: (progress) => loadPercentage.value = progress,
onPageFinished: (url) => loadPercentage.value = 100,
onNavigationRequest: (request) {
final host = Uri.parse(request.url).host;
if (host.contains('youtube.com')) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(
'Blocking navigation to $host',
),
),
);
return NavigationDecision.prevent;
}
return NavigationDecision.navigate;
},
))
..loadRequest(url);
var webViewWidget = WebViewWidget(
controller: controller,
);
var valueListenableBuilder = ValueListenableBuilder(
valueListenable: loadPercentage,
builder: (context, count, child) {
return LinearProgressIndicator(
value: count / 100,
);
});
var stack = Stack(
children: [webViewWidget, valueListenableBuilder],
);
var appBar = AppBar(
title: const Text('Flutter WebView'),
actions: [
NavigationConrtoller(controller: controller),
Menu(controller: controller)
],
);
var scaffold = Scaffold(
appBar: appBar,
body: stack,
);
return scaffold;
}
}
class NavigationConrtoller extends StatelessWidget {
final WebViewController controller;
const NavigationConrtoller({Key? key, required this.controller})
: super(key: key);
@override
Widget build(BuildContext context) {
late final Row row;
var left = IconButton(
icon: const Icon(Icons.arrow_back_ios),
onPressed: () {
controller.canGoBack().then((value) => {
if (value)
{controller.goBack()}
else
{
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('No back history item')),
)
}
});
},
);
var center = IconButton(
icon: const Icon(Icons.arrow_forward_ios),
onPressed: () async {
if (await controller.canGoForward()) {
await controller.goForward();
} else {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('No forward history item')),
);
return;
}
},
);
var right = IconButton(
icon: const Icon(Icons.replay),
onPressed: () {
controller.reload();
},
);
row = Row(
children: <Widget>[
left,
center,
right,
],
);
return row;
}
}
enum _MenuOptions {
navigationDelegate,
userAgent,
javascriptChannel,
listCookies,
clearCookies,
addCookie,
setCookie,
removeCookie,
loadFlutterAsset,
loadLocalFile,
loadHtmlString,
}
class Menu extends StatelessWidget {
static final url = Uri(
scheme: 'https',
host: 'youtube.com',
);
final WebViewController controller;
final cookieManager = WebViewCookieManager();
Menu({Key? key, required this.controller}) : super(key: key);
@override
Widget build(BuildContext context) {
var menu = PopupMenuButton(itemBuilder: (context) {
return <PopupMenuEntry>[
const PopupMenuItem<_MenuOptions>(
value: _MenuOptions.navigationDelegate,
child: Text('Navigate to YouTube'),
),
const PopupMenuItem<_MenuOptions>(
value: _MenuOptions.userAgent,
child: Text('Show user-agent'),
),
const PopupMenuItem<_MenuOptions>(
value: _MenuOptions.javascriptChannel,
child: Text('Lookup IP Address'),
),
const PopupMenuItem<_MenuOptions>(
value: _MenuOptions.clearCookies,
child: Text('Clear cookies'),
),
const PopupMenuItem<_MenuOptions>(
value: _MenuOptions.listCookies,
child: Text('List cookies'),
),
const PopupMenuItem<_MenuOptions>(
value: _MenuOptions.addCookie,
child: Text('Add cookie'),
),
const PopupMenuItem<_MenuOptions>(
value: _MenuOptions.setCookie,
child: Text('Set cookie'),
),
const PopupMenuItem<_MenuOptions>(
value: _MenuOptions.removeCookie,
child: Text('Remove cookie'),
),
const PopupMenuItem<_MenuOptions>(
value: _MenuOptions.loadFlutterAsset,
child: Text('Load Flutter Asset'),
),
const PopupMenuItem<_MenuOptions>(
value: _MenuOptions.loadHtmlString,
child: Text('Load HTML string'),
),
const PopupMenuItem<_MenuOptions>(
value: _MenuOptions.loadLocalFile,
child: Text('Load local file'),
),
];
}, onSelected: (value) {
switch (value) {
case _MenuOptions.navigationDelegate:
controller.loadRequest(url);
break;
case _MenuOptions.userAgent:
controller.getUserAgent().then((value) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('User-Agent: $value'),
),
);
});
break;
case _MenuOptions.javascriptChannel:
controller.runJavaScript(request).then((value) => {});
break;
case _MenuOptions.clearCookies:
cookieManager.clearCookies();
break;
case _MenuOptions.listCookies:
controller.runJavaScriptReturningResult('document.cookie').then(
(value) {
final String cookies = value as String;
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(
cookies.isNotEmpty ? cookies : 'There are no cookies.'),
),
);
},
);
break;
case _MenuOptions.addCookie:
controller.runJavaScript(addCookie).then((value) => {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Custom cookie added.'),
),
),
});
break;
case _MenuOptions.setCookie:
cookieManager
.setCookie(
const WebViewCookie(
name: 'foo', value: 'bar', domain: 'flutter.dev'),
)
.then((value) => {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Custom cookie is set.'),
),
),
});
break;
case _MenuOptions.removeCookie:
controller.runJavaScript(removeCookie).then((value) => {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Custom cookie removed.'),
),
),
});
break;
case _MenuOptions.loadFlutterAsset:
_onLoadFlutterAssetExample(controller, context);
break;
case _MenuOptions.loadLocalFile:
_onLoadLocalFileExample(controller, context);
break;
case _MenuOptions.loadHtmlString:
_onLoadHtmlStringExample(controller, context);
break;
}
});
return menu;
}
Future<void> _onLoadFlutterAssetExample(
WebViewController controller, BuildContext context) async {
await controller.loadFlutterAsset('assets/www/index.html');
}
Future<void> _onLoadLocalFileExample(
WebViewController controller, BuildContext context) async {
final String pathToIndex = await _prepareLocalFile();
await controller.loadFile(pathToIndex);
}
static Future<String> _prepareLocalFile() async {
final String tmpDir = (await getTemporaryDirectory()).path;
final File indexFile = File('$tmpDir/www/index.html');
await Directory('$tmpDir/www').create(recursive: true);
await indexFile.writeAsString(kExamplePage);
return indexFile.path;
}
Future<void> _onLoadHtmlStringExample(
WebViewController controller, BuildContext context) async {
await controller.loadHtmlString(kExamplePage);
}
}