“This is the first day of my participation in the First Challenge 2022. For details: First Challenge 2022”

The webview_flutter plugin is available for loading HTML pages. There are many tutorials on how to load HTML pages using this WebView control, but there are relatively few references to loading HTML strings. This article explains how to load HTML strings using the WebView provided by the webview_FLUTTER plugin.

Usage scenarios

When do you use a WebView to load AN HTML string in your development? Here is an example of a requirement that the author met in a real project. The content submitted by the PC side using a rich text editor needs to be displayed in the App, because the server side stores/returns a paragraph of HTML string to the App. At this point, the App needs to use the WebView to load and display the HTML string content.

The WebView loads the Html string

Add the dependent

Add webview_flutter dependencies to your project’s pubspec.yaml file:

dependencies:
  webview_flutter: ^ 3.0.0
Copy the code

Loading HTML Strings

Import package webview_flutter:

import 'package:webview_flutter/webview_flutter.dart';
Copy the code

Then create a WebView object when you use it.

The WebView construction parameter has an initialUrl parameter, which can be passed in a URL to load an HTML page, as follows:

WebView(
  initialUrl: "https://juejin.cn",
  javascriptMode: JavascriptMode.unrestricted,
)
Copy the code

InitialUrl incoming Denver’s address, and then sets the javascriptMode to javascriptMode. Unrestricted open js, because a web page using the js if not open leads to incomplete page load. The operation effect is shown as follows:

However, there is no HTML string loading parameter in the WebView constructor, so you cannot directly load the HTML string when creating the WebView. You need to use the WebViewController to load the HTML string.

The WebViewController provides a loadHtmlString or loadUrl method to load an HTML string. The WebViewController needs to get it through the WebView onWebViewCreated callback, As follows:

WebView(
  javascriptMode: JavascriptMode.unrestricted,
  onWebViewCreated: (WebViewController controller){
    // Get the WebViewController},)Copy the code

loadHtmlString

Load the HTML string with the loadHtmlString method of the WebViewController, passing in the HTML string as follows:

String html = 

Hello WebView

""
; WebView( javascriptMode: JavascriptMode.unrestricted, onWebViewCreated: (WebViewController controller){ controller.loadHtmlString(html); },)Copy the code

The effect is as follows:

The content did load, but the text was very small,
> otherwise the default font will be very small. Modified as follows:

  String html = "" "
        
       < / head > < body > < p > Hello WebView Denver < / p > < / body > < / HTML >" "";
Copy the code

The effect is as follows:

In addition, loadHtmlString also has an optional parameter baseUrl, which is used when a relative path URL is used in the HTML string. After setting baseUrl, the WebView will bring baseUrl when loading HTML and requesting the corresponding URL. For example, if there is a display image in the HTML string and the image address is a relative path, the baseUrl parameter can be used to solve the problem as follows:

 String html = "" "
        
         """;

WebView(
  javascriptMode: JavascriptMode.unrestricted,
  onWebViewCreated: (WebViewController controller){
    controller.loadHtmlString(html, baseUrl: "https://lf3-cdn-tos.bytescm.com"); },)Copy the code

The effect is as follows:

Here, the rare-earth logo is loaded in this way. The image address in the HTML string is not a complete address and will fail to load if baseUrl is not set.

loadUrl

In addition to using loadHtmlString, you can also use loadUrl to load HTML strings. You can also use loadUrl to load HTML strings. It does work, but it needs to be converted via uri.dataFromString. As follows:

WebView(
  javascriptMode: JavascriptMode.unrestricted,
  onWebViewCreated: (WebViewController controller){
    controller.loadUrl(Uri.dataFromString(html, mimeType: "text/html", encoding: utf8,).toString()); },)Copy the code

The uri. dataFromString conversion can also be used to load HTML strings. Note that uri. dataFromString is not an HTML string argument. You also need to set mimeType to “text/ HTML “and encoding to UTF8. If encoding is not set, an error may be reported when loading, and if mimeType is not set, the HTML code is loaded directly.

WebView is highly adaptive

By default, WebView cannot be height adaptive, that is, according to the height of the HTML content. If you use WebView in a control such as Column without manually setting a fixed height, an error will be reported.

If you want to achieve height adaptation, you need to use the JS method to monitor the change of page size in HTML through JS, and then obtain the height of the page and transfer the height to the Flutter. After obtaining the height in the Flutter, you can dynamically change the height of the WebView.

The implementation steps are as follows:

  • Add one to the WebViewJavascriptChannelUsed for JS to communicate with Flutter
  • Add in HTMLscriptuseResizeObserverListening to thebodyElement changes in size, called in the change callback from the previous additionJavascriptChannelSend a page height message
  • When a message is received in a Flutter, get the height of the js message and update the height of the WebView

The code is as follows:

  String html = "" "
        
          "" ";

SizedBox(
  height: webViewHeight,
  child: WebView(
    javascriptMode: JavascriptMode.unrestricted,
    onWebViewCreated: (WebViewController controller){
      controller.loadHtmlString(html, baseUrl: "https://lf3-cdn-tos.bytescm.com");
    },
    javascriptChannels: {
      JavascriptChannel(name: "Resize", onMessageReceived: (JavascriptMessage message) {
        double height = double.parse(message.message); setState(() { webViewHeight = height; }); })}),)Copy the code

As shown above, we put a SizeBox on the WebView to limit the height of the WebView, Meanwhile, JavascriptChannel named Resize is added to WebView, script is added to HTML string, and JS ResizeObserver is used to monitor the size changes of page elements. Get the scrollHeight of the element in the change callback and send it to Flutter, get the height of the element in the JavascriptChannel message callback of the Flutter and update the SizeBox height. In this way, the height of WebView is self-adaptive.

The complete code

class WebViewPage extends StatefulWidget {
  const WebViewPage({Key? key}) : super(key: key);

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

class _WebViewPageState extends State<WebViewPage> {

  double webViewHeight = 0;
  String html = "" "
        
          """;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text("WebView"),),
      body: SizedBox(
        height: webViewHeight,
        child: WebView(
          javascriptMode: JavascriptMode.unrestricted,
          onWebViewCreated: (WebViewController controller){
            controller.loadHtmlString(html, baseUrl: "https://lf3-cdn-tos.bytescm.com");
          },
          javascriptChannels: {
            JavascriptChannel(name: "Resize", onMessageReceived: (JavascriptMessage message) {
              double height = double.parse(message.message); setState(() { webViewHeight = height; }); })}),),); }}Copy the code