Skip to main content

桌面平台上的默认滚动条

摘要

#

ScrollBehavior现在会自动在桌面平台(Mac、Windows 和 Linux)上的滚动小部件应用Scrollbar

背景

#

在此更改之前,开发人员需要在所有平台上手动将Scrollbar应用于滚动小部件。这与开发人员在桌面平台上执行Flutter应用程序时的预期不符。

现在,继承的ScrollBehavior会自动将Scrollbar应用于大多数滚动小部件。这类似于ScrollBehavior创建GlowingOverscrollIndicator的方式。下面列出了不受此行为影响的少数几个小部件。

为了更好地管理和控制此功能,ScrollBehavior也进行了更新。应用GlowingOverscrollIndicatorbuildViewportChrome方法已被弃用。现在,ScrollBehavior支持用于装饰视口的单个方法buildScrollbarbuildOverscrollIndicator。可以重写这些方法来控制在可滚动内容周围构建的内容。

此外,ScrollBehavior子类MaterialScrollBehaviorCupertinoScrollBehavior已公开,允许开发人员扩展和构建框架中其他现有的ScrollBehavior。这些子类以前是私有的。

变更描述

#

以前的方法要求开发人员在所有平台上创建自己的Scrollbar。在某些用例中,需要将ScrollController提供给Scrollbar和可滚动小部件。

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

ScrollBehavior现在在桌面平台上执行时会自动应用Scrollbar,并为您处理向Scrollbar提供ScrollController

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

框架中的一些小部件不受此自动Scrollbar应用的影响。它们是:

  • EditableText,当maxLines为1时。
  • ListWheelScrollView
  • PageView
  • NestedScrollView

由于这些小部件手动重写继承的ScrollBehavior以移除Scrollbar,因此所有这些小部件现在都有一个scrollBehavior参数,以便可以使用它来代替重写。

此更改在开发过程中没有导致任何测试失败、崩溃或错误消息,但如果您在桌面平台上手动添加Scrollbar,则可能会导致应用程序中呈现两个Scrollbar

如果您在应用程序中看到这种情况,有几种方法可以控制和配置此功能。

  • 在桌面平台上运行时,移除应用程序中手动应用的Scrollbar

  • 扩展ScrollBehaviorMaterialScrollBehaviorCupertinoScrollBehavior以修改默认行为。

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

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

  • 除了创建您自己的ScrollBehavior之外,更改默认行为的另一种方法是复制现有的ScrollBehavior,并切换所需的功能。
    • 在您的widget树中创建一个ScrollConfiguration,并使用copyWith在当前上下文提供修改后的现有ScrollBehavior副本。

迁移指南

#

移除桌面平台上手动添加的 Scrollbar

#

迁移前的代码:

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

迁移后的代码:

dart
final ScrollController controller = ScrollController();
final Widget child = ListView.builder(
  controller: controller,
  itemBuilder: (BuildContext context, int index) {
    return Text('Item $index');
  }
);
// 仅在非桌面平台上手动添加 `Scrollbar`。
// 或者,请参阅其他迁移以更改 `ScrollBehavior`。
switch (currentPlatform) {
  case TargetPlatform.linux:
  case TargetPlatform.macOS:
  case TargetPlatform.windows:
    return child;
  case TargetPlatform.android:
  case TargetPlatform.fuchsia:
  case TargetPlatform.iOS:
    return Scrollbar(
      controller: controller,
      child: child;
    );
}

为您的应用程序设置自定义 ScrollBehavior

#

迁移前的代码:

dart
// MaterialApps 以前有一个私有的 ScrollBehavior。
MaterialApp(
  // ...
);

迁移后的代码:

dart
// MaterialApps 以前有一个私有的 ScrollBehavior。
// 现在可以扩展它了。
class MyCustomScrollBehavior extends MaterialScrollBehavior {
  // 重写行为方法,如 buildOverscrollIndicator 和 buildScrollbar
}

// 现在可以为整个应用程序配置 ScrollBehavior。
MaterialApp(
  scrollBehavior: MyCustomScrollBehavior(),
  // ...
);

为特定的小部件设置自定义 ScrollBehavior

#

迁移前的代码:

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

迁移后的代码:

dart
// MaterialApps 以前有一个私有的 ScrollBehavior。
// 现在可以扩展它了。
class MyCustomScrollBehavior extends MaterialScrollBehavior {
  // 重写行为方法,如 buildOverscrollIndicator 和 buildScrollbar
}

// 可以为特定的小部件设置 ScrollBehavior。
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 可以被复制和调整。
final ScrollController controller = ScrollController();
ScrollConfiguration(
  behavior: ScrollConfiguration.of(context).copyWith(scrollbars: false),
  child: ListView.builder(
    controller: controller,
    itemBuilder: (BuildContext context, int index) {
     return Text('Item $index');
    }
  ),
);

时间线

#

包含的版本:2.2.0-10.0.pre
稳定版:2.2.0

参考

#

API文档:

相关问题:

相关PR: