You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 07:37:56