flutterflutter-webdart-htmldart-webui

WebView support for FlutterWeb for plugin development


Hi I developed a Flutter Plugin flutter_tex. It's based on the WebView. How do I add Flutter Web support for this??

I tried this example to show my HTML content.

import 'dart:ui' as ui;

  void forWeb() {
    if(kIsWeb){
      // ignore: undefined_prefixed_name
      ui.platformViewRegistry.registerViewFactory(
          'hello-world-html',
              (int viewId) => uni_html.IFrameElement()
            ..width = '640'
            ..height = '360'
            ..src = 'https://www.youtube.com/embed/IyFZznAk69U'
            ..style.border = 'none');

      Directionality(
        textDirection: TextDirection.ltr,
        child: Center(
          child: SizedBox(
            width: 200,
            height: 200,
            child: HtmlElementView(viewType: 'hello-world-html'),
          ),
        ),
      );
    }
  }

But this code is fine when building for the web but when for compiling on android I get this error even if I am not calling above code.

Compiler message:
../lib/flutter_tex.dart:139:10: Error: Getter not found: 'platformViewRegistry'.
      ui.platformViewRegistry.registerViewFactory(
         ^^^^^^^^^^^^^^^^^^^^
Target kernel_snapshot failed: Exception: Errors during snapshot creation: null
build failed.

FAILURE: Build failed with an exception.

Solution

  • You can copy paste run 3 files below main.dart , mobileui.dart and webui.dart
    You can put mobile and web code in different files and use conditional import
    This allow you to have different implement on mobile and web

    import 'mobileui.dart' if (dart.library.html) 'webui.dart' as multiPlatform;
    ...
    home:  multiPlatform.TestPlugin(),
    

    working demo
    when run with Chrome or Android Emulator in Android Studio

    enter image description here enter image description here

    main.dart

    import 'package:flutter/material.dart';
    import 'mobileui.dart' if (dart.library.html) 'webui.dart' as multiPlatform;
    
    void main() => runApp(MyApp());
    
    class MyApp extends StatelessWidget { 
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Flutter Demo',
          theme: ThemeData(        
            primarySwatch: Colors.blue,
          ),
          home:  multiPlatform.TestPlugin(),
        );
      }
    }
    

    mobileui.dart

    import 'package:flutter/material.dart';
    
    class TestPlugin extends StatefulWidget {
      @override
      _TestPluginState createState() => _TestPluginState();
    }
    
    class _TestPluginState extends State<TestPlugin> {
      @override
      Widget build(BuildContext context) {
        return Text("Mobile");
      }
    }
    

    webui.dart

    import 'package:flutter/material.dart';
    import 'dart:html' as html;
    import 'dart:js' as js;
    import 'dart:ui' as ui;
    
    
    class TestPlugin extends StatefulWidget {
      TestPlugin();
    
      _TestPluginState createState() => _TestPluginState();
    }
    
    class _TestPluginState extends State<TestPlugin> {
      String createdViewId = 'map_element';
    
      @override
      void initState() {
        // ignore: undefined_prefixed_name
        ui.platformViewRegistry.registerViewFactory(
            createdViewId,
                (int viewId) => html.IFrameElement()
              ..width = MediaQuery.of(context).size.width.toString() //'800'
              ..height = MediaQuery.of(context).size.height.toString() //'400'
              ..srcdoc = """<!DOCTYPE html><html>
              <head><title>Page Title</title></head><body><h1>This is a Heading</h1><p>This is a paragraph.</p></body></html>"""            
              ..style.border = 'none');
    
        super.initState();
      }
    
      @override
      void dispose() {
        super.dispose();
      }
    
      @override
      Widget build(BuildContext context) {
        return Container(
            padding: EdgeInsets.symmetric(horizontal: 10),
            decoration: BoxDecoration(
                color: Colors.white,
                border: Border.all(color: Colors.grey[300], width: 1),
                borderRadius: BorderRadius.all(Radius.circular(5))),
            width: 200,
            height: 200,
            child: Directionality(
                textDirection: TextDirection.ltr,
                child: HtmlElementView(
                  viewType: createdViewId,
                )));
      }
    }