flutter使用WebView,iOS下页面无响应问题

macos下使用android studio环境开发flutter应用,使用了webview_flutter组件访问cesium地图页面,android环境下正常。ios模拟器和真机调试都出现了同一个问题:即普通访问页面、拖动地图正常,但如果该dart页面(包含webview_flutter组件)上加了floatingActionButton或者其他Stack布局的浮动组件,点击触发这些组件后,就无法再拖动webview_flutter页面中的地图。换用flutter_inappwebview问题依旧。

环境参数:
macOS版本:13.2.1 (22D68)。
android studio版本:2022.1.1 Patch 2;flutter插件版本:72.1.2;dart插件版本:221.6096。
Flutter SDK版本:3.3.9;Dart版本:2.18.5;flutter DevTools版本:2.15.0。
webview_flutter库版本: ^4.0.5;flutter_inappwebview库版本: ^5.7.2+3。
xcode版本:14.1 (14B47b)。

测试代码:

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
//#region platform_imports
// Import for Android features.
import 'package:webview_flutter_android/webview_flutter_android.dart';
// Import for iOS features.
import 'package:webview_flutter_wkwebview/webview_flutter_wkwebview.dart';
//#endregion platform_imports

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  late final WebViewController _controller;

  @override void initState() {
    //#region platform_features
    late final PlatformWebViewControllerCreationParams params;
    if (WebViewPlatform.instance is WebKitWebViewPlatform) {
      params = WebKitWebViewControllerCreationParams(
        allowsInlineMediaPlayback: true,
        mediaTypesRequiringUserAction: const <PlaybackMediaTypes>{},
      );
    } else {
      params = const PlatformWebViewControllerCreationParams();
    }

    final WebViewController controller = WebViewController.fromPlatformCreationParams(params);
    //#endregion platform_features

    controller
      ..setJavaScriptMode(JavaScriptMode.unrestricted)
      ..loadRequest(Uri.parse('https://www.sdgrxh.xyz/test/'));
    //#region platform_features
    if (controller.platform is AndroidWebViewController) {
      AndroidWebViewController.enableDebugging(true);
      (controller.platform as AndroidWebViewController)
          .setMediaPlaybackRequiresUserGesture(false);
    }
    //#endregion platform_features

    _controller = controller;

    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: WebViewWidget(controller: _controller,),
      floatingActionButton: FloatingActionButton(
        onPressed: () {},
        child: const Icon(Icons.add),
      ), 
    );
  }
}

测试网址:https://www.sdgrxh.xyz/test/
测试方法:运行上述代码后,在ios模拟器中自动显示cesium地图,此时拖动地图正常;点击一次右下方FAB按钮后,拖动地图操作将变成放大缩小;再次点击FAB后,拖动地图操作不再响应。
补充:访问其他网站没有问题,只有cesium地图出问题,难道是WebGL的问题?

参考GPT和自己的思路,这个问题可能与Flutter在iOS上的手势识别有关。iOS上有一些手势识别器(例如滑动返回)可能会与WebView的手势冲突,导致WebView页面无响应。在您的情况下,添加了浮动组件之后,它可能会干扰WebView的手势。
有几种方法可以尝试解决这个问题:

1 禁用WebView的手势识别器
尝试在WebView中禁用手势识别器,这样就可以避免与Flutter的手势冲突。在WebViewController对象上调用gesturesDisabled方法,将其设置为true。

2 禁用Flutter的手势识别器
禁用Flutter的手势识别器,这样就可以避免与WebView的手势冲突。可以使用GestureDetector组件的behavior属性将其设置为HitTestBehavior.translucent,这将允许手势穿透并传递到下面的WebView。

3 使用flutter_inappwebview插件
尝试使用flutter_inappwebview插件代替webview_flutter库。它提供了更多的手势控制选项,并且在iOS上具有更好的性能。

class _MyHomePageState extends State<MyHomePage> {
  late final WebViewController _controller;

  @override void initState() {
    ...
    _controller = controller;
    super.initState();
  }

  ...

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: GestureDetector(
        behavior: HitTestBehavior.translucent, // 允许手势穿透
        child: WebViewWidget(controller: _controller,),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {},
        child: const Icon(Icons.add),
      ), 
    );
  }
}


希望这可以帮助您解决问题。

该回答引用GPTᴼᴾᴱᴺᴬᴵ
根据您的描述,问题可能是由于iOS设备上WebView的手势识别和FloatingActionButton的手势识别之间存在冲突所导致的。您可以尝试使用一些手势识别的技巧来解决这个问题。

首先,您可以尝试禁用FloatingActionButton的手势识别,以确保WebView的手势识别得到正确响应。为此,您可以将FloatingActionButton包装在一个GestureDetector中,并禁用GestureDetector的手势识别,例如:

GestureDetector(
  onTap: () {},
  behavior: HitTestBehavior.translucent,
  child: FloatingActionButton(
    onPressed: () {},
    child: Icon(Icons.add),
    heroTag: null,
  ),
  excludeFromSemantics: true,
)


在上面的代码中,behavior属性设置为HitTestBehavior.translucent,以允许手势穿透GestureDetector并直接触发WebView的手势识别。excludeFromSemantics属性设置为true,以避免将GestureDetector包装的控件添加到无障碍功能中。

另外,您也可以尝试使用一些手势识别的库,例如gesture_zoom_box,来实现更加灵活的手势控制。该库可以让您在任何控件上实现缩放和拖动手势,而无需处理手势冲突。

最后,如果您仍然无法解决问题,您可以考虑在iOS设备上使用WKWebView来代替UIWebView,因为UIWebView已经被苹果官方标记为已弃用。您可以通过将webview_flutter库的版本更新到最新版本来启用WKWebView支持,然后使用WebView.platform = TargetPlatform.iOS来显示WKWebView。这可能需要您重新调整您的代码,但它可能会解决手势冲突问题。

希望这些建议能够帮助您解决问题!

上述回答均未解决……

楼下 singsex 的方法也试了,不满足需求,页面上方需要有按钮,即使将按钮放置在页面外的工具条,也需要有drawer,drawer一出现,页面还是被锁死

楼下其他解决方法也试过了,将xcode升级到14.2,还是未解决该问题

很奇怪的是,地图虽然锁死了,但网页页面上的按钮却可以得到点击响应(示例网址上没有按钮,我本地测试的),另外,地图锁死不能拖动后,在flutter_inappwebview外包裹GestureDetector,仍然能够在onDoubleTap()中监听到双击事件

该思路参考GPT,仅供借鉴。
可以尝试将WebView的初始化和加载代码放在dispatch_async的块中,以确保它在主线程上运行:

dispatch_async(dispatch_get_main_queue(), ^{
    // 在这里初始化和加载WebView
});

另外,也可以尝试设置WebView的UIDelegate和NavigationDelegate,并实现相应的方法来处理任何可能的交互和导航事件。
如果仍然存在问题,请检查是否有任何JavaScript代码或插件与您的WebView不兼容。可以通过禁用它们来进行测试。
最后,查看Xcode控制台是否有任何错误消息或警告。这些消息可能会提供有关问题所在的更多信息。

以下答案由GPT-3.5大模型与博主波罗歌共同编写:
这个问题可能是因为iOS浮动组件(FloatingActionButton)造成了UI渲染的冲突,导致WebView页面无法响应。可以尝试在iOS上使用Navigator等方法从WebView页面中移出浮动组件,或者使用Cupertino风格的浮动组件来代替常规的FloatingActionButton。

以下是可能的解决方法:

1.使用Navigator方法移出FAB

在iOS上,移除浮动组件可能会使页面重新进行布局和渲染,从而解决UI渲染冲突的问题。可以使用Navigator.pop(context)方法来从WebView页面中移出浮动组件。

floatingActionButton: FloatingActionButton(
        onPressed: () { 
           Navigator.pop(context); //移出浮动组件
        },
        child: const Icon(Icons.add),
      ),

2.使用Cupertino风格的浮动组件

使用CupertinoButton.filled来代替常规的浮动按钮。这个组件具有iOS设计风格,可能可以解决UI渲染冲突的问题。

floatingActionButton: SizedBox(
        width: 70,
        height: 70,
        child: CupertinoButton.filled(
          onPressed: () {},
          child: const Icon(Icons.add),
        ),
      ),

如果以上方法无法解决问题,你还可以尝试在WebView页面中使用手势识别器,而不是浮动组件来实现操作。

return GestureDetector(
        onTap: () {
          print('tap');
        },
        child: WebViewWidget(controller: _controller,),
      );

如果我的回答解决了您的问题,请采纳!

你可以尝试一下让h5去做这个fab按钮,应该是由于焦点丢失,导致webview无法获到焦点。
因为你现在已经用了webview了,这个fab完全可以让h5端同学做一下,或者你可以在Appbar里面加个按钮,测试一下。

如有帮助,望采纳。

实在不行就自定义FAB 估计是stack布局 遮挡了

js中webgl加速开了没

题主,这个问题我来替你解决,若有帮助,还望采纳,点击回答右侧采纳即可。

在你的代码中加入如下试试,然后重启模拟器,一定要重启让info.list生效,不然会报错。

<key>NSAppTransportSecurity</key>
    <dict>
        <key>NSAllowsArbitraryLoads</key>
        <true/>
    </dict>

该回答引用ChatGPT

根据您提供的信息,可能是因为在iOS模拟器和真机上,WebView组件与FloatingActionButton或Stack组件的布局结构不兼容,导致在点击FloatingActionButton或Stack组件后,无法再次拖动WebView页面中的地图。

尝试一些可能的解决方法:

1、在Scaffold的body属性中使用Stack布局,将WebView和FloatingActionButton放在同一个Stack中,而不是分别放在Scaffold的body属性和floatingActionButton属性中。

2、尝试在Scaffold的body属性中使用SingleChildScrollView或ListView等可滚动的组件包装WebView和FloatingActionButton,以确保两者的布局结构兼容。

3、如果上述方法不起作用,可以尝试使用Flutter中的GestureDetector组件来手动实现拖动地图的功能,而不是依赖于WebView中的手势识别。