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内的点击交互。
- 导入手势识别相关包:
import 'package:flutter/gestures.dart';
- 修改
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中禁用自身滚动,再配合手势配置确保事件传递:
- 修改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>
- 同样为
InAppWebView添加gestureRecognizers配置(同方案一),确保滚动事件传递到父级的SingleChildScrollView。
这两种方案都能在保留WebView内点击交互的同时,让鼠标滚轮在WebView区域正常控制整个页面的滚动。
内容的提问来源于stack exchange,提问作者TheQ
相关产品推荐
相关产品推荐

