flutter嵌入HTML5页面,Flutter加载Html并实现与JS 的双向调用
2019-07-20 16:01:01?早起的年輕人?閱讀數(shù) 2025?收藏更多
可以用來加載 Html 頁(yè)面,以實(shí)現(xiàn) Android 中 WebView 或者 是 iOS 中的 UIWebView 中的功能。
Flutter中可用于來加載 Html 頁(yè)面的插件 ,
flutter_WebView_plugin
webView_flutter
flutter_inappbrowser
html
flutter_html
flutter_html_view
這些多多少滿足不了我項(xiàng)目中的需求,所以花了幾天時(shí)間開發(fā)了 Flutter_Fai_Webview 插件,可實(shí)現(xiàn) Android 中 WebView 或者 是 iOS 中的 UIWebView 中的功能,因?yàn)?Flutter_Fai_Webview 插件本質(zhì)上是通過 PlatformView 功能將原生的 View 嵌套在 Flutter 中。
開發(fā)插件要具備的知識(shí):
Flutter 與 原生 Android iOS 雙向通信
Flutter 中內(nèi)嵌 Android iOS 原生View的編程基礎(chǔ)
最重要的一點(diǎn)是 具備 Android iOS 原生語言的開發(fā)能力
Flutter_Fai_Webview 插件可實(shí)現(xiàn)的功能:
同時(shí)適配于 Android Ios 兩個(gè)平臺(tái)
通過 url 來加載渲染一個(gè)Html 頁(yè)面
加載 Html 文本數(shù)據(jù) 如? .... 等
加載 Html 標(biāo)簽數(shù)據(jù) 如??
...
實(shí)現(xiàn) WebView 加載完成后,自動(dòng)測(cè)量 WebView 的高度,并回調(diào) Flutter
實(shí)現(xiàn) WebView 加載完成監(jiān)聽
實(shí)現(xiàn) WebView 上下滑動(dòng)、滑動(dòng)到頂部兼聽、滑動(dòng)到底部兼聽并回調(diào) Flutter
實(shí)現(xiàn) 兼聽 WebView 輸出日志并將日志回調(diào) Flutter
實(shí)現(xiàn) 為 Html 頁(yè)面中所有的圖片添加點(diǎn)擊事件 并回調(diào) Flutter
實(shí)現(xiàn) Html 中Js 調(diào)用 Flutter 頁(yè)面功能
實(shí)現(xiàn) Flutter 頁(yè)面中 觸發(fā) Html 頁(yè)面中 Js 方法
本插件開發(fā)的過程將在這里詳細(xì)論述
也就是說在這里將教會(huì)你 開發(fā)一個(gè) Flutter 插件。
flutter_fai_webview:
git:
url: https://github.com/zhaolongs/Flutter_Fai_Webview.git
ref: master
引入頭文件
import 'package:flutter_fai_webview/flutter_fai_webview.dart';
1
//使用插件 FaiWebViewWidget
webViewWidget = FaiWebViewWidget(
//webview 加載網(wǎng)頁(yè)鏈接
url: htmlUrl,
//webview 加載信息回調(diào)
callback: callBack,
//輸出日志
isLog: true,
);
FaiWebViewWidget({
//webview 加載網(wǎng)頁(yè)鏈接
this.url,
//webview 加載 完整的 html 文件數(shù)據(jù)? 如 ....
// 不完整的 html 文件數(shù)據(jù) 如
...
中已有的樣式 不會(huì)適配移動(dòng)端顯示this.htmlData,
//webview 加載完整的 html 文件數(shù)據(jù) 或者是 不完整的 html 文件數(shù)據(jù) 如
//不完整的 html 文件數(shù)據(jù) 如
this.htmlBlockData,
//輸出 Log 日志功能
this.isLog,
// 為 Html 頁(yè)面中所有的圖片添加 點(diǎn)擊事件 并通過回調(diào) 通知 Flutter 頁(yè)面
// 只有使用 htmlBlockData 屬性加載的頁(yè)面才會(huì)有此效果
this.htmlImageIsClick = false,
// Html 頁(yè)面中圖片點(diǎn)擊回調(diào)
this.imageCallBack,
// Html 頁(yè)面中所有的消息回調(diào)
this.callback,
});
/**
* code 原生 Android iOS 回調(diào) Flutter 的消息類型標(biāo)識(shí)
* message 消息類型日志
* content 回調(diào)的基本數(shù)據(jù)
*/
Function(int code, String message, dynamic content) callback;
詳細(xì)說明
//當(dāng)前點(diǎn)擊的圖片 URL
String imageUrl = null;
//是否顯示浮動(dòng)按鈕
bool isShowFloat = false;
/**
* code 當(dāng)前點(diǎn)擊圖片的 位置
* url 當(dāng)前點(diǎn)擊圖片對(duì)應(yīng)的 鏈接
* images 當(dāng)前 Html 頁(yè)面中所有的圖片集合
*/
void imageCallBack(int code, String url, List images) {
imageUrl = url;
setState(() {});
}
void callBack(int code, String msg, content) {
String call = "回調(diào) code:" +
code.toString() +
" msg:" +
msg.toString() +
" content:" +
content.toString();
if (code == 201) {
//加載頁(yè)面完成后 對(duì)頁(yè)面重新測(cè)量的回調(diào)
//這里沒有使用到
//當(dāng)FaiWebViewWidget 被嵌套在可滑動(dòng)的 widget 中,必須設(shè)置 FaiWebViewWidget 的高度
//設(shè)置 FaiWebViewWidget 的高度 可通過在 FaiWebViewWidget 嵌套一層 Container 或者 SizeBox
webViewHeight = content;
} else if (code == 202) {
// Html 頁(yè)面中 Js 的回調(diào)
// Html 頁(yè)面中的開發(fā)需要使用 Js 調(diào)用? 【 Android 中 使用 controll.otherJsMethodCall( json )】 【iOS中 直接調(diào)用 otherJsMethodCall( json ) 】
// 在 Flutter 中解析 json 然后加載不同的功能
String jsJson = content;
} else if (code == 203) {
// 為 Html 頁(yè)面中的圖片添加 點(diǎn)擊事件后,點(diǎn)擊圖片會(huì)回調(diào)此方法
// content 為當(dāng)前點(diǎn)擊圖片的 地址
// 實(shí)現(xiàn)更多功能 比如 一個(gè) Html 頁(yè)面中 有5張圖片,點(diǎn)擊放大查看并可右右滑動(dòng)
// 這個(gè)功能可以在 imageCallBack 回調(diào)中處理
} else if (code == 301) {
//當(dāng) WebView 滑動(dòng)到頂部的回調(diào)
} else if (code == 302) {
//當(dāng) WebView 開始向下滑動(dòng)時(shí)的回調(diào)
//隱藏按鈕
isShowFloat = true;
} else if (code == 303) {
//當(dāng) WebView 開始向上滑動(dòng)時(shí)的回調(diào)
//顯示按鈕
isShowFloat = false;
} else if (code == 304) {
//當(dāng) WebView 滑動(dòng)到底部的回調(diào)
} else if (code == 401) {
//當(dāng) WebView 開始加載的回調(diào)
} else if (code == 402) {
//當(dāng) WebView 加載完成的回調(diào)
} else if (code == 403) {
// WebView 中 Html中日志輸出回調(diào)
} else if (code == 401) {
// WebView 加載 Html 頁(yè)面出錯(cuò)的回調(diào)
} else if (code == 501) {
// 當(dāng) Html 頁(yè)面中有 Alert 彈框彈出時(shí) 回調(diào)消息
} else if (code == 1000) {
// 操作失敗 例如 空指針異常 等等
} else {
//其他回調(diào)
}
setState(() {
message = call;
});
}
//調(diào)用此方法 便可刷新(重新加載頁(yè)面)
webViewWidget.refresh();
//testAlert() 就是我們要調(diào)用的 Html 頁(yè)面中 JS的方法
// testAlert() 可以自定義與 Html 中的 JS 開發(fā)約定
webViewWidget.loadJsMethod("testAlert()");
import 'package:flutter/material.dart';
import 'package:flutter_fai_webview/flutter_fai_webview.dart';
/**
*? 加載地址
*? 通過 url 加載了一個(gè) Html頁(yè)面 是取常用的方法
*/
class DefaultLoadingWebViewUrlPage extends StatefulWidget {
@override
MaxUrlState createState() => MaxUrlState();
}
class MaxUrlState extends State {
//要顯示的頁(yè)面內(nèi)容
Widget childWidget;
//加載Html的View
FaiWebViewWidget webViewWidget;
//原生 發(fā)送給 Flutter 的消息
String message = "--";
// 頁(yè)面
String htmlUrl = "https://blog.csdn.net/zl18603543572";
@override
void initState() {
super.initState();
//使用插件 FaiWebViewWidget
webViewWidget = FaiWebViewWidget(
//webview 加載網(wǎng)頁(yè)鏈接
url: htmlUrl,
//webview 加載信息回調(diào)
callback: callBack,
//輸出日志
isLog: true,
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: IconButton(
onPressed: () {
Navigator.pop(context);
},
icon: Icon(Icons.arrow_back_ios),
),
title: Container(
padding: EdgeInsets.only(left: 10, right: 10),
height: 28,
alignment: Alignment(0, 0),
color: Color.fromARGB(90, 0, 0, 0),
child: Text(
message,
style: TextStyle(color: Colors.white, fontSize: 12),
),
),
),
body: webViewWidget,
);
}
void callBack(int code, String msg, content) {
//加載頁(yè)面完成后 對(duì)頁(yè)面重新測(cè)量的回調(diào)
//這里沒有使用到
//當(dāng)FaiWebViewWidget 被嵌套在可滑動(dòng)的 widget 中,必須設(shè)置 FaiWebViewWidget 的高度
//設(shè)置 FaiWebViewWidget 的高度 可通過在 FaiWebViewWidget 嵌套一層 Container 或者 SizeBox
if (code == 201) {
//頁(yè)面加載完成后 測(cè)量的 WebView 高度
int webViewHeight = content;
print("webViewHeight " + webViewHeight.toString());
} else {
//其他回調(diào)
}
setState(() {
message = "回調(diào):code[" + code.toString() + "]; msg[" + msg.toString() + "]";
});
}
}
2.2 通過 Html Data 加載 Html 頁(yè)面
import 'package:flutter/material.dart';
import 'package:flutter_fai_webview/flutter_fai_webview.dart';
/**
*? 通過 htmlBlockData 加載 Html 數(shù)據(jù) 并添加移動(dòng)適配
*/
class DefaultHtmlBlockDataPage2 extends StatefulWidget {
@override
DefaultHtmlBlockDataPageState createState() =>
DefaultHtmlBlockDataPageState();
}
class DefaultHtmlBlockDataPageState extends State {
FaiWebViewWidget webViewWidget;
//原生 發(fā)送給 Flutter 的消息
String message = "--";
double webViewHeight = 100;
//要顯示的頁(yè)面內(nèi)容
Widget childWidget;
String htmlBlockData = "
?生物真題?
@override
void initState() {
super.initState();
//使用插件 FaiWebViewWidget
webViewWidget = FaiWebViewWidget(
//webview 加載網(wǎng)頁(yè)鏈接
htmlBlockData: htmlBlockData,
//webview 加載信息回調(diào)
callback: callBack,
//輸出日志
isLog: true,
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: IconButton(
onPressed: () {
Navigator.pop(context);
},
icon: Icon(Icons.arrow_back_ios),
),
title: Container(
padding: EdgeInsets.only(left: 10, right: 10),
height: 28,
alignment: Alignment(0, 0),
color: Color.fromARGB(90, 0, 0, 0),
child: Text(
message,
style: TextStyle(color: Colors.white, fontSize: 12),
),
),
),
body: Container(child: webViewWidget,),
);
}
callBack(int code, String msg, content) {
//加載頁(yè)面完成后 對(duì)頁(yè)面重新測(cè)量的回調(diào)
//這里沒有使用到
//當(dāng)FaiWebViewWidget 被嵌套在可滑動(dòng)的 widget 中,必須設(shè)置 FaiWebViewWidget 的高度
//設(shè)置 FaiWebViewWidget 的高度 可通過在 FaiWebViewWidget 嵌套一層 Container 或者 SizeBox
if (code == 201) {
webViewHeight = content;
print("webViewHeight " + webViewHeight.toString());
} else {
//其他回調(diào)
}
setState(() {
message = "回調(diào):code[" + code.toString() + "]; msg[" + msg.toString() + "]";
});
}
}
也就是說 一個(gè)頁(yè)面中,一部分是 Flutter Widget 一部分是 webview 加載。
import 'package:flutter/material.dart';
import 'dart:async';
import 'package:flutter_fai_webview/flutter_fai_webview.dart';
/**
*? 混合頁(yè)面加載
*
*/
class DefaultHexRefreshPage extends StatefulWidget {
@override
MaxUrlHexRefreshState createState() => MaxUrlHexRefreshState();
}
class MaxUrlHexRefreshState extends State {
FaiWebViewWidget webViewWidget;
//原生 發(fā)送給 Flutter 的消息
String message = "--";
String htmlUrl = "https://blog.csdn.net/zl18603543572";
double webViewHeight = 1;
@override
void initState() {
super.initState();
//使用插件 FaiWebViewWidget
webViewWidget = FaiWebViewWidget(
//webview 加載網(wǎng)頁(yè)鏈接
url: htmlUrl,
//webview 加載信息回調(diào)
callback: callBack,
//輸出日志
isLog: true,
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: IconButton(
onPressed: () {
Navigator.pop(context);
},
icon: Icon(Icons.arrow_back_ios),
),
title: Container(
padding: EdgeInsets.only(left: 10, right: 10),
height: 28,
alignment: Alignment(0, 0),
color: Color.fromARGB(90, 0, 0, 0),
child: Text(
message,
style: TextStyle(color: Colors.white, fontSize: 12),
),
),
),
body: buildRefreshHexWidget(),
);
}
/**
* 需要注意的是
* RefreshIndicator 會(huì)覆蓋 WebView 的滑動(dòng)事件
* 所有關(guān)于 監(jiān)聽 WebView 的滑動(dòng)監(jiān)聽將會(huì)失效
*/
Widget buildRefreshHexWidget() {
return RefreshIndicator(
//下拉刷新觸發(fā)方法
onRefresh: _onRefresh,
//設(shè)置webViewWidget
child: SingleChildScrollView(
child: Column(
children: [
Container(
color: Colors.grey,
height: 220.0,
child: Column(mainAxisSize: MainAxisSize.min,children: [
Center(child: Text("這里是 Flutter widget? "),)
],),
),
Align(
alignment: Alignment(0, 0),
child: Text("以下是 Html 頁(yè)面 "),
),
Container(
color: Colors.redAccent,
height: 1.0,
),
Container(
height: webViewHeight,
child: webViewWidget,
)
],
),
),
);
}
Future _onRefresh() async {
return await Future.delayed(Duration(seconds: 1), () {
print('refresh');
webViewWidget.refresh();
});
}
callBack(int code, String msg, content) {
//加載頁(yè)面完成后 對(duì)頁(yè)面重新測(cè)量的回調(diào)
if (code == 201) {
//更新高度
webViewHeight = content;
print("webViewHeight " + content.toString());
} else {
//其他回調(diào)
}
setState(() {
message = "回調(diào):code[" + code.toString() + "]; msg[" + msg.toString() + "]";
});
}
}
文章最后發(fā)布于: 2019-07-20 16:01:01
總結(jié)
以上是生活随笔為你收集整理的flutter嵌入HTML5页面,Flutter加载Html并实现与JS 的双向调用的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 织梦的网站地图怎么做html,如何优化织
- 下一篇: android 截屏指定区域,Andro