如何将Flutter项目代码从flutter_webview_plugin迁移到webview_flutter?
从flutter_webview_plugin迁移到webview_flutter的适配方案
1. 替换依赖
在pubspec.yaml中移除flutter_webview_plugin,添加webview_flutter依赖:
dependencies: webview_flutter: ^4.4.0 # 使用最新稳定版本
2. 核心代码适配
替换WebView实例与URL监听
原代码中的FlutterWebviewPlugin实例需替换为WebViewController,URL变化监听通过NavigationDelegate实现。
替换WebviewScaffold组件
原WebviewScaffold的加载动画和隐藏逻辑,通过Stack配合WebViewWidget实现。
完整适配后代码
import 'package:flutter/material.dart'; import 'package:webview_flutter/webview_flutter.dart'; class YourWebViewPage extends StatefulWidget { const YourWebViewPage({super.key}); @override State<YourWebViewPage> createState() => _YourWebViewPageState(); } class _YourWebViewPageState extends State<YourWebViewPage> { late final String _url; late final WebViewController _webViewController; bool _isLoading = true; @override void initState() { super.initState(); // 获取传入的URL参数 _url = ModalRoute.of(context)?.settings.arguments as String; // 初始化WebViewController _webViewController = WebViewController() ..setJavaScriptMode(JavaScriptMode.unrestricted) // 根据业务需求启用/禁用JS ..loadRequest(Uri.parse(_url)) ..setNavigationDelegate( NavigationDelegate( // 监听页面开始加载时的URL onPageStarted: (String url) { if (url.contains("https://www.laplata.com.py/")) { final urlResult = Uri.parse(url); // 关闭当前WebView页面并跳转至支付页 Navigator.of(context).pop(); Navigator.of(context).pushReplacementNamed('pay', arguments: urlResult.queryParameters); } }, // 页面加载完成后隐藏加载动画 onPageFinished: (String url) { setState(() { _isLoading = false; }); }, ), ); } @override Widget build(BuildContext context) { final size = MediaQuery.of(context).size; if (_url.isNotEmpty) { return SafeArea( child: Stack( children: [ // 替换原WebviewScaffold的WebView组件 WebViewWidget(controller: _webViewController), // 原initialChild的加载动画,加载完成后隐藏 if (_isLoading) Center( child: Container( margin: const EdgeInsets.symmetric(horizontal: 50), decoration: const BoxDecoration( image: DecorationImage(image: AssetImage('assets/loading2.gif')), ), ), ), ], ), ); } else { return Scaffold( body: CustomScrollView( slivers: [ SliverPersistentHeader( floating: true, pinned: true, delegate: SliverCustomHeaderDelegate( minheight: size.height * 0.15, maxheight: size.height * 0.15, child: _cabecera() ) ), SliverList( delegate: SliverChildListDelegate([ SizedBox( height: size.height * 0.85, child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ const Spacer(), Container( padding: const EdgeInsets.symmetric(horizontal: 20), height: 300, child: SvgPicture.asset( 'assets/error.svg')), const SizedBox(height: 20), const Text("UPS!!!... Ocurrió un error inesperado", style: TextStyle(fontFamily: "Montserrat", fontWeight: FontWeight.bold, fontSize: 18)), const Spacer(), const Text("Vuelva a intentarlo o comuniquese con nuestro contact center", textAlign: TextAlign.center, style: TextStyle(fontFamily: "Montserrat", fontSize: 18)), const SizedBox(height: 20) ], ), ), ]) ) ], ) ); } } // 保留原_cabecera方法(假设已实现) Widget _cabecera() { return const Placeholder(); // 替换为你的实际实现 } } // 保留原SliverCustomHeaderDelegate类(假设已实现) class SliverCustomHeaderDelegate extends SliverPersistentHeaderDelegate { final double minheight; final double maxheight; final Widget child; SliverCustomHeaderDelegate({required this.minheight, required this.maxheight, required this.child}); @override Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) { return child; } @override double get maxExtent => maxheight; @override double get minExtent => minheight; @override bool shouldRebuild(covariant SliverPersistentHeaderDelegate oldDelegate) { return true; } }
关键适配点说明
- WebViewController:替代原
FlutterWebviewPlugin实例,负责WebView的初始化、加载请求和导航控制。 - NavigationDelegate:通过
onPageStarted/onPageFinished监听URL变化,替代原onUrlChanged流。 - 加载动画实现:用
Stack叠加WebViewWidget和加载动画,通过_isLoading状态控制显示,替代原WebviewScaffold的hidden和initialChild属性。 - 页面关闭逻辑:原
flutterWebviewPlugin.close()对应Navigator.of(context).pop(),因为WebView是作为页面路由存在的,关闭路由即可。
内容的提问来源于stack exchange,提问作者Gonzalo Garcia
相关产品推荐
相关产品推荐

