Flutter:从WebView加载IFrame

时间:2019-01-31 16:17:33

标签: android webview flutter

我正在寻找一种从Flutter WebView加载iFrame的方法(webview_flutter:^ 0.1.2),并且找不到任何相关信息。

                 Container(
                    child: WebView(
                      initialUrl: 'https://www.youtube.com/embed/abc',
                      javaScriptMode: JavaScriptMode.unrestricted,
                    )),

有任何想法如何将IFrame传递给Webview,它会作为initialUrl的一部分吗?我已经尝试过相同的方法,但是加载不正确。

3 个答案:

答案 0 :(得分:1)

这可能会做您想要的

 Container(
    child: WebView(
      initialUrl: Uri.dataFromString('<html><body><iframe src="https://www.youtube.com/embed/abc"></iframe></body></html>', mimeType: 'text/html').toString(),
      javaScriptMode: JavaScriptMode.unrestricted,
    )),

这将传递数据URL,该数据URL包含带有iframe的HTML页面。

答案 1 :(得分:1)

基于上述@Günter,我进行了一些细微的调整,因为我无法在iOS上使用它。这基于webview_flutter官方pub.dev页面。

String html = """<!DOCTYPE html>
          <html>
            <head>
            <style>
            body {
              overflow: hidden; 
            }
        .embed-youtube {
            position: relative;
            padding-bottom: 56.25%; 
            padding-top: 0px;
            height: 0;
            overflow: hidden;
        }

        .embed-youtube iframe,
        .embed-youtube object,
        .embed-youtube embed {
            border: 0;
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
        }
        </style>

        <meta charset="UTF-8">
         <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
          <meta http-equiv="X-UA-Compatible" content="ie=edge">
           </head>
          <body bgcolor="#121212">                                    
        <div class="embed-youtube">
         <iframe
          id="vjs_video_3_Youtube_api"
          style="width:100%;height:100%;top:0;left:0;position:absolute;"
          class="vjs-tech holds-the-iframe"
          frameborder="0"
          allowfullscreen="1"
          allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture"
          webkitallowfullscreen mozallowfullscreen allowfullscreen
          title="Live Tv"
          frameborder="0"
          src="$iframeUrl"
          ></iframe></div>
          </body>                                    
        </html>
  """;
final Completer<WebViewController> _controller =
    Completer<WebViewController>();
final String contentBase64 =
    base64Encode(const Utf8Encoder().convert(html));
return WebView(
  initialUrl: 'data:text/html;base64,$contentBase64',
  javascriptMode: JavascriptMode.unrestricted,
  onWebViewCreated: (WebViewController webViewController) {
    _controller.complete(webViewController);
  },
  onPageStarted: (String url) {
    print('Page started loading: $url');
  },
  onPageFinished: (String url) {
    print('Page finished loading: $url');
  },
  gestureNavigationEnabled: true,
);

然后我使用@Lorenzo Pichilli答案在android上进行了操作。我为我工作更快。希望这对任何人都有帮助。花了我一整天。

PS

这使我能够在Android和iOS上播放youtube和vimeo视频。到目前为止一切正常

编辑:

要在Webview完成加载之前添加加载器,请查看此question,了解如何添加进度通知指示器

答案 2 :(得分:0)

您还可以使用我的插件flutter_inappwebview,它是Flutter插件,允许您添加内联WebView或打开应用程序内浏览器窗口,并具有许多事件,方法和选项来控制WebView。

要在WebView中加载iFrame,您可以使用initialData小部件的InAppWebView参数直接加载HTML源。

完整示例:

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;
  String iframeUrl = "https://www.youtube.com/embed/sPW7nDBqt8w";

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
            title: Text("InAppWebView")
        ),
        body: Container(
            child: Column(children: <Widget>[
              Expanded(
                child: Container(
                  child: InAppWebView(
                    initialData: InAppWebViewInitialData(
                        data: """
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>Flutter InAppWebView</title>
    </head>
    <body>
        <iframe src="$iframeUrl" width="100%" height="100%" frameborder="0" allowfullscreen></iframe>
    </body>
</html>"""
                    ),
                    initialHeaders: {},
                    initialOptions: InAppWebViewWidgetOptions(
                      inAppWebViewOptions: InAppWebViewOptions(
                        debuggingEnabled: true,
                      ),
                    ),
                    onWebViewCreated: (InAppWebViewController controller) {
                      webView = controller;
                    },
                    onLoadStart: (InAppWebViewController controller, String url) {

                    },
                    onLoadStop: (InAppWebViewController controller, String url) {

                    },
                  ),
                ),
              ),
            ]))
    );
  }
}

或从资产文件夹中加载HTML文件(请参阅更多here)并使用initialFile参数:

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) {

                    },
                  ),
                ),
              ),
            ]))
    );
  }
}

其中index.html文件包含<iframe>标记。