web_page.dart 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. import 'package:flutter/material.dart';
  2. import 'package:get/get.dart';
  3. import 'package:webview_flutter/webview_flutter.dart';
  4. class WebviewPage extends StatefulWidget {
  5. final String url;
  6. final bool? isDialog;
  7. final bool? isFile;
  8. const WebviewPage({Key? key, required this.url, this.isDialog, this.isFile})
  9. : super(key: key);
  10. @override
  11. _WebviewPageState createState() => _WebviewPageState();
  12. }
  13. class _WebviewPageState extends State<WebviewPage> {
  14. String _title = '...';
  15. double progress = 0.0;
  16. bool isPayFlow = false;
  17. late WebViewController _webViewController;
  18. late Function payCallback;
  19. late Function jumpCallback;
  20. void jumpFunction() {
  21. Map<String, String> params = {};
  22. // 点击不显示弹窗
  23. params.remove('action');
  24. Get.back();
  25. }
  26. @override
  27. void initState() {
  28. super.initState();
  29. final WebViewController controller = WebViewController();
  30. var userAgent =
  31. "Mozilla/5.0 (Linuxxxx; Android 10; Redmi K30 Pro) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Mobile Safari/537.36";
  32. controller.setUserAgent(userAgent);
  33. var loadUrl = Uri.parse(widget.url);
  34. controller
  35. ..setJavaScriptMode(JavaScriptMode.unrestricted)
  36. ..setBackgroundColor((widget.isDialog ?? false)
  37. ? Colors.transparent
  38. : const Color(0x00000000))
  39. ..setNavigationDelegate(
  40. NavigationDelegate(
  41. onProgress: (value) {
  42. progress = value.toDouble();
  43. debugPrint("loadUrl progress:$progress");
  44. try {
  45. setState(() => {});
  46. } catch (e) {}
  47. },
  48. onPageStarted: (String url) {
  49. debugPrint("loadUrl pageStart:$url");
  50. if (url.startsWith("mailto") ||
  51. url.startsWith("tel") ||
  52. url.startsWith("http") ||
  53. url.startsWith("file") ||
  54. url.startsWith("https")) {
  55. } else {
  56. _webViewController.goBack();
  57. }
  58. },
  59. onPageFinished: (controller) async {
  60. // 获取页面标题
  61. var title = await _webViewController.getTitle();
  62. setState(() {
  63. _title = title ?? "";
  64. });
  65. },
  66. onWebResourceError: (WebResourceError error) {
  67. debugPrint('''
  68. Page resource error:
  69. code: ${error.errorCode}
  70. description: ${error.description}
  71. errorType: ${error.errorType}
  72. isForMainFrame: ${error.isForMainFrame}
  73. ''');
  74. },
  75. onNavigationRequest: (NavigationRequest request) {
  76. String url = Uri.decodeComponent(request.url);
  77. debugPrint('navigationDelegate decode $url');
  78. return NavigationDecision.navigate;
  79. },
  80. ),
  81. )
  82. ..addJavaScriptChannel(
  83. 'DsBridgeApp',
  84. onMessageReceived: (JavaScriptMessage message) {},
  85. )
  86. ..addJavaScriptChannel(
  87. 'Alert',
  88. onMessageReceived: (JavaScriptMessage message) {},
  89. );
  90. if (widget.isFile ?? false) {
  91. // var requestUrl = Uri.decodeComponent('${widget.url}?is_flutter=1');
  92. loadFileUrl(controller, widget.url);
  93. controller.loadFile(widget.url);
  94. } else {
  95. controller.loadRequest(loadUrl);
  96. }
  97. // #enddocregion platform_features
  98. _webViewController = controller;
  99. jumpCallback = () {
  100. jumpFunction();
  101. };
  102. }
  103. Future<void> loadFileUrl(
  104. WebViewController webViewController, String fileAbsoluteFilePath) async {}
  105. @override
  106. Widget build(BuildContext context) {
  107. if (widget.isDialog ?? false) {
  108. return Stack(
  109. children: [
  110. WebViewWidget(controller: _webViewController),
  111. const Positioned(child: WebviewTimerClose(time: 30), left: 0, top: 0)
  112. ],
  113. );
  114. } else {
  115. return Container(
  116. width: double.infinity,
  117. height: double.infinity,
  118. decoration: const BoxDecoration(color: Color(0xFFF4F0EF)),
  119. child: Column(
  120. mainAxisAlignment: MainAxisAlignment.start,
  121. crossAxisAlignment: CrossAxisAlignment.start,
  122. children: [
  123. // AppBar(
  124. // leading: IconButton(
  125. // icon: Image.asset(
  126. // "assets/images/ic_back_arrow.png",
  127. // width: 34,
  128. // height: 34,
  129. // ),
  130. // onPressed: () => Get.back(closeOverlays: true)),
  131. // backgroundColor: Colors.transparent,
  132. // elevation: 0,
  133. // centerTitle: true,
  134. // title: Text(
  135. // _title,
  136. // ),
  137. // // actions: actions ?? [],
  138. // ),
  139. Expanded(
  140. child: WebViewWidget(
  141. controller: _webViewController,
  142. )),
  143. ],
  144. ),
  145. );
  146. }
  147. }
  148. void reloadWebView() {
  149. _webViewController.reload();
  150. }
  151. }
  152. class WebviewTimerClose extends StatefulWidget {
  153. final int time;
  154. const WebviewTimerClose({Key? key, required this.time}) : super(key: key);
  155. @override
  156. WebviewTimerCloseState createState() => WebviewTimerCloseState();
  157. }
  158. class WebviewTimerCloseState extends State<WebviewTimerClose> {
  159. bool showClose = false;
  160. @override
  161. void initState() {
  162. super.initState();
  163. Future.delayed(Duration(seconds: widget.time)).then((value) {
  164. try {
  165. showClose = true;
  166. if (mounted) setState(() => {});
  167. } catch (e) {
  168. e.printError();
  169. }
  170. });
  171. }
  172. @override
  173. Widget build(BuildContext context) {
  174. if (showClose) {
  175. return Material(
  176. color: Colors.transparent,
  177. child: IconButton(
  178. icon: Image.asset(
  179. "assets/images/ic_dialog_close.png",
  180. width: 25,
  181. height: 25,
  182. ),
  183. onPressed: () => Get.back()),
  184. );
  185. }
  186. return Container();
  187. }
  188. }