WebView_Flutter4.0+使用

该代码示例展示了在Flutter应用中使用WebView加载网页,同时通过JavaScriptChannel进行App与网页的交互,包括页面加载监听、图片选择、文件选择、用户信息传递和登出功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

/**用法参考博客:http://t.csdn.cn/2vTkT*/
import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'dart:typed_data';
import 'dart:ui';

import 'package:flutter/material.dart';
import 'package:hlcdp_app/http/api.dart';
import 'package:hlcdp_app/http/service.dart';
import 'package:hlcdp_app/pages/login_page.dart';
import 'package:hlcdp_app/pages/message/message_page.dart';
import 'package:hlcdp_app/pages/myPages/my_page.dart';
import 'package:hlcdp_app/pages/transition_page2.dart';
import 'package:hlcdp_app/utils/file_utils.dart';
import 'package:hlcdp_app/utils/image_utils.dart';
import 'package:hlcdp_app/utils/navigator_util.dart';
import 'package:hlcdp_app/utils/personal_data.dart';
import 'package:hlcdp_app/utils/web_socket_util.dart';
import 'package:path_provider/path_provider.dart';
import 'package:webview_flutter/webview_flutter.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:image_picker/image_picker.dart';
import 'package:file_picker/file_picker.dart';
import 'package:shared_preferences/shared_preferences.dart';
/*WebView其他地方调用的接口类*/
class WebViewPage{
  late String url;
  late Map mapParams;
  late BuildContext context;
  WebViewPage(this.url,this.context,{this.mapParams = const {'title':'FlutterWebView'} }){
    Navigator.push(context, MaterialPageRoute<void>(
        builder: (BuildContext context){
          return Scaffold(
              body: EmbeddH5(url,mapParams:mapParams)
          );
        }
    ));
  }
}

class EmbeddH5 extends StatefulWidget {
  late String url;
  late Map mapParams;
  late BuildContext context;
  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;
  WebViewController webViewController = WebViewController();
  TransitionPage2 transitionPage2 = TransitionPage2();
  bool pageFinished = false;

  _EmbeddH5State({required this.url, required this.mapParams});

  @override
  void initState() {
    super.initState();
    initWebViewController();
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: Container(
          padding: EdgeInsets.only(top: MediaQuery.of(context).padding.top),
          child: pageFinished?WebViewWidget(controller: webViewController,):transitionPage2
        )
    );
  }
  void initWebViewController() {
    webViewController
      ..loadRequest(Uri.parse(url))
      ..setJavaScriptMode(JavaScriptMode.unrestricted)
      ..setNavigationDelegate(
          NavigationDelegate(
              // onNavigationRequest: (NavigationRequest request){return NavigationDecision.navigate;},
              onPageStarted: (String url) {
                  Fluttertoast.showToast(msg: "页面开始加载");
                  print("开始加载:${url}");
                },
              onPageFinished: (String url) {
                  if (pageFinished == false) {Fluttertoast.showToast(msg: "页面加载完成");}
                  pageFinished = true;
                  setState(() {print("加载完成");});//会调用build方法
                },
              onProgress: (int progress){print("progress:$progress");},
              onWebResourceError: (WebResourceError error){print(error);Fluttertoast.showToast(msg: "出现错误:${error}");}
          )
      )
      ..addJavaScriptChannel('testBridge', onMessageReceived: (JavaScriptMessage message){
        print("testBridge");
        webViewController.runJavaScript('callTest("Hello,H5")');
      })
      ..addJavaScriptChannel('cameraBridge', onMessageReceived: (JavaScriptMessage message)async{
        print('camera:${message.message}');
        final XFile? xFile = await loadCamera();
        webViewController.runJavaScript('callCamera("${xFile?.path}")');

      })
      ..addJavaScriptChannel('photoBridge', onMessageReceived: (JavaScriptMessage message)async{
        print('photo:${message.message}');
        final XFile? xFile = await loadPhotoGallery();
        webViewController.runJavaScript('callPhoto("${xFile?.path}")');
      })
      ..addJavaScriptChannel('fileBridge', onMessageReceived: (JavaScriptMessage message)async{
        PlatformFile? file = await FileUtils.pickFile();
        webViewController.runJavaScript('callFile("${file?.path}")');
      })
      ..addJavaScriptChannel('navigatorBridge', onMessageReceived: (JavaScriptMessage message){
        NavigatorUtil.pushMaterialPage(context, MyPage());
      })
      ..addJavaScriptChannel('userMessageBridge', onMessageReceived: (JavaScriptMessage message){
        print('userMessage:${message.message}');
        Map<String,String> map = PersonData.map;
        final String userMessage = jsonEncode(map);
        webViewController.runJavaScript('callUserMessage("$userMessage")');
      })
      ..addJavaScriptChannel('logoutBridge', onMessageReceived: (JavaScriptMessage message)async{
        print('logouMessage:${message.message}');
        final prefs = await SharedPreferences.getInstance();
        post2(Api.host + "/admin/user/auth/common/logout").then((value) {print("成功退出用户");});
        prefs.setBool("isLogin", false);
        WebSocketUtility().sendWhenLogout();
        WebSocketUtility().closeSocket();//退出登录,关闭通知
        Navigator.of(context).pushAndRemoveUntil(
            MaterialPageRoute(
                builder: (BuildContext context){
                  return LoginPage();
                }
            ),
                (route) => false
        );
      });
  }
}
/**
 * 首次不加载页面的解决方案:采用预加载再释放的方式(治标不治本);参考网站:https://juejin.cn/post/6844903831315152909*/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值