我想使用Flutter和Dart渲染存储在手机内存中的本地HTML文件到Webview中。
答案 0 :(得分:3)
这是更详细的答案。我正在使用Flutter团队的webview_flutter插件。
将依赖项添加到 pubspec.yaml :
dependencies:
webview_flutter: ^0.3.4
将HTML文件放入assets
文件夹中(请参见this)。我称它为help.html
。
获取代码中的html字符串并将其添加到webview。
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:webview_flutter/webview_flutter.dart';
class HelpScreen extends StatefulWidget {
@override
HelpScreenState createState() {
return HelpScreenState();
}
}
class HelpScreenState extends State<HelpScreen> {
WebViewController _controller;
@override
Widget build(BuildContext context) {
_loadHtmlFromAssets();
return Scaffold(
appBar: AppBar(title: Text('Help')),
body: WebView(
initialUrl: '',
onWebViewCreated: (WebViewController webViewController) {
_controller = webViewController;
},
),
);
}
_loadHtmlFromAssets() async {
String fileText = await rootBundle.loadString('assets/help.html');
_controller.loadUrl( Uri.dataFromString(
fileText,
mimeType: 'text/html',
encoding: Encoding.getByName('utf-8')
).toString());
}
}
initialUrl
设置为空字符串(null会导致异常)。我不知道这是否是标准做法,但似乎可行。io.flutter.embedded_views_preview
添加为true
。检查docs是否有关于此要求的任何更新。答案 1 :(得分:2)
您可以传递数据URI
A.prototype.msg
或者您可以在Flutter内部启动Web服务器,并传递一个URL,该URL指向服务器提供文件的IP /端口。
另请参阅https://github.com/fluttercommunity/flutter_webview_plugin/issues/23
中的讨论有关如何从资产中加载字符串的信息,请参见https://flutter.io/docs/development/ui/assets-and-images#loading-text-assets。
有关如何读取其他文件的信息,请参见https://flutter.io/docs/cookbook/persistence/reading-writing-files。
答案 2 :(得分:2)
您可以使用Flutter InAppWebView Plugin。它将在应用程序内创建本地服务器,并在WebView中运行HTML应用程序。启动服务器:
InAppLocalhostServer localhostServer = new InAppLocalhostServer();
Future main() async {
WidgetsFlutterBinding.ensureInitialized();
await localhostServer.start();
runApp(new MyApp());
}
//... ...
class _MyHomePageState extends State < MyHomePage > {
//... ...
@override
void dispose() {
localhostServer.close();
super.dispose();
}
}
然后将您的localhost html索引文件指向WebView。
InAppWebView(
initialUrl: "http://localhost:8080/assets/index.html",
),
在许多情况下,它对许多人来说并不起作用,因为他们忘记将所有文件夹作为资产添加到pubspec.yaml
文件中。例如,您需要指定所有文件夹和索引文件,如下所示:
assets:
- assets/index.html
- assets/css/
- assets/images/
- assets/js/
- assets/others/
您可以查看this tutorial以获得更多详细信息。
答案 3 :(得分:1)
我有同样的问题;这就是我解决的方法。
将webview_flutter添加到项目依赖项:
public ActionResult<FilterList<MyPOCO>> GetFilteredResult(string filter)
{
var l = new FilterList<MyPOCO>();
l.Total = 123456;
// Continue to add many MyPOCO objects into the list
return l;
}
在屏幕/状态小部件内创建一个WebViewController
webview_flutter: 0.3.14+1
使用onWebViewCreated属性实施WebView并将值分配给_controller。加载HTML文件。
WebViewController _controller;
WebView(
initialUrl: '',
onWebViewCreated: (WebViewController webViewController) async {
_controller = webViewController;
await loadHtmlFromAssets('legal/privacy_policy.html', _controller);
},
)
答案 4 :(得分:1)
asset_webview 插件是专门为此设计的。功能比其他插件少,但使用简单。
答案 5 :(得分:0)
@Suragch,您的代码在发布时不起作用,它说localUrl被调用为null。 分配控制器后,需要调用_loadHtmlFromAssets:
onWebViewCreated: (WebViewController webViewController) {
_controller = webViewController;
_loadHtmlFromAssets();
}
然后正常工作:)
答案 6 :(得分:0)
您可以使用我的插件flutter_inappwebview,与其他插件相比,该插件具有许多事件,方法和选项!
要从资产文件夹中加载html文件,您需要在pubspec.yaml
文件中声明它,然后再使用它(请参阅更多here)。
pubspec.yaml
文件的示例:
...
# The following section is specific to Flutter.
flutter:
# The following line ensures that the Material Icons font is
# included with your application, so that you can use the icons in
# the material Icons class.
uses-material-design: true
assets:
- assets/index.html
...
之后,您只需使用initialFile
小部件的InAppWebView
参数即可将index.html
加载到WebView中:
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
Future main() async {
runApp(new MyApp());
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => new _MyAppState();
}
class _MyAppState extends State<MyApp> {
@override
void initState() {
super.initState();
}
@override
void dispose() {
super.dispose();
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: InAppWebViewPage()
);
}
}
class InAppWebViewPage extends StatefulWidget {
@override
_InAppWebViewPageState createState() => new _InAppWebViewPageState();
}
class _InAppWebViewPageState extends State<InAppWebViewPage> {
InAppWebViewController webView;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("InAppWebView")
),
body: Container(
child: Column(children: <Widget>[
Expanded(
child: Container(
child: InAppWebView(
initialFile: "assets/index.html",
initialHeaders: {},
initialOptions: InAppWebViewWidgetOptions(
inAppWebViewOptions: InAppWebViewOptions(
debuggingEnabled: true,
),
),
onWebViewCreated: (InAppWebViewController controller) {
webView = controller;
},
onLoadStart: (InAppWebViewController controller, String url) {
},
onLoadStop: (InAppWebViewController controller, String url) {
},
),
),
),
]))
);
}
}
答案 7 :(得分:0)
strip()
答案 8 :(得分:0)
你可以用这个获取页面html
var htmlCode = await controller.getHtml();
var document = parse(htmlCode);
你还需要html包
答案 9 :(得分:0)
您可以获取页面 html 并使用它来加载页面,下面是示例代码
import 'dart:convert';
import 'package:aws_bot/Utils/Const.dart';
import 'package:aws_bot/Utils/User.dart';
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import 'package:flutter_webview_plugin/flutter_webview_plugin.dart';
import 'package:html/parser.dart';
class signIn extends StatefulWidget {
const signIn({Key? key}) : super(key: key);
@override
_signInState createState() => _signInState();
}
class _signInState extends State<signIn> {
String userEmail = "";
String userPassword = "";
final flutterWebviewPlugin = new FlutterWebviewPlugin();
bool evalJsOnce = false;
String _currentUrl = "";
User _user = User();
bool _loading = true;
double progress = 0.0;
@override
void initState() {
super.initState();
// Future.delayed(Duration(microseconds: 3), () async {
// Map info = await _user.getEmailPassword();
// _user.userEmail = info['email'];
// _user.userPassword = info['password'];
// setState(() {});
// });
}
@override
Widget build(BuildContext context) {
flutterWebviewPlugin.onProgressChanged.listen((double progress) {
print("progress changed = $progress");
if (progress == 1.0) {
//https://portal.aws.amazon.com/billing/signup
flutterWebviewPlugin.onUrlChanged.listen((String url) {
_currentUrl = url;
print("url changed = $url");
if (url.contains('https://portal.aws.amazon.com/billing/signup')) {
print("signup");
flutterWebviewPlugin.evalJavascript(''
'document.querySelector("#CredentialCollection").addEventListener("submit", function(e) {window.Mchannel.postMessage(JSON.stringify({"email": document.querySelector("#awsui-input-0").value, "password": document.querySelector("#awsui-input-1").value, "confirmPass": document.querySelector("#awsui-input-2").value, "accountName": document.querySelector("#awsui-input-3").value}));});');
} else {
flutterWebviewPlugin.evalJavascript(''
'let pageHtml = document.documentElement.innerHTML;'
'window.Emailchannel.postMessage(pageHtml);'
'if (pageHtml.includes("Root user email address")) {'
'document.querySelector("#next_button").addEventListener("click", function(e) {window.Emailchannel.postMessage(JSON.stringify({"email": document.querySelector("#resolving_input").value}));});}'
'');
}
// } else if (url.contains(
// 'https://signin.aws.amazon.com/signin?redirect_uri=https%3A%2F%2Fconsole.aws.amazon.com%2Fconsole%2Fhome%3Ffromtb%3Dtrue%26hashArgs%3D%2523%26isauthcode%3Dtrue%26state%3DhashArgsFromTB_us-east-1_2b2a9061808657b8&client_id=arn%3Aaws%3Asignin%3A%3A%3Aconsole%2Fcanvas&forceMobileApp=0&code_challenge=-HEkj8kWzXDv2qBLcBQX2GYULvcP2gsHr0p0X_fJJcU&code_challenge_method=SHA-256')) {
// flutterWebviewPlugin.evalJavascript(''
// 'document.querySelector("#next_button").addEventListener("click", function(e) {e.preventDefault(); window.Emailchannel.postMessage(JSON.stringify({"email": document.querySelector("#resolving_input").value}));});;');
// } else if (url.contains(
// "https://signin.aws.amazon.com/signin?redirect_uri=https%3A%2F%2Fconsole.aws.amazon.com%2Fconsole%2Fhome%3Ffromtb%3Dtrue%26hashArgs%3D%2523%26isauthcode%3Dtrue%26state%3DhashArgsFromTB_us-east-1_c885b81ed0514ab4&client_id=arn%3Aaws%3Asignin%3A%3A%3Aconsole%2Fcanvas&forceMobileApp=0&code_challenge=_Tqr3pEXTDAqOYjWp0ehE6ToYYSN7OLeyJWBx5HTPVM&code_challenge_method=SHA-256")) {
// print("enter pass");
// // flutterWebviewPlugin.evalJavascript(''
// // 'document.querySelector("#signin_button").addEventListener("click", function(e) {e.preventDefault(); window.Passwordchannel.postMessage(JSON.stringify({"password": document.querySelector("#password").value}));});;');
// } else if (url.contains("https://console.aws.amazon.com/")) {
// // flutterWebviewPlugin.launch(_consts.successDirectUrl +
// // "email=${_user.userEmail}&password=${_user.userPassword}");
// }
});
}
});
flutterWebviewPlugin.onStateChanged.listen((WebViewStateChanged state) {
print("state changed = $state");
});
return Scaffold(
appBar: AppBar(
title: Text(
'AWS Sign In',
style: TextStyle(color: Colors.black),
),
backgroundColor: Colors.yellow[600],
),
floatingActionButton: _backButton(context),
body: Column(
children: [
(progress != 1.0)
? LinearProgressIndicator(
// minHeight: 10.0,
value: progress,
backgroundColor: Colors.redAccent,
valueColor: AlwaysStoppedAnimation<Color>(Colors.black))
: Container(),
Container(
color: Colors.yellow[600],
width: double.infinity,
padding: EdgeInsets.all(8.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Email Address of you AWS : ${consts.user.userEmail}",
style: TextStyle(
fontWeight: FontWeight.w600,
),
),
SizedBox(
height: 4.0,
),
Text(
"IAM user name : ${consts.user.accountName}",
style: TextStyle(
fontWeight: FontWeight.w600,
),
),
SizedBox(
height: 4.0,
),
Text(
"Password : ${consts.user.userPassword != "null" && consts.user.userPassword != "" ? consts.user.userPassword.replaceAll(consts.user.userPassword, "******") : ""}",
style: TextStyle(
fontWeight: FontWeight.w600,
),
),
],
)),
Expanded(child: _buildSignInPage()),
],
),
);
}
_buildSignInPage() {
String _url = "https://console.aws.amazon.com/iam/home#/users";
return InAppWebView(
initialUrlRequest: URLRequest(url: Uri.parse(_url)),
// javascriptChannels: Set.from([
// JavascriptChannel(
// name: 'Emailchannel',
// onMessageReceived: (JavascriptMessage message) {
// //This is where you receive message from
// //javascript code and handle in Flutter/Dart
// //like here, the message is just being printed
// //in Run/LogCat window of android studio
// print("console message = ${message.message}");
// setState(() {
// _user.userEmail =
// jsonDecode(message.message)['email'].toString();
// });
// }),
// JavascriptChannel(
// name: 'Passwordchannel',
// onMessageReceived: (JavascriptMessage message) {
// //This is where you receive message from
// //javascript code and handle in Flutter/Dart
// //like here, the message is just being printed
// //in Run/LogCat window of android studio
// print("console message = ${jsonDecode(message.message)}");
// setState(() {
// _user.userEmail =
// jsonDecode(message.message)['password'].toString();
// });
// })
// ]),
// withJavascript: true,
onConsoleMessage: (controller, consoleMessage) async {
print("console message = ${consoleMessage.message}");
print(consoleMessage.messageLevel.toString());
// LOG ERROR => message levels
if (consoleMessage.messageLevel.toString() != "ERROR" &&
consoleMessage.messageLevel.toString() != "WARNING") {
Map message = jsonDecode(consoleMessage.message);
if (message.containsKey("email")) {
consts.user.userEmail = message['email'].toString();
await consts.user.storeSignUpInfo(email: consts.user.userEmail);
} else if (message.containsKey("password")) {
consts.user.userPassword = message['password'].toString();
await consts.user
.storeSignUpInfo(password: consts.user.userPassword);
} else if (message.containsKey("delete")) {
Future.delayed(Duration.zero, () async {
await consts.user.clearStorage();
consts.user.userEmail = "";
consts.user.userPassword = "";
});
} else if (message.containsKey("sEmail")) {
consts.user.userEmail = message['sEmail'].toString();
await consts.user.storeSignUpInfo(email: consts.user.userEmail);
} else if (message.containsKey("sPassword")) {
consts.user.userPassword = message["sPassword"].toString();
await consts.user
.storeSignUpInfo(password: consts.user.userPassword);
} else if (message.containsKey("sAccountName")) {
consts.user.accountName = message["sAccountName"].toString();
await consts.user
.storeSignUpInfo(accountName: consts.user.accountName);
} else if (message.containsKey("sFullName")) {
consts.user.fullName = message["sFullName"].toString();
await consts.user.storeSignUpInfo(fullName: consts.user.fullName);
} else if (message.containsKey("sPhone")) {
consts.user.phoneNumber = message["sPhone"].toString();
await consts.user
.storeSignUpInfo(phoneNumber: consts.user.phoneNumber);
} else if (message.containsKey("sRegion")) {
consts.user.region = message["sRegion"].toString();
await consts.user.storeSignUpInfo(region: consts.user.region);
} else if (message.containsKey("sAddress")) {
consts.user.address = message["sAddress"].toString();
await consts.user.storeSignUpInfo(address: consts.user.address);
} else if (message.containsKey("sCity")) {
consts.user.city = message["sCity"].toString();
await consts.user.storeSignUpInfo(city: consts.user.city);
} else if (message.containsKey("sState")) {
consts.user.state = message["sState"].toString();
await consts.user.storeSignUpInfo(state: consts.user.state);
} else if (message.containsKey("sPostal")) {
consts.user.postalCode = message["sPostal"].toString();
await consts.user
.storeSignUpInfo(postalCode: consts.user.postalCode);
} else if (message.containsKey("sOrganize")) {
consts.user.oraganization = message["sOrganize"].toString();
await consts.user
.storeSignUpInfo(organization: consts.user.oraganization);
}
setState(() {
if (consts.user.userPassword != "" &&
!message.containsKey("delete")) {
/*Future.delayed(Duration.zero, () async {
await consts.user.storeEmailAndPassword(
consts.user.userEmail, consts.user.userPassword);
// controller.loadUrl(
// urlRequest: URLRequest(
// url: Uri.parse(_consts.successDirectUrl +
// "email=${_user.userEmail}&password=${_user.userPassword}")));
});*/
}
});
}
},
onWindowFocus: (controller) async {
var currentUrl = await controller.getUrl();
final html = await controller.getHtml();
var document = parse(html);
if (currentUrl != _currentUrl) {
Future.delayed(Duration.zero, () async {
var htmlCode = await controller.getHtml();
var document = parse(htmlCode);
var currentUrl = await controller.getUrl();
print("currentUrl = ${currentUrl}");
if (document.body!.innerHtml.contains("username@example.com")) {
print("get email");
await consts.user.clearStorage();
// get entered email address
getUserEmail(controller, document.body!.innerHtml);
} else if (document.body!.innerHtml.contains("Root user sign in")) {
print("get pass");
// get entered password
getUserPassword(controller, document.body!.innerHtml);
} else if (currentUrl
.toString()
.contains("https://portal.aws.amazon.com/billing/signup")) {
if (document.body!.innerHtml.contains("AWS account name")) {
print("sign up");
// get signUp email
getSignUpEmail(controller);
// get signUp password
getSignUpPassword(controller);
// get signUp account name
getSignUpAccountName(controller);
} else if (document.body!.innerHtml
.contains("Contact Information")) {
// get full name
getSignUpFullname(controller);
// get phone number
getSignUpPhoneNumber(controller);
// get region
getSignUpRegion(controller);
// get address
getSignUpAddress(controller);
// get city
getSignUpCity(controller);
// get state
getSignUpState(controller);
// get postal code
getSignUpPostalCode(controller);
// get organization
getSignUpOrganization(controller);
}
}
});
}
_currentUrl = currentUrl.toString();
//controller.goBack();
},
onProgressChanged:
(InAppWebViewController controller, int progress) async {
setState(() {
this.progress = progress / 100;
print("progress = ${this.progress}");
});
if (progress == 100) {
var currentUrl = await controller.getUrl();
Future.delayed(Duration(microseconds: 3), () async {
var htmlCode = await controller.getHtml();
var document = parse(htmlCode);
print("currentUrl progress = ${currentUrl.toString()}");
//print("html = ${document.body!.innerHtml}");
if (document.body!.innerHtml
.contains("Email address of your AWS account")) {
print("get email");
await consts.user.clearStorage();
consts.user.userEmail = "";
consts.user.userPassword = "";
controller.evaluateJavascript(source: """
document.querySelector("#new_account_container").style.display = "none";
""");
setState(() {});
// get entered email address
getUserEmail(controller, document.body!.innerHtml);
} else if (document.body!.innerHtml.contains("Root user sign in")) {
print("get pass");
// get entered password
getUserPassword(controller, document.body!.innerHtml);
} else if (currentUrl
.toString()
.contains("https://portal.aws.amazon.com/billing/signup#/")) {
if (document.body!.innerHtml.contains("AWS account name")) {
print("sign up progress");
// get signUp email
getSignUpEmail(controller);
// get signUp password
getSignUpPassword(controller);
// get signUp account name
getSignUpAccountName(controller);
} else if (document.body!.innerHtml
.contains("Contact Information")) {
// get full name
getSignUpFullname(controller);
// get phone number
getSignUpPhoneNumber(controller);
// get region
getSignUpRegion(controller);
// get address
getSignUpAddress(controller);
// get city
getSignUpCity(controller);
// get state
getSignUpState(controller);
// get postal code
getSignUpPostalCode(controller);
// get organization
getSignUpOrganization(controller);
}
}
if (currentUrl.toString() ==
"https://console.aws.amazon.com/iam/home#/users" ||
currentUrl.toString() ==
"https://console.aws.amazon.com/iam/home?#/users") {
print("delete credentials");
// delete user data if loged out
deleteCredentials(controller);
}
});
}
},
);
}
// get user amil
getUserEmail(InAppWebViewController controller, String html) {
controller.addJavaScriptHandler(
handlerName: 'EmailGetter',
callback: (args) {
// print arguments coming from the JavaScript side!
print("email args = $args");
// return data to the JavaScript side!
return args;
});
controller.evaluateJavascript(source: """
document.querySelector("#next_button").addEventListener("click", function(ee) {
window.console.log(JSON.stringify({"email": document.querySelector("#resolving_input").value}));});
""");
}
// getting password
getUserPassword(InAppWebViewController controller, String html) {
controller.evaluateJavascript(source: """
document.querySelector("#signin_button").addEventListener("click", function(ee) {
window.console.log(JSON.stringify({"password": document.querySelector("#password").value}));});
""");
}
// getting SignUp Email address
getSignUpEmail(InAppWebViewController controller) {
controller.evaluateJavascript(source: """
document.querySelector("#CredentialCollection").addEventListener("submit", function(ee) {
window.console.log(JSON.stringify({"sEmail": document.querySelector("input[name='email']").value}));});
""");
}
// getting SignUp password
getSignUpPassword(InAppWebViewController controller) {
controller.evaluateJavascript(source: """
document.querySelector("#CredentialCollection").addEventListener("submit", function(ee) {
window.console.log(JSON.stringify({"sPassword": document.querySelector("input[name='password']").value}));});
""");
}
// getting SignUp account name
getSignUpAccountName(InAppWebViewController controller) {
controller.evaluateJavascript(source: """
document.querySelector("#CredentialCollection").addEventListener("submit", function(ee) {
window.console.log(JSON.stringify({"sAccountName": document.querySelector("input[name='accountName']").value}));});
""");
}
// getting SignUp fullName
getSignUpFullname(InAppWebViewController controller) {
controller.evaluateJavascript(source: """
document.querySelector("#ContactInformation").addEventListener("submit", function(ee) {
window.console.log(JSON.stringify({"sFullName": document.querySelector("input[name='address.fullName']").value}));});
""");
}
// getting SignUp phone number
getSignUpPhoneNumber(InAppWebViewController controller) {
controller.evaluateJavascript(source: """
document.querySelector("#ContactInformation").addEventListener("submit", function(ee) {
window.console.log(JSON.stringify({"sPhone": document.querySelector("input[name='address.phoneNumber']").value}));});
""");
}
// getting SignUp region
getSignUpRegion(InAppWebViewController controller) {
controller.evaluateJavascript(source: """
document.querySelector("#ContactInformation").addEventListener("submit", function(ee) {
window.console.log(JSON.stringify({"sRegion": document.querySelectorAll(".awsui-select-trigger-label")[1].innerText}));});
""");
}
// getting SignUp address
getSignUpAddress(InAppWebViewController controller) {
controller.evaluateJavascript(source: """
document.querySelector("#ContactInformation").addEventListener("submit", function(ee) {
window.console.log(JSON.stringify({"sAddress": document.querySelectorAll("input[name='address.addressLine1']").value}));});
""");
}
// getting SignUp city
getSignUpCity(InAppWebViewController controller) {
controller.evaluateJavascript(source: """
document.querySelector("#ContactInformation").addEventListener("submit", function(ee) {
window.console.log(JSON.stringify({"sCity": document.querySelectorAll("input[name='address.city']").value}));});
""");
}
// getting SignUp state
getSignUpState(InAppWebViewController controller) {
controller.evaluateJavascript(source: """
document.querySelector("#ContactInformation").addEventListener("submit", function(ee) {
window.console.log(JSON.stringify({"sState": document.querySelectorAll("input[name='address.state']").value}));});
""");
}
// getting SignUp postal code
getSignUpPostalCode(controller) {
controller.evaluateJavascript(source: """
document.querySelector("#ContactInformation").addEventListener("submit", function(ee) {
window.console.log(JSON.stringify({"sPostal": document.querySelectorAll("input[name='address.postalCode']").value}));});
""");
}
// getting SignUp organization
getSignUpOrganization(InAppWebViewController controller) {
controller.evaluateJavascript(source: """
document.querySelector("#ContactInformation").addEventListener("submit", function(ee) {
window.console.log(JSON.stringify({"sOrganize": document.querySelectorAll("input[name='address.company']").value}));});
""");
}
// deleting user credentials
deleteCredentials(InAppWebViewController controller) {
controller.evaluateJavascript(source: """
document.querySelector("#aws-console-logout").addEventListener("click", function(ee) {
window.console.log(JSON.stringify({"delete": "delete"}));});
""");
}
_backButton(BuildContext context) {
return ElevatedButton(
onPressed: () {
Navigator.pop(context);
},
child: Icon(Icons.arrow_back),
);
}
}
答案 10 :(得分:-1)
解压缩apk包,我发现原因:路径错误;
对于Android:
"assets/test.html" == "file:///android_asset/flutter_assets/assets/test.html"
所以,就像这样:
WebView(
initialUrl: "file:///android_asset/flutter_assets/assets/test.html",
javascriptMode: JavascriptMode.unrestricted,
)
您可以加载“ assets / test.html”。