概述

#

ScrollBehavior 现在允许或禁止来自指定 PointerDeviceKind 的拖动滚动。默认情况下,ScrollBehavior.dragDevices 允许通过除 PointerDeviceKind.mouse 之外的所有 PointerDeviceKind 来拖动滚动小部件。

背景

#

在此更改之前,所有 PointerDeviceKind 都可以拖动 Scrollable 小部件。这与开发者在使用鼠标输入设备与 Flutter 应用程序交互时的预期不符。这也使得执行其他鼠标手势变得困难,例如选择包含在 Scrollable 小部件中的文本。

现在,继承的 ScrollBehavior 会根据 ScrollBehavior.dragDevices 来管理哪些设备可以拖动滚动小部件。允许拖动的 PointerDeviceKind 集合就是这个集合。

变更说明

#

此更改解决了通过鼠标拖动意外滚动的问题。

如果您在应用程序中依赖于之前的行为,有几种方法可以控制和配置此功能。

  • 扩展 ScrollBehaviorMaterialScrollBehaviorCupertinoScrollBehavior,通过覆盖 ScrollBehavior.dragDevices 来修改默认行为。

    • 有了您自己的 ScrollBehavior,您可以通过设置 MaterialApp.scrollBehaviorCupertinoApp.scrollBehavior 将其应用于整个应用程序。
    • 或者,如果您只想将其应用于特定组件,请在相关组件上方添加一个 ScrollConfiguration,并使用您的自定义 ScrollBehavior

您的滚动小部件将继承并反映此行为。

  • 除了创建自己的 ScrollBehavior,改变默认行为的另一种选择是复制现有的 ScrollBehavior,并设置不同的 dragDevices
    • 在您的组件树中创建一个 ScrollConfiguration,并使用 copyWith 提供当前上下文中现有 ScrollBehavior 的修改副本。

为了适应 ScrollBehavior 中拖动设备的新的配置,GestureDetector.kind 已被弃用,以及该参数的所有子类实例。Flutter 提供了一个修复程序,可以将所有手势检测器从 kind 迁移到 supportedDevices。之前的参数 kind 只允许使用一个 PointerDeviceKind 来过滤手势。引入 supportedDevices 使得可以支持多个有效的 PointerDeviceKind

迁移指南

#

为应用程序设置自定义 ScrollBehavior

#

迁移前的代码

dart
MaterialApp(
  // ...
);

迁移后的代码

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

// Set ScrollBehavior for an entire application.
MaterialApp(
  scrollBehavior: MyCustomScrollBehavior(),
  // ...
);

为特定组件设置自定义 ScrollBehavior

#

迁移前的代码

dart
final ScrollController controller = ScrollController();
ListView.builder(
  controller: controller,
  itemBuilder: (BuildContext context, int index) {
   return Text('Item $index');
 }
);

迁移后的代码

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

// ScrollBehavior can be set for a specific widget.
final ScrollController controller = ScrollController();
ScrollConfiguration(
  behavior: MyCustomScrollBehavior(),
  child: ListView.builder(
    controller: controller,
    itemBuilder: (BuildContext context, int index) {
     return Text('Item $index');
    }
  ),
);

复制并修改现有 ScrollBehavior

#

迁移前的代码

dart
final ScrollController controller = ScrollController();
ListView.builder(
  controller: controller,
  itemBuilder: (BuildContext context, int index) {
   return Text('Item $index');
 }
);

迁移后的代码

dart
// ScrollBehavior can be copied and adjusted.
final ScrollController controller = ScrollController();
ScrollConfiguration(
  behavior: ScrollConfiguration.of(context).copyWith(dragDevices: {
    PointerDeviceKind.touch,
    PointerDeviceKind.mouse,
  }),
  child: ListView.builder(
    controller: controller,
    itemBuilder: (BuildContext context, int index) {
     return Text('Item $index');
    }
  ),
);

GestureDetectors 从 kind 迁移到 supportedDevices

#

迁移前的代码

dart
VerticalDragGestureRecognizer(
  kind: PointerDeviceKind.touch,
);

迁移后的代码

dart
VerticalDragGestureRecognizer(
  supportedDevices: <PointerDeviceKind>{ PointerDeviceKind.touch },
);

时间线

#

发布版本:2.3.0-12.0.pre
稳定版本:2.5

参考资料

#

API 文档

相关议题

相关 PR