桌面上的默认滚动条
概述
#ScrollBehavior 现在会在桌面平台(Mac、Windows 和 Linux)上自动为滚动控件应用 Scrollbar。
背景
#在此更改之前,Scrollbar 需要由开发者在所有平台上手动应用于滚动控件。这与用户在桌面平台上运行 Flutter 应用程序时的预期不符。
现在,继承的 ScrollBehavior 会自动将 Scrollbar 应用于大多数滚动控件。这类似于 ScrollBehavior 创建 GlowingOverscrollIndicator 的方式。少数豁免此行为的控件列在下方。
为了更好地管理和控制此功能,ScrollBehavior 也得到了更新。用于应用 GlowingOverscrollIndicator 的 buildViewportChrome 方法已被弃用。取而代之的是,ScrollBehavior 现在支持用于装饰视口的独立方法:buildScrollbar 和 buildOverscrollIndicator。可以覆盖这些方法来控制滚动区域周围的内容。
此外,ScrollBehavior 的子类 MaterialScrollBehavior 和 CupertinoScrollBehavior 已公开,允许开发者扩展和构建框架中其他现有的 ScrollBehavior。这些子类以前是私有的。
变更说明
#以前的方法要求开发者在所有平台上创建自己的 Scrollbar。在某些用例中,需要将 ScrollController 提供给 Scrollbar 和滚动控件。
final ScrollController controller = ScrollController();
Scrollbar(
controller: controller,
child: ListView.builder(
controller: controller,
itemBuilder: (BuildContext context, int index) {
return Text('Item $index');
}
)
);ScrollBehavior 现在在桌面平台上执行时会自动应用 Scrollbar,并为您处理将 ScrollController 提供给 Scrollbar 的操作。
final ScrollController controller = ScrollController();
ListView.builder(
controller: controller,
itemBuilder: (BuildContext context, int index) {
return Text('Item $index');
}
);框架中的一些控件豁免了此自动 Scrollbar 应用。它们是:
EditableText,当maxLines为 1 时。ListWheelScrollViewPageViewNestedScrollView
由于这些控件手动覆盖了继承的 ScrollBehavior 以移除 Scrollbar,因此所有这些控件现在都具有 scrollBehavior 参数,以便可以提供一个来代替覆盖。
此更改在开发过程中没有导致任何测试失败、崩溃或错误消息,但如果您正在桌面平台上手动添加 Scrollbar,则可能会导致应用程序中渲染两个 Scrollbar。
如果您在应用程序中看到此情况,有几种方法可以控制和配置此功能。
在桌面运行时,从应用程序中移除手动应用的
Scrollbar。扩展
ScrollBehavior、MaterialScrollBehavior或CupertinoScrollBehavior来修改默认行为。- 有了您自己的
ScrollBehavior,您可以通过设置MaterialApp.scrollBehavior或CupertinoApp.scrollBehavior将其应用于整个应用程序。 - 或者,如果您只想将其应用于特定组件,请在相关组件上方添加一个
ScrollConfiguration,并使用您的自定义ScrollBehavior。
- 有了您自己的
您的滚动控件将继承此设置并反映此行为。
- 与创建自己的
ScrollBehavior不同,更改默认行为的另一种选择是复制现有的ScrollBehavior,然后切换所需的设置。- 在您的组件树中创建一个
ScrollConfiguration,并使用copyWith提供当前上下文中现有ScrollBehavior的修改副本。
- 在您的组件树中创建一个
迁移指南
#移除桌面上手动 Scrollbar
#迁移前的代码
final ScrollController controller = ScrollController();
Scrollbar(
controller: controller,
child: ListView.builder(
controller: controller,
itemBuilder: (BuildContext context, int index) {
return Text('Item $index');
}
)
);迁移后的代码
final ScrollController controller = ScrollController();
final Widget child = ListView.builder(
controller: controller,
itemBuilder: (BuildContext context, int index) {
return Text('Item $index');
}
);
// Only manually add a `Scrollbar` when not on desktop platforms.
// Or, see other migrations for changing `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
#迁移前的代码
// MaterialApps previously had a private ScrollBehavior.
MaterialApp(
// ...
);迁移后的代码
// MaterialApps previously had a private ScrollBehavior.
// This is available to extend now.
class MyCustomScrollBehavior extends MaterialScrollBehavior {
// Override behavior methods like buildOverscrollIndicator and buildScrollbar
}
// ScrollBehavior can now be configured for an entire application.
MaterialApp(
scrollBehavior: MyCustomScrollBehavior(),
// ...
);为特定组件设置自定义 ScrollBehavior
#迁移前的代码
final ScrollController controller = ScrollController();
ListView.builder(
controller: controller,
itemBuilder: (BuildContext context, int index) {
return Text('Item $index');
}
);迁移后的代码
// MaterialApps previously had a private ScrollBehavior.
// This is available to extend now.
class MyCustomScrollBehavior extends MaterialScrollBehavior {
// Override behavior methods like buildOverscrollIndicator and buildScrollbar
}
// 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
#迁移前的代码
final ScrollController controller = ScrollController();
ListView.builder(
controller: controller,
itemBuilder: (BuildContext context, int index) {
return Text('Item $index');
}
);迁移后的代码
// ScrollBehavior can be copied and adjusted.
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 文档
ScrollConfigurationScrollBehaviorMaterialScrollBehaviorCupertinoScrollBehaviorScrollbarCupertinoScrollbar
相关问题
相关 PR