【问题标题】:Dart: Load an html file into a Flutter WebviewDart:将 html 文件加载到 Flutter Webview 中
【发布时间】:2019-05-11 16:28:24
【问题描述】:

Sthg 让我抓狂,我尝试使用带有 dart:io 库的 path_provider 插件在磁盘上编写一个 html 文件。

这是我尝试过的(OKAY):

Future<File> writeFile() async {
   final file = await _localFile;
   return file.writeAsString('<!DOCTYPE html><html lang="fr"> <head> <meta charset="UTF-8"> <title>test_design</title> ...');
 }

然后将文件加载到 webview 中:OKAY

但如果我尝试使用更长的 html 文件,它就不再起作用了,例如:

return file.writeAsString(' html file containing js ');

有什么想法吗?

或者如何在 Flutter webview 中加载 html 文件(文件不是静态的)?


我使用 flutter_webview_plugin.dart

(https://pub.dartlang.org/packages/flutter_webview_plugin)

网页浏览代码:

         writeFile().then((file){
            readFile().then((r){
               _localPath.then((path){
                    var uri='file:///'+path+'/index.html';

                    flutterWebViewPlugin.launch(uri,
                        rect: new Rect.fromLTWH(
                          0.0,
                          400.0,
                          MediaQuery.of(context).size.width,
                          200.0,
                        ),
                      );

【问题讨论】:

标签: javascript android dart flutter


【解决方案1】:

IMO,这是解决这个问题的方法:

这是一个示例方法,我将构建一个 Flutter 应用程序,它可以读取文件并将数据写入文件以供以后使用。

这是一个可以将字符串写入 text.txt 文件的应用程序。每次启动应用程序时,它都会显示 text.txt 的内容。

我需要一个地方在磁盘上写入数据并在应用加载时再次读取它。所以我使用path_provider插件访问Documents目录(iOS上对应NSDocumentDirectory,Android上是AppData目录)。

Future<String> get _localPath async {
  final directory = await getApplicationDocumentsDirectory();
  return directory.path;
}

创建对文件完整位置的引用(在我们的例子中是 text.txt 文件),我们使用来自 dart:io 库的 File 类。

Future<File> get _localFile async {
  final path = await _localPath;
  return File('$path/text.txt');
}

需要使用 File writeAsString() 方法将字符串写入文件。它返回一个Future&lt;File&gt;,一旦整个操作完成,这个 File 对象就完成了。

默认情况下,writeAsString() 创建文件并在文件已存在时将其截断。

要将数据附加到现有文件,请将FileMode.append 模式作为第二个参数传递。

Future<File> writeFile(String text) async {
  final file = await _localFile;
  return file.writeAsString('$text\r\n', mode: FileMode.append);
}

使用 File readAsString() 方法将整个内容作为字符串读取。它返回一个Future&lt;String&gt;,一旦内容被读取,就会以字符串结尾。

Future<String> readFile() async {
  try {
    final file = await _localFile;
 
    String content = await file.readAsString();
    return content;
  } catch (e) {
    return '';
  }
}

这是完整的示例代码:

import 'package:flutter/material.dart';
import 'package:path_provider/path_provider.dart';
import 'dart:async';
import 'dart:io';

void main() {
  runApp(
    MaterialApp(
      title: 'Read/Write Files',
      home: MyApp(storage: TextStorage()),
    ),
  );
}

class TextStorage {
  Future<String> get _localPath async {
    final directory = await getApplicationDocumentsDirectory();
    return directory.path;
  }

  Future<File> get _localFile async {
    final path = await _localPath;
    return File('$path/text.txt');
  }

  Future<String> readFile() async {
    try {
      final file = await _localFile;

      String content = await file.readAsString();
      return content;
    } catch (e) {
      return '';
    }
  }

  Future<File> writeFile(String text) async {
    final file = await _localFile;
    return file.writeAsString('$text\r\n', mode: FileMode.append);
  }

  Future<File> cleanFile() async {
    final file = await _localFile;
    return file.writeAsString('');
  }
}

class MyApp extends StatefulWidget {
  final TextStorage storage;

  MyApp({Key key, @required this.storage}) : super(key: key);

  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  TextEditingController _textField = new TextEditingController();

  String _content = '';

  @override
  void initState() {
    super.initState();
    widget.storage.readFile().then((String text) {
      setState(() {
        _content = text;
      });
    });
  }

  Future<File> _writeStringToTextFile(String text) async {
    setState(() {
      _content += text + '\r\n';
    });

    return widget.storage.writeFile(text);
  }

  Future<File> _clearContentsInTextFile() async {
    setState(() {
      _content = '';
    });

    return widget.storage.cleanFile();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Read/Write File Example'),
        backgroundColor: Colors.blue,
      ),
      body: Container(
        padding: EdgeInsets.all(20.0),
        child: Column(
          children: <Widget>[
            TextField(
              controller: _textField,
            ),
            Padding(
              padding: EdgeInsets.all(20.0),
              child: RaisedButton(
                child: Text('Write to File'),
                color: Colors.lightBlueAccent,
                onPressed: () {
                  if (_textField.text.isNotEmpty) {
                    _writeStringToTextFile(_textField.text);
                    _textField.clear();
                  }
                },
              ),
            ),
            Padding(
              padding: EdgeInsets.only(bottom: 20.0),
              child: RaisedButton(
                child: Text(
                  'Clear Contents',
                  style: TextStyle(color: Colors.white),
                ),
                color: Colors.grey,
                onPressed: () {
                  _clearContentsInTextFile();
                },
              ),
            ),
            Expanded(
              flex: 1,
              child: new SingleChildScrollView(
                child: Text(
                  '$_content',
                  style: TextStyle(
                    color: Colors.blue,
                    fontSize: 22.0,
                  ),
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

这是运行时的样子:

你可以根据你的要求来玩。

还有关于如何在 Flutter webview 中加载 html 文件的其他问题,这是我的方法:

您实际上可以使用webview_flutter 插件使其工作。

在你的 Flutter 应用的根目录下创建一个 assets 文件夹,然后将你的 .html 文件放到 assets 文件夹中。

您应该将您的 .html 文件添加到 pubspec.yaml 文件中的 assets 下。

pubspec.yaml

  assets:
    - assets/SampleHtml.html

这是从本地文件加载 html 的示例实现:

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:webview_flutter/webview_flutter.dart';
import 'dart:async';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  Future<String> localLoader() async {
    return await rootBundle.loadString('assets/SampleHtml.html');
  }

  @override
  Widget build(BuildContext context) {
    return FutureBuilder<String>(
        future: localLoader(),
        builder: (context, snapshot) {
          if (snapshot.hasData) {
            return WebView(
              initialUrl:
                  new Uri.dataFromString(snapshot.data, mimeType: 'text/html')
                      .toString(),
              javascriptMode: JavascriptMode.unrestricted,
            );
          } else if (snapshot.hasError) {
            return Text("${snapshot.error}");
          }
          return CircularProgressIndicator();
        });
  }
}

SampleHtml.html

<!DOCTYPE html>
<meta charset="utf-8">
<title>Sample HTML</title>
<html>
    <head>
        <link rel="stylesheet">
    </head>
    <body>
        <h1>Flutter Webview</h1>
        <p>A Flutter plugin that provides a WebView widget.</p>
        <ul>
            <li>List 1</li>
            <li>List 2</li>
            <li>List 3</li>
        </ul>
    </body>
</html>

看起来是这样的:

【讨论】:

    猜你喜欢
    • 2011-08-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-18
    • 1970-01-01
    • 2020-09-01
    相关资源
    最近更新 更多