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

Flutter WebView实现下拉刷新时RefreshIndicator失效如何解决

Flutter WebView 下拉刷新不生效解决方案

RefreshIndicator默认仅响应可滚动组件的下拉手势,WebView本身的滚动事件默认无法被RefreshIndicator捕获,因此直接嵌套不会触发刷新效果。

实现步骤

  • 新增滚动位置监听变量,记录WebView当前是否滚动到页面顶部
  • 新增JS通道接收网页滚动位置回调
  • 页面加载完成后注入JS监听网页滚动事件
  • 调整页面结构,嵌套RefreshIndicator和SingleChildScrollView保证下拉手势可被识别

修改后的完整代码

// 新增变量记录网页是否滚动到顶部
bool _isWebAtTop = true;

// 新增滚动事件JS通道
JavascriptChannel _scrollListenerChannel(BuildContext context) {
  return JavascriptChannel(
    name: 'ScrollListener',
    onMessageReceived: (JavascriptMessage message) {
      _isWebAtTop = message.message == "true";
    },
  );
}

@override
Widget build(BuildContext context) {
return Scaffold(
  appBar: PreferredSize(
    preferredSize: MediaQuery.of(context).size * 0.05,
    child: AppBar(
      //leading: Image.asset(gnTabIcon),
      elevation: 3.5,
      shadowColor: AppColors.navyBlue,
      backgroundColor: AppColors.orange,
      title: const Text(title),
      actions: <Widget>[
        NavigationControls(_controller.future), // control navigation
      ],
    ),
  ),


  // build scaffold for main app
  body: Builder(
    builder: (BuildContext context) {
      return RefreshIndicator(
        onRefresh: () async {
          // 仅网页滚动到顶部时触发刷新
          if(_isWebAtTop) {
            final controller = await _controller.future;
            controller.reload();
          }
        },
        child: SingleChildScrollView(
          // 强制可滚动,保证内容不足一屏时也能触发下拉
          physics: const AlwaysScrollableScrollPhysics(),
          child: SizedBox(
            // 高度设置为可用屏幕高度,撑满空间
            height: MediaQuery.of(context).size.height - (MediaQuery.of(context).size.height * 0.05) -15,
            child: Stack(
              children: [
                Padding(
                  padding: const EdgeInsets.fromLTRB(0, 0, 0, 15.0),
                  child: WebView(
                    gestureNavigationEnabled: false,
                    initialUrl: url,
                    javascriptMode: JavascriptMode.unrestricted,
                    zoomEnabled: false, // disable pinch to zoom
                    // 增加垂直手势识别,避免滚动冲突
                    gestureRecognizers: {
                      Factory<VerticalDragGestureRecognizer>(() => VerticalDragGestureRecognizer()),
                    },
                    onWebViewCreated: (webViewController) {
                      print('WebView is created');
                      _controller.complete(webViewController);
                    },
                    onProgress: (int progress) {
                      print("WebView is loading (progress : $progress%)");
                      splashScreenDelay(progress);
                    },
                    javascriptChannels: <JavascriptChannel>{
                      _toasterJavascriptChannel(context),
                      // 注册滚动监听通道
                      _scrollListenerChannel(context),
                    },

                    onPageStarted: (String url) {
                      print('Page started loading: $url');
                      _loadingStateTrue();
                    },
                    onPageFinished: (String url) async {
                      print('Page finished loading: $url');
                      _loadingStateFalse();
                      // 页面加载完成后注入JS监听滚动位置
                      final controller = await _controller.future;
                      controller.runJavascript('''
                        window.addEventListener("scroll", function() {
                          ScrollListener.postMessage(window.pageYOffset == 0 ? "true" : "false");
                        });
                      ''');
                    },
                  ),
                ),
                isLoading
                    ? Center(
                        child: GnLoader(),
                      )
                    : const SizedBox.shrink(),
              ],
            ),
          ),
        ),
      );
    },
  ),
);
}

注意事项

  • 可根据实际布局调整SizedBox的高度计算逻辑,保证WebView撑满可用空间
  • 如果网页本身存在嵌套滚动容器,可调整JS监听逻辑,适配对应容器的scrollTop属性即可
  • 原有WebView的业务逻辑无需修改,不会影响原有功能

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.23 20:15:01