Flutter Web:RefreshIndicator 不再工作

Jos*_*let 5 dart overscroll pull-to-refresh flutter

虽然 RefreshIndicator 之前在移动设备和 Web 上都运行良好,但它不再刷新 Flutter Web 上的屏幕。在我的任何屏幕上都不可能再过度滚动,即使列表很长,但在移动版本上很容易实现。

从 flutter 3.3.x 更新到 3.7.9 后我注意到了这个问题

在此输入图像描述

这是另一个简化的例子。在手机上,重新加载随机生成的数字效果很好,在网络上什么也没有发生:

import 'package:flutter/material.dart';
import 'dart:math';

void main() => runApp(const MyHomePage());

class MyHomePage extends StatefulWidget {
  const MyHomePage({
    Key? key,
  }) : super(key: key);

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

class _MyHomePageState extends State<MyHomePage> {
  String title = 'Hello';
  var rng = Random();

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Scaffold(
        appBar: AppBar(
          title: Text(title),
        ),
        body: RefreshIndicator(
          onRefresh: () async => setState(() {
            title = 'Hey';
          }),
          child: ListView.builder(
            physics: const AlwaysScrollableScrollPhysics(),
            itemBuilder: (_, i) => Container(
              padding: const EdgeInsets.all(10),
              color: Colors.lightBlue,
              width: double.infinity,
              height: 50,
              child: Text(
                rng.nextInt(100).toString(),
                style: Theme.of(context).textTheme.bodyLarge!.copyWith(
                      color: Colors.white,
                    ),
              ),
            ),
            itemCount: 200,
          ),
        ),
      ),
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

我尝试用谷歌搜索几个小时,但没有找到任何有用的信息。有任何想法吗?谢谢

编辑:Niladri Raychaudhuri 的版本。还是同样的问题 在此输入图像描述

Ang*_*gel 7

动图示例

我找到了一个更好的方法来解决这个问题,很简单!

用这个包装接收刷新指示器或列表视图的主要内容

在行为上,您可以定义滚动类型,弹跳工作对我来说非常完美,当结束向下推时,我的内容将返回到向上

ScrollConfiguration(
              behavior: ScrollConfiguration.of(context).copyWith(
                physics: const BouncingScrollPhysics(),
                dragDevices: {
                  PointerDeviceKind.touch,
                  PointerDeviceKind.mouse,
                  PointerDeviceKind.trackpad
                },
              ),
Run Code Online (Sandbox Code Playgroud)

在你的代码上

 return MaterialApp(
  title: 'Flutter Demo',
  theme: ThemeData(
    primarySwatch: Colors.blue,
  ),
  home: Scaffold(
    appBar: AppBar(
      title: Text(title),
    ),
    body: ScrollConfiguration(
      behavior: ScrollConfiguration.of(context).copyWith(
        physics: const BouncingScrollPhysics(),
        dragDevices: {
          PointerDeviceKind.touch,
          PointerDeviceKind.mouse,
          PointerDeviceKind.trackpad
        },
      ),
      child: RefreshIndicator(
        onRefresh: () async => setState(() {
          title = 'Hey';
        }),
        child: ListView.builder(
          physics: const AlwaysScrollableScrollPhysics(),
          itemBuilder: (_, i) => Container(
            padding: const EdgeInsets.all(10),
            color: Colors.lightBlue,
            width: double.infinity,
            height: 50,
            child: Text(
              rng.nextInt(100).toString(),
              style: Theme.of(context).textTheme.bodyLarge!.copyWith(
                    color: Colors.white,
                  ),
            ),
          ),
          itemCount: 200,
        ),
      ),
    ),
  ),
);
Run Code Online (Sandbox Code Playgroud)


Nil*_*uri 0

更新2

添加PointerDeviceKind.trackpad到 PointerDeviceKind 集中

更新:

这是一个已知问题,或者可能是针对 Flutter Web 的,并且已在 Flutter Github 中报告

报告的问题

您需要自定义滚动行为来覆盖行为方法和 getter,例如 DragDevices。

按照步骤:

1.添加插件

custom_refresh_indicator: ^2.0.1

该解决方案也应该与本机刷新指示器一起使用。

2. 编写自定义滚动行为

class MyCustomScrollBehavior extends MaterialScrollBehavior {
  // Override behavior methods and getters like dragDevices
  @override
  Set<PointerDeviceKind> get dragDevices => {
        PointerDeviceKind.touch,
        PointerDeviceKind.mouse,
        PointerDeviceKind.trackpad
        // etc.
      };
}
Run Code Online (Sandbox Code Playgroud)

3.定义你的滚动控制器

 final ScrollController controller = ScrollController();
Run Code Online (Sandbox Code Playgroud)

4. 使用 ScrollConfiguration 小部件包装您的 listView 并向其添加自定义滚动行为

child: ScrollConfiguration(
        behavior: MyCustomScrollBehavior(),
        child: ListView.builder(
          physics: const AlwaysScrollableScrollPhysics(),
          itemBuilder: (_, i) => Container(
            padding: const EdgeInsets.all(10),
            color: Colors.lightBlue,
            width: double.infinity,
            height: 50,
            child: Text(
              rng.nextInt(100).toString(),
              style: Theme.of(context).textTheme.bodyLarge!.copyWith(
                    color: Colors.white,
                  ),
            ),
          ),
          itemCount: 200,
        ),
      ),
Run Code Online (Sandbox Code Playgroud)

5.最后用CustomRefreshIndicator或者原生RefreshIndicator包装一下

CustomRefreshIndicator(
      builder: MaterialIndicatorDelegate(
        builder: (context, controller) {
          return const Icon(
            Icons.ac_unit,
            color: Colors.blue,
            size: 30,
          );
        },
      ),
      child: ScrollConfiguration(
        behavior: MyCustomScrollBehavior(),
        child: ListView.builder(
          physics: const AlwaysScrollableScrollPhysics(),
          itemBuilder: (_, i) => Container(
            padding: const EdgeInsets.all(10),
            color: Colors.lightBlue,
            width: double.infinity,
            height: 50,
            child: Text(
              rng.nextInt(100).toString(),
              style: Theme.of(context).textTheme.bodyLarge!.copyWith(
                    color: Colors.white,
                  ),
            ),
          ),
          itemCount: 200,
        ),
      ),
      onRefresh: () async => setState(
        () {
          title = 'Hey';
          print('Page is refreshed');
        },
      ),
    ),
Run Code Online (Sandbox Code Playgroud)

最后注意:我在这里使用了 CustomRefreshIndicator,您可以使用本机 RefreshIndicator

完整代码

import 'package:custom_refresh_indicator/custom_refresh_indicator.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'dart:math';

void main() => runApp(const MyHomePage());

class MyHomePage extends StatefulWidget {
  const MyHomePage({
    Key? key,
  }) : super(key: key);

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

class MyCustomScrollBehavior extends MaterialScrollBehavior {
  // Override behavior methods and getters like dragDevices
  @override
  Set<PointerDeviceKind> get dragDevices => {
        PointerDeviceKind.touch,
        PointerDeviceKind.mouse,
        // etc.
      };
}

class _MyHomePageState extends State<MyHomePage> {
  String title = 'Hello';
  var rng = Random();
  final ScrollController controller = ScrollController();

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Scaffold(
        appBar: AppBar(
          title: Text(title),
        ),
        body: CustomRefreshIndicator(
          builder: MaterialIndicatorDelegate(
            builder: (context, controller) {
              return const Icon(
                Icons.ac_unit,
                color: Colors.blue,
                size: 30,
              );
            },
          ),
          child: ScrollConfiguration(
            behavior: MyCustomScrollBehavior(),
            child: ListView.builder(
              physics: const AlwaysScrollableScrollPhysics(),
              itemBuilder: (_, i) => Container(
                padding: const EdgeInsets.all(10),
                color: Colors.lightBlue,
                width: double.infinity,
                height: 50,
                child: Text(
                  rng.nextInt(100).toString(),
                  style: Theme.of(context).textTheme.bodyLarge!.copyWith(
                        color: Colors.white,
                      ),
                ),
              ),
              itemCount: 200,
            ),
          ),
          onRefresh: () async => setState(
            () {
              title = 'Hey';
              print('Page is refreshed');
            },
          ),
        ),
      ),
    );
  }
}
Run Code Online (Sandbox Code Playgroud)