【flutter】特别篇:flutter嵌入h5页面

博客学习

学习的博客地址

  1. 主要是通过webViewScaffold来进行页面的渲染
  2. 属性有:
    1. url,页面跳转的url
    2. appBar,页面的头表
    3. initialChild:还没有加载出来的时候显示的页面
    4. hidden:如果设置为true,将会出现默认的“转圈圈图标”
import 'package:flutter/material.dart';
import 'package:flutter_webview_plugin/flutter_webview_plugin.dart';

/// WebView使用flutter_webview_plugin插件
/// https://pub.dev/packages/flutter_webview_plugin
// 此dart在真机上可以正常运行,但是虚拟机没法联网就不能运行,为什么不能联网这个问题还没有解决
class EmbeddH5 extends StatefulWidget {
  String title = "百度";
  String url = "https://www.baidu.com";

  @override
  _EmbeddH5State createState() =>_EmbeddH5State(title: title, url: url);
}

class _EmbeddH5State extends State<EmbeddH5> {
  String url;
  String title;
  _EmbeddH5State({required this.url, required this.title});
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      ///隐藏Debug标志
      debugShowCheckedModeBanner: false,
      home: Scaffold(
          body: Container(
            child: WebviewScaffold(
              url: url,
              appBar: AppBar(
                title: Text(title),
              ),
              //当WebView没加载出来前显示
              initialChild: Container(
                color: Colors.white,
                child: Center(
                  child: Text("正在加载中...."),
                ),
              ),
            ),
          )),
    );
  }
}

调用该怎么调用呢?下面这样再main.dart中调用就行

WidgetsFlutterBinding.ensureInitialized();
runApp(EmbeddH5('百度','https://www.baidu.com'));

Flutter中所有的运转都是在各种Binding中调度的,也正是这些绑定器的存在彻底解耦了Widget、 Element 、RenderObject 对 Platform端的依赖
【flutter】特别篇:flutter嵌入h5页面_第1张图片

官方学习

官方文档

  1. webView加载出来的页面在最顶部,没有其他的flutter widget能覆盖
    官方代码如下:
import 'dart:async';

import 'package:flutter/material.dart';

import 'package:flutter_webview_plugin/flutter_webview_plugin.dart';

const kAndroidUserAgent =
    'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Mobile Safari/537.36';

String selectedUrl = 'https://flutter.io';

// ignore: prefer_collection_literals
final Set<JavascriptChannel> jsChannels = [
  JavascriptChannel(
      name: 'Print',
      onMessageReceived: (JavascriptMessage message) {
        print(message.message);
      }),
].toSet();

class EmbeddH5OfficeDemo extends StatelessWidget {
  final flutterWebViewPlugin = FlutterWebviewPlugin();
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter WebView Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      routes: {
        '/': (_) => const MyHomePage(title: 'Flutter WebView Demo'),
        '/widget': (_) {
          return WebviewScaffold(
            url: selectedUrl,
            javascriptChannels: jsChannels,
            mediaPlaybackRequiresUserGesture: false,
            appBar: AppBar(
              title: const Text('Widget WebView'),
            ),
            withZoom: true,
            withLocalStorage: true,
            hidden: true,
            initialChild: Container(
              color: Colors.redAccent,
              child: const Center(
                child: Text('Waiting.....'),
              ),
            ),
            bottomNavigationBar: BottomAppBar(
              child: Row(
                children: <Widget>[
                  IconButton(
                    icon: const Icon(Icons.arrow_back_ios),
                    onPressed: () {
                      flutterWebViewPlugin.goBack();
                    },
                  ),
                  IconButton(
                    icon: const Icon(Icons.arrow_forward_ios),
                    onPressed: () {
                      flutterWebViewPlugin.goForward();
                    },
                  ),
                  IconButton(
                    icon: const Icon(Icons.autorenew),
                    onPressed: () {
                      flutterWebViewPlugin.reload();
                    },
                  ),
                ],
              ),
            ),
          );
        },
      },
    );
  }
}

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

  final String title;

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

class _MyHomePageState extends State<MyHomePage> {
  // Instance of WebView plugin
  final flutterWebViewPlugin = FlutterWebviewPlugin();

  // On destroy stream
  late StreamSubscription _onDestroy;

  // On urlChanged stream
  late StreamSubscription<String> _onUrlChanged;

  // On urlChanged stream
  late StreamSubscription<WebViewStateChanged> _onStateChanged;

  late StreamSubscription<WebViewHttpError> _onHttpError;

  late StreamSubscription<double> _onProgressChanged;

  late StreamSubscription<double> _onScrollYChanged;

  late StreamSubscription<double> _onScrollXChanged;

  final _urlCtrl = TextEditingController(text: selectedUrl);

  final _codeCtrl = TextEditingController(text: 'window.navigator.userAgent');

  final _scaffoldKey = GlobalKey<ScaffoldState>();

  final _history = [];

  @override
  void initState() {
    super.initState();

    flutterWebViewPlugin.close();

    _urlCtrl.addListener(() {
      selectedUrl = _urlCtrl.text;
    });

    // Add a listener to on destroy WebView, so you can make came actions.
    _onDestroy = flutterWebViewPlugin.onDestroy.listen((_) {
      if (mounted) {
        // Actions like show a info toast.
        ScaffoldMessenger.of(context)
            .showSnackBar(const SnackBar(content: Text('Webview Destroyed')));
      }
    });

    // Add a listener to on url changed
    _onUrlChanged = flutterWebViewPlugin.onUrlChanged.listen((String url) {
      if (mounted) {
        setState(() {
          _history.add('onUrlChanged: $url');
        });
      }
    });

    _onProgressChanged =
        flutterWebViewPlugin.onProgressChanged.listen((double progress) {
          if (mounted) {
            setState(() {
              _history.add('onProgressChanged: $progress');
            });
          }
        });

    _onScrollYChanged =
        flutterWebViewPlugin.onScrollYChanged.listen((double y) {
          if (mounted) {
            setState(() {
              _history.add('Scroll in Y Direction: $y');
            });
          }
        });

    _onScrollXChanged =
        flutterWebViewPlugin.onScrollXChanged.listen((double x) {
          if (mounted) {
            setState(() {
              _history.add('Scroll in X Direction: $x');
            });
          }
        });

    _onStateChanged =
        flutterWebViewPlugin.onStateChanged.listen((WebViewStateChanged state) {
          if (mounted) {
            setState(() {
              _history.add('onStateChanged: ${state.type} ${state.url}');
            });
          }
        });

    _onHttpError =
        flutterWebViewPlugin.onHttpError.listen((WebViewHttpError error) {
          if (mounted) {
            setState(() {
              _history.add('onHttpError: ${error.code} ${error.url}');
            });
          }
        });
  }

  @override
  void dispose() {
    // Every listener should be canceled, the same should be done with this stream.
    _onDestroy.cancel();
    _onUrlChanged.cancel();
    _onStateChanged.cancel();
    _onHttpError.cancel();
    _onProgressChanged.cancel();
    _onScrollXChanged.cancel();
    _onScrollYChanged.cancel();

    flutterWebViewPlugin.dispose();

    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      key: _scaffoldKey,
      appBar: AppBar(
        title: const Text('Plugin example app'),
      ),
      body: SingleChildScrollView(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Container(
              padding: const EdgeInsets.all(24.0),
              child: TextField(controller: _urlCtrl),
            ),
            ElevatedButton(
              onPressed: () {
                flutterWebViewPlugin.launch(
                  selectedUrl,
                  rect: Rect.fromLTWH(
                      0.0, 0.0, MediaQuery.of(context).size.width, 300.0),
                  userAgent: kAndroidUserAgent,
                  invalidUrlRegex:
                  r'^(https).+(twitter)', // prevent redirecting to twitter when user click on its icon in flutter website
                );
              },
              child: const Text('Open Webview (rect)'),
            ),
            ElevatedButton(
              onPressed: () {
                flutterWebViewPlugin.launch(selectedUrl, hidden: true);
              },
              child: const Text('Open "hidden" Webview'),
            ),
            ElevatedButton(
              onPressed: () {
                flutterWebViewPlugin.launch(selectedUrl);
              },
              child: const Text('Open Fullscreen Webview'),
            ),
            ElevatedButton(
              onPressed: () {
                Navigator.of(context).pushNamed('/widget');
              },
              child: const Text('Open widget webview'),
            ),
            Container(
              padding: const EdgeInsets.all(24.0),
              child: TextField(controller: _codeCtrl),
            ),
            ElevatedButton(
              onPressed: () {
                final future =
                flutterWebViewPlugin.evalJavascript(_codeCtrl.text);
                future.then((String? result) {
                  setState(() {
                    _history.add('eval: $result');
                  });
                });
              },
              child: const Text('Eval some javascript'),
            ),
            ElevatedButton(
              onPressed: () {
                final future = flutterWebViewPlugin
                    .evalJavascript('alert("Hello World");');
                future.then((String? result) {
                  setState(() {
                    _history.add('eval: $result');
                  });
                });
              },
              child: const Text('Eval javascript alert()'),
            ),
            ElevatedButton(
              onPressed: () {
                setState(() {
                  _history.clear();
                });
                flutterWebViewPlugin.close();
              },
              child: const Text('Close'),
            ),
            ElevatedButton(
              onPressed: () {
                flutterWebViewPlugin.getCookies().then((m) {
                  setState(() {
                    _history.add('cookies: $m');
                  });
                });
              },
              child: const Text('Cookies'),
            ),
            Text(_history.join('\n'))
          ],
        ),
      ),
    );
  }
}

flutterWebViewPlugin.launch(url)可以实现H5页面的加载,也就是说既可以通过WebViewScaffold中的url来实现页面的加载,也可以通过button响应式这样的加载

launnch里的属性

Future<Null> launch(String url, {
    Map<String, String> headers: null,
    Set<JavascriptChannel> javascriptChannels: null,
    bool withJavascript: true,
    bool clearCache: false,
    bool clearCookies: false,
    bool hidden: false,
    bool enableAppScheme: true,
    Rect rect: null,
    String userAgent: null,
    bool withZoom: false,
    bool displayZoomControls: false,
    bool withLocalStorage: true,
    bool withLocalUrl: true,
    String localUrlScope: null,
    bool withOverviewMode: false,
    bool scrollBar: true,
    bool supportMultipleWindows: false,
    bool appCacheEnabled: false,
    bool allowFileURLs: false,
    bool useWideViewPort: false,
    String invalidUrlRegex: null,
    bool geolocationEnabled: false,
    bool debuggingEnabled: false,
    bool ignoreSSLErrors: false,
});
ElevatedButton(
              onPressed: () {
                flutterWebViewPlugin.launch(selectedUrl);
              },
              child: const Text('Open Fullscreen Webview'),
            ),

Button

  1. TextButton
  2. OutlinedButton
  3. ElevatedButton
    他们只是样式不一样,但是都有onPressed属性

flutter里的events

Stream onDestroy
Stream onUrlChanged
Stream onStateChanged
Stream onScrollXChanged
Stream onScrollYChanged
Stream onError

如何监听事件?
首先是new一个FlutterWebviewPlugin(),然后通过这个实例的上面的这些方法来监听,比如:

 StreamSubscription<WebViewStateChanged> _stateChanged;
 final flutterWebviewPlugin = new FlutterWebviewPlugin();
	//页面导航的状态
    _stateChanged = flutterWebviewPlugin.onStateChanged.listen((event) {
      print("SZJstartLoadUrl${event.url}");
    });

Error Detected

用真机来说可以成功运行,但是用虚拟机就会出现:
【flutter】特别篇:flutter嵌入h5页面_第2张图片

错误介绍及解决

参考博客
这个错误是Chrome浏览器显示的错误消息,其他浏览器会出现不同的错误消息。DNS域名解析失败
虚拟机没法上网:
解决方法:重启虚拟机!!!!!,重启之后office的demo和博客的demo都能运行了
【flutter】特别篇:flutter嵌入h5页面_第3张图片
【flutter】特别篇:flutter嵌入h5页面_第4张图片
即可
【题外话】

  1. late一般用在类中,表示之后再初始化,不用声明的时候就初始化
  2. func({}),大括号中的是命名参数;
  3. func([]),中括号中的是可选参数,类中的变量为可选参数时要给一个默认值
  4. 关于Dart中map的使用
    【查看变量】
  5. 想要查看一个变量的值:可以在debug模式下查看
  6. 直接用Print打印,
    【flutter】特别篇:flutter嵌入h5页面_第5张图片
  7. 打开结构树,在网页里查看更方便哦
    【flutter】特别篇:flutter嵌入h5页面_第6张图片
    【flutter】特别篇:flutter嵌入h5页面_第7张图片
    【自己设计的mapParams的流向】
    用户调用EmbeddH5有参构造传入mapParams->EmbeddH5类中的mapParams->State类中的mapParams,
    下面是添加了mapParams的代码
    调用:
WidgetsFlutterBinding.ensureInitialized();
 runApp(EmbeddH5('https://www.baidu.com',{'title':'百度','UserAgent':'myUserAgent','time':'19:00:01','Tip':'别着急,正在加载ヾ(✿゚▽゚)ノ'}));
import 'package:flutter/material.dart';
import 'package:flutter_webview_plugin/flutter_webview_plugin.dart';
import 'dart:ui';
/// WebView使用flutter_webview_plugin插件
/// https://pub.dev/packages/flutter_webview_plugin
// 此dart在真机上可以正常运行,但是虚拟机没法联网就不能运行,为什么不能联网这个问题还没有解决
class EmbeddH5 extends StatefulWidget {
  String url;
  Map mapParams;
  EmbeddH5(this.url,[this.mapParams = const {'title':'FlutterwebView'}]);

  @override
  _EmbeddH5State createState() =>_EmbeddH5State(url: url,mapParams: mapParams);
}

class _EmbeddH5State extends State<EmbeddH5> {
  String url;
  Map mapParams;
  _EmbeddH5State({required this.url, required this.mapParams});
  @override
  Widget build(BuildContext context) {
    print(mapParams);
    print("------------------");
    return MaterialApp(
      ///隐藏Debug标志
      debugShowCheckedModeBanner: false,
      home: Scaffold(
          body: Container(
            padding: EdgeInsets.only(top: MediaQueryData.fromWindow(window).padding.top),//把H5页面整体往下移动状态栏那么高的位置

            child: WebviewScaffold(
              url: url,
              appBar: AppBar(
                title: Text(mapParams['title'])
              ),
              //当WebView没加载出来前显示
              initialChild: Container(
                color: Colors.white,
                child: Center(
                  child: Text(mapParams['Tip']),
                ),
              ),
            ),
          )),
    );
  }
}


你可能感兴趣的:(flutter,flutter,android)