桌面默认滚动条
概述
#ScrollBehavior
现在可以自动将Scrollbar
应用于桌面平台(Mac、Windows和Linux)上的可滚动组件。
背景
#在此更改之前,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
,并切换所需的功能。- 在您的组件树中创建一个
ScrollConfiguration
,并使用copyWith
提供当前上下文中现有ScrollBehavior
的修改副本。
- 在您的组件树中创建一个
迁移指南
#移除桌面手动滚动条
#迁移前的代码
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 文档
ScrollConfiguration
ScrollBehavior
MaterialScrollBehavior
CupertinoScrollBehavior
Scrollbar
CupertinoScrollbar
相关问题
相关 PR