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

Flutter Web中InAppWebView导致全局滚动失效的问题求助

Flutter Web中InAppWebView拦截滚动事件的解决方案

问题描述

开发Flutter Web应用时,页面顶部、底部为Flutter Widget,中间嵌入InAppWebView,整体由SingleChildScrollView包裹。使用鼠标滚轮滚动时,光标悬停在InAppWebView区域后无法继续滚动,需将鼠标移至其他Flutter Widget区域才能恢复滚动,用户体验不佳。

推测原因是InAppWebView默认拦截了滚动事件,但WebView内部无可滚动内容,该拦截无必要。曾尝试为Flutter渲染的iframe设置pointer-events: none;,虽解决滚动问题,但导致WebView内内容无法点击,并非可行方案。

复现步骤

  • 创建新Flutter项目
  • 执行命令:flutter pub add flutter_inappwebview
  • 将main.dart内容替换为以下代码:
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';

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

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

  @override
  Widget build(BuildContext context) {
    final html = '''
      <!DOCTYPE html>
      <html>
        <head>
          <style type="text/css">
            body {
              margin: 0;
              padding: 0;
              display: flex;
              justify-content: center;
              align-items: center;
              height: 100vh;
              background-color:green;
            }
          </style>
        </head>
        <body>
          This is a web view!
        </body>
      </html>
    ''';
    
    return MaterialApp(
      home: Scaffold(
        body: SingleChildScrollView(
          child: Column(
            children: [
              Container(
                height: 800,
                color: Colors.red,
                child: Center(child: Text('Top of the app')),
              ),
              SizedBox(
                height: 800,
                child: InAppWebView(
                  onWebViewCreated: (controller) async {
                    await controller.loadData(data: html);
                  },
                  ),
              ),
              Container(
                height: 800,
                color: Colors.blue,
                child: Center(child: Text('Bottom of the app')),
              ),
            ],
          ),
        ),
      ),
    );
  }
}
  • 在网页浏览器中运行应用
  • 使用鼠标滚轮向下滚动,会发现难以滚动到应用底部

解决方案

方案一:配置gestureRecognizers传递滚动事件

通过InAppWebView的gestureRecognizers属性,将垂直滚动事件的处理权交给父级的SingleChildScrollView,同时保留WebView内的点击交互。

  1. 导入手势识别相关包:
import 'package:flutter/gestures.dart';
  1. 修改InAppWebView的配置,添加gestureRecognizers参数:
SizedBox(
  height: 800,
  child: InAppWebView(
    onWebViewCreated: (controller) async {
      await controller.loadData(data: html);
    },
    gestureRecognizers: {
      // 允许父级处理垂直滚动事件
      Factory<VerticalDragGestureRecognizer>(
        () => VerticalDragGestureRecognizer()
          ..onUpdate = (DragUpdateDetails details) {
            // 将滚动事件传递给全局事件处理,让SingleChildScrollView响应
            WidgetsBinding.instance.handlePointerEvent(PointerMoveEvent(
              position: details.globalPosition,
              delta: details.delta,
            ));
          },
      ),
    },
  ),
)

方案二:禁用WebView内部滚动+手势配置

先在WebView加载的HTML中禁用自身滚动,再配合手势配置确保事件传递:

  1. 修改HTML的body样式,添加overflow: hidden;:
<style type="text/css">
  body {
    margin: 0;
    padding: 0;
    display: flex;
    justify-content: center;
    align-items: center;
    height: 100vh;
    background-color:green;
    overflow: hidden; /* 禁用WebView内部滚动 */
  }
</style>
  1. 同样为InAppWebView添加gestureRecognizers配置(同方案一),确保滚动事件传递到父级的SingleChildScrollView。

这两种方案都能在保留WebView内点击交互的同时,让鼠标滚轮在WebView区域正常控制整个页面的滚动。

内容的提问来源于stack exchange,提问作者TheQ

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 23:31:06