桌面平台上的默认滚动条
摘要
#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
,并为您处理向Scrollbar
提供ScrollController
。
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
。扩展
ScrollBehavior
、MaterialScrollBehavior
或CupertinoScrollBehavior
以修改默认行为。- 使用您自己的
ScrollBehavior
,您可以通过设置MaterialApp.scrollBehavior
或CupertinoApp.scrollBehavior
来将其应用于整个应用程序。 - 或者,如果您只想将其应用于特定的小部件,请在相关小部件上方添加一个
ScrollConfiguration
,其中包含您自定义的ScrollBehavior
。
- 使用您自己的
然后您的可滚动小部件将继承并反映此行为。
- 除了创建您自己的
ScrollBehavior
之外,更改默认行为的另一种方法是复制现有的ScrollBehavior
,并切换所需的功能。- 在您的widget树中创建一个
ScrollConfiguration
,并使用copyWith
在当前上下文提供修改后的现有ScrollBehavior
副本。
- 在您的widget树中创建一个
迁移指南
#移除桌面平台上手动添加的 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');
}
);
// 仅在非桌面平台上手动添加 `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
#迁移前的代码:
// MaterialApps 以前有一个私有的 ScrollBehavior。
MaterialApp(
// ...
);
迁移后的代码:
// MaterialApps 以前有一个私有的 ScrollBehavior。
// 现在可以扩展它了。
class MyCustomScrollBehavior extends MaterialScrollBehavior {
// 重写行为方法,如 buildOverscrollIndicator 和 buildScrollbar
}
// 现在可以为整个应用程序配置 ScrollBehavior。
MaterialApp(
scrollBehavior: MyCustomScrollBehavior(),
// ...
);
为特定的小部件设置自定义 ScrollBehavior
#迁移前的代码:
final ScrollController controller = ScrollController();
ListView.builder(
controller: controller,
itemBuilder: (BuildContext context, int index) {
return Text('Item $index');
}
);
迁移后的代码:
// 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
#迁移前的代码:
final ScrollController controller = ScrollController();
ListView.builder(
controller: controller,
itemBuilder: (BuildContext context, int index) {
return Text('Item $index');
}
);
迁移后的代码:
// 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文档:
ScrollConfiguration
ScrollBehavior
MaterialScrollBehavior
CupertinoScrollBehavior
Scrollbar
CupertinoScrollbar
相关问题:
相关PR:
- Exposing ScrollBehaviors for app-wide settings
- Automatically applying Scrollbars on desktop platforms with configurable ScrollBehaviors
除非另有说明,否则本网站上的文档反映的是 Flutter 的最新稳定版本。页面最后更新于 2025-01-30。 查看源代码 或 报告问题。