Flutter 使用 flutter
在 Flutter 开发中,加载本地 HTML 文件是一个常见的需求,尤其是在需要展示离线内容或自定义页面时。flutter_inappwebview 是一个功能强大的插件,支持加载本地文件和网络资源。本文将详细介绍如何使用 flutter_inappwebview 加载 App 本地 HTML 文件,包括传统加载资源文件的方法和从 App 目录加载文件的方法。
一、传统加载资源文件
- HTML 文件放置
首先,将 .html 文件拖入工程中。通常,我会将文件放在工程的根目录下,与 pubspec.yaml 同级。
然后,打开 pubspec.yaml 文件,在 assets: 下添加该文件,例如:
flutter: assets: - membership_agreement.html
- 加载本地 HTML 文件
接下来,使用 rootBundle 读取文件内容,并通过 InAppWebView 加载 HTML 数据。
dart复制
import 'package:flutter/material.dart'; import 'package:flutter/services.dart' show rootBundle; import 'package:flutter_inappwebview/flutter_inappwebview.dart'; class LocalHtmlPage extends StatefulWidget { final String html; LocalHtmlPage({required this.html}); @override _LocalHtmlPageState createState() => _LocalHtmlPageState(); } class _LocalHtmlPageState extends State { late InAppWebViewController _webViewController; Future _getFile() async { return await rootBundle.loadString(widget.html); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text("加载本地 HTML 文件")), body: FutureBuilder( future: _getFile(), builder: (context, snapshot) { if (snapshot.hasData) { final String htmlUrl = Uri.dataFromString( snapshot.data!, mimeType: 'text/html', encoding: Encoding.getByName('utf-8'), base64: true, ).toString(); return InAppWebView( initialUrlRequest: URLRequest(url: Uri.parse(htmlUrl)), onWebViewCreated: (controller) { _webViewController = controller; }, onLoadStart: (controller, url) { print('开始加载: $url'); }, onLoadStop: (controller, url) { print('加载完毕: $url'); }, onConsoleMessage: (controller, consoleMessage) { print('Console message: ${consoleMessage.message}'); }, ); } return Center(child: Text('读取失败')); }, ), ); } }
二、加载 App 目录文件
- 需求背景
在某些场景下,HTML 文件可能需要先下载到 App 的本地目录,然后再从目录中加载。例如,从网络下载 HTML 文件并保存到本地缓存目录。
- 核心代码
以下是使用 flutter_inappwebview 加载 App 目录中的 HTML 文件的完整代码示例:
import 'dart:io'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_inappwebview/flutter_inappwebview.dart'; import 'package:path_provider/path_provider.dart'; class LocalHtmlPage extends StatefulWidget { final String htmlFileName; LocalHtmlPage({required this.htmlFileName}); @override _LocalHtmlPageState createState() => _LocalHtmlPageState(); } class _LocalHtmlPageState extends State { late InAppWebViewController _webViewController; Future getLocalHtmlFile() async { final directory = await getApplicationDocumentsDirectory(); final filePath = "${directory.path}/${widget.htmlFileName}"; final file = File(filePath); if (await file.exists()) { return file; } return null; } Future load() async { try { final file = await getLocalHtmlFile(); if (file != null) { print('加载本地 HTML 文件: file://${file.path}'); _webViewController.loadUrl( urlRequest: URLRequest(url: Uri.file(file.path)), ); } else { print('文件不存在'); } } catch (e, stackTrace) { print('加载本地 HTML 文件异常: $e'); print(stackTrace); } } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text("加载本地 HTML 文件")), body: InAppWebView( onWebViewCreated: (controller) { _webViewController = controller; load(); }, onLoadStart: (controller, url) { print('开始加载: $url'); }, onLoadStop: (controller, url) { print('加载完毕: $url'); }, onProgressChanged: (controller, progress) { print('WebView 加载中 (进度: $progress%)'); }, onConsoleMessage: (controller, consoleMessage) { print('Console message: ${consoleMessage.message}'); }, gestureRecognizers: { Factory(() => EagerGestureRecognizer()), }.toSet(), ), ); } }
三、注意事项
文件路径问题:
确保文件路径正确,并且文件确实存在于指定路径下。
如果文件路径是动态生成的,确保路径格式正确。
文件内容问题:
确保 HTML 文件内容是有效的,且没有语法错误。
可以在浏览器中直接打开该 HTML 文件,确认其是否正常显示。
iOS 网络权限:
如果加载的文件路径是 file://,确保 iOS 的网络权限配置正确。在 Info.plist 中添加以下配置:
NSAppTransportSecurity NSAllowsArbitraryLoads
日志输出:
如果需要关闭日志输出,可以在 Dart 代码中过滤日志消息,或在 iOS 和 Android 项目中配置日志级别。
通过以上方法,你可以灵活地使用 flutter_inappwebview 加载本地 HTML 文件,无论是通过资源文件还是从 App 目录加载。希望本文能帮助你更好地实现这一功能。