Flutter.源码分析 ScrollView flutter/packages/flutter/lib/src/widgets/scroll_view.dart/ScrollView
李俊才 的个人博客:blog.csdn.net/qq_28550263
本文地址:blog.csdn.net/qq_28550263…
本文供给Flutter结构中ScrollView类源码注释的中文翻译以及必要的分析说明。
目 录
- 1. 类注释部分
- 2. 结构办法部分
- 3. scrollDirection 特点部分
- 4. reverse 特点部分
- 5. controller 特点部分
- 6. primary特点部分
- 7. physics特点部分
- 8. scrollBehavior特点部分
- 9. shrinkWrap特点部分
- 10. center特点部分
- 11. anchor特点部分
- 12. cacheExtent特点部分
- 13. semanticChildCount特点部分
- 14. dragStartBehavior特点部分
- 15. keyboardDismissBehavior特点部分
- 16. restorationId特点部分
- 17. clipBehavior特点部分
- 18. getDirection办法部分
- 19. buildSlivers办法部分
- 20. buildViewport办法部分
- 21. build办法部分
- 22. 其它代码
1. 类注释部分
/// 一个组合了 [Scrollable] 和 [Viewport] 的组件,用于在一个维度上创立一个可交互的翻滚内容窗格。
///
/// 可翻滚组件由三部分组成:
///
/// 1. 一个 [Scrollable] 组件,它监听各种用户手势并完成翻滚的交互设计。
/// 2. 一个视口组件,如 [Viewport] 或 [ShrinkWrappingViewport],它经过仅显现翻滚视图内部的部分组件来完成翻滚的视觉设计。
/// 3. 一个或多个 slivers,这些组件能够组合起来创立各种翻滚作用,如列表、网格和打开的头部。
///
/// [ScrollView] 经过创立 [Scrollable] 和视口,并将创立 slivers 的使命托付给其子类,来和谐这些部分。
///
/// 要了解更多关于 slivers 的信息,请参看 [CustomScrollView.slivers]。
///
/// 要操控翻滚视图的初始翻滚偏移量,供给一个设置了 [ScrollController.initialScrollOffset] 特点的 [controller]。
///
/// 另请参看:
///
/// * [ListView],这是一个常用的 [ScrollView],显现一个翻滚的、线性的子组件列表。
/// * [PageView],这是一个翻滚的子组件列表,每个子组件都是视口的巨细。
/// * [GridView],这是一个 [ScrollView],显现一个翻滚的、二维的子组件数组。
/// * [CustomScrollView],这是一个 [ScrollView],运用 slivers 创立自界说翻滚作用。
/// * [ScrollNotification] 和 [NotificationListener],它们能够用来调查翻滚方位,而无需运用 [ScrollController]。
/// * [TwoDimensionalScrollView],这是一个相似的组件 [ScrollView],它在两个维度上翻滚。
abstract class ScrollView extends StatelessWidget {
2. 结构办法部分
/// 创立一个能够翻滚的组件。
///
/// 假如没有供给 [controller],则 [ScrollView.primary] 参数默许为笔直翻滚视图的 true。假如 [primary] 清晰设置为 true,则 [controller] 参数有必要为 null。假如 [primary] 为 true,则将最近的围住组件的 [PrimaryScrollController] 附加到此翻滚视图。
///
/// 假如 [shrinkWrap] 参数为 true,则 [center] 参数有必要为 null。
///
/// [scrollDirection]、[reverse] 和 [shrinkWrap] 参数有必要不为 null。
///
/// [anchor] 参数有必要为非 null,而且在 0.0 到 1.0 的范围内。
const ScrollView({
super.key,
this.scrollDirection = Axis.vertical,
this.reverse = false,
this.controller,
this.primary,
ScrollPhysics? physics,
this.scrollBehavior,
this.shrinkWrap = false,
this.center,
this.anchor = 0.0,
this.cacheExtent,
this.semanticChildCount,
this.dragStartBehavior = DragStartBehavior.start,
this.keyboardDismissBehavior = ScrollViewKeyboardDismissBehavior.manual,
this.restorationId,
this.clipBehavior = Clip.hardEdge,
}) : assert(
!(controller != null && (primary ?? false)),
'Primary ScrollViews obtain their ScrollController via inheritance '
'from a PrimaryScrollController widget. You cannot both set primary to '
'true and pass an explicit controller.',
),
assert(!shrinkWrap || center == null),
assert(anchor >= 0.0 && anchor <= 1.0),
assert(semanticChildCount == null || semanticChildCount >= 0),
physics = physics ?? ((primary ?? false) || (primary == null && controller == null && identical(scrollDirection, Axis.vertical)) ? const AlwaysScrollableScrollPhysics() : null);
3. scrollDirection 特点部分
/// {@template flutter.widgets.scroll_view.scrollDirection}
/// 翻滚视图偏移量增加的 [Axis]。
///
/// 关于可能产生活动翻滚的方向,请拜见 [ScrollDirection]。
///
/// 默许为 [Axis.vertical]。
/// {@endtemplate}
final Axis scrollDirection;
4. reverse 特点部分
/// {@template flutter.widgets.scroll_view.reverse}
/// 翻滚视图是否按阅读方向翻滚。
///
/// 例如,假如阅读方向是从左到右,且 [scrollDirection] 为 [Axis.horizontal],
/// 那么当 [reverse] 为 false 时,翻滚视图从左向右翻滚,当 [reverse] 为 true 时,从右向左翻滚。
///
/// 相似地,假如 [scrollDirection] 为 [Axis.vertical],那么当 [reverse] 为 false 时,
/// 翻滚视图从上向下翻滚,当 [reverse] 为 true 时,从下向上翻滚。
///
/// 默许为 false。
/// {@endtemplate}
final bool reverse;
5. controller 特点部分
/// {@template flutter.widgets.scroll_view.controller}
/// 可用于操控翻滚视图翻滚到哪个方位的目标。
///
/// 假如 [primary] 为 true,则有必要为 null。
///
/// [ScrollController] 有多个用途。它能够用来操控初始翻滚方位(拜见 [ScrollController.initialScrollOffset])。
/// 它能够用来操控翻滚视图是否应主动在 [PageStorage] 中保存和康复其翻滚方位(拜见 [ScrollController.keepScrollOffset])。
/// 它能够用来读取当前翻滚方位(拜见 [ScrollController.offset]),或改动它(拜见 [ScrollController.animateTo])。
/// {@endtemplate}
final ScrollController? controller;
6. primary特点部分
/// {@template flutter.widgets.scroll_view.primary}
/// 是否是与父 [PrimaryScrollController] 相关的主翻滚视图。
///
/// 当此值为 true 时,即便翻滚视图没有满足的内容实际翻滚,也能够翻滚。不然,默许情况下,用户只要在视图有满足的内容时才干翻滚。拜见 [physics]。
///
/// 同样,当为 true 时,翻滚视图用于默许的 [ScrollAction]。假如 ScrollAction 没有被运用程序的其他聚集部分处理,
/// 则将运用此翻滚视图评价 ScrollAction,例如,履行 [Shortcuts] 键事情,如页面上下。
///
/// 在 iOS 上,这还标识了将呼应状况栏点击而翻滚到顶部的翻滚视图。
///
/// 不能在供给 `controller` 的 [ScrollController] 时为 true,只要一个 ScrollController 能够与 ScrollView 相关。
///
/// 设置为 false 将清晰阻止承继任何 [PrimaryScrollController]。
///
/// 默许为 null。当为 null,且没有供给操控器时,运用 [PrimaryScrollController.shouldInherit] 决议主动承继。
///
/// 默许情况下,每个 [ModalRoute] 注入的 [PrimaryScrollController] 都装备为在 [TargetPlatformVariant.mobile] 上主动承继
/// [Axis.vertical] 翻滚方向的 ScrollViews。在您的运用中增加另一个将覆盖其上方的 PrimaryScrollController。
///
/// 以下视频包括有关翻滚操控器、PrimaryScrollController 组件及其对您的运用的影响的更多信息:
///
/// {@youtube 560 315 https://www.youtube.com/watch?v=33_0ABjFJUU}
///
/// {@endtemplate}
final bool? primary;
从注释中能够了解到:
primary 特点决议了 ScrollView 是否是与父 PrimaryScrollController 相关的主翻滚视图。
当 primary 特点为 true 时,即便翻滚视图没有满足的内容能够实际翻滚,也能够翻滚。不然,默许情况下,用户只要在视图有满足的内容时才干翻滚。
此外,当 primary 为 true 时,翻滚视图用于默许的 ScrollAction。假如 ScrollAction 没有被运用程序的其他聚集部分处理,那么将运用此翻滚视图评价 ScrollAction,例如,履行 Shortcuts 键事情,如页面上下。
在 iOS 上,primary 为 true 还标识了将呼应状况栏点击而翻滚到顶部的翻滚视图。
注意,不能在供给 controller 的 ScrollController 时将 primary 设置为 true,由于只要一个 ScrollController 能够与 ScrollView 相关。
设置 primary 为 false 将清晰阻止承继任何 PrimaryScrollController。
primary 的默许值为 null。当 primary 为 null,且没有供给操控器时,将运用 PrimaryScrollController.shouldInherit 决议是否主动承继。
默许情况下,每个 ModalRoute 注入的 PrimaryScrollController 都装备为在 TargetPlatformVariant.mobile 上主动承继 Axis.vertical 翻滚方向的 ScrollViews。在您的运用中增加另一个 PrimaryScrollController 将覆盖其上方的 PrimaryScrollController。
7. physics特点部分
/// {@template flutter.widgets.scroll_view.physics}
/// 翻滚视图应怎么呼运用户输入。
///
/// 例如,确认用户停止拖动翻滚视图后,翻滚视图怎么继续动画。
///
/// 默许为匹配渠道约定。此外,假如 [primary] 为 false,那么用户只要在有满足的内容能够翻滚时才干翻滚,
/// 而假如 [primary] 为 true,他们总是能够测验翻滚。
///
/// 要强制翻滚视图始终能够翻滚,即便没有满足的内容,就像 [primary] 为 true 相同,但不必定要将其设置为 true,
/// 供给一个 [AlwaysScrollableScrollPhysics] 物理目标,如下所示:
///
/// ```dart
/// physics: const AlwaysScrollableScrollPhysics(),
/// ```
///
///
/// 要强制翻滚视图运用默许的渠道约定,而且假如内容缺乏,不管 [primary] 的值怎么,都不可翻滚,
/// 供给一个清晰的 [ScrollPhysics] 目标,如下所示:
///
/// ```dart
/// physics: const ScrollPhysics(),
/// ```
///
/// 物理能够动态地改动(经过在后续的构建中供给一个新的目标),但新的物理只要在供给的目标的 _类_ 改动时才会收效。
/// 只是结构一个具有不同装备的新实例是缺乏以使物理从头运用的。 (这是由于终究运用的目标是动态生成的,
/// 这可能相对贵重,假如每帧都猜测性地创立这个目标以查看物理是否应该更新,那将是低效的。)
/// {@endtemplate}
///
/// 假如向 [scrollBehavior] 供给了清晰的 [ScrollBehavior],那么该行为供给的 [ScrollPhysics] 将优先于 [physics]。
final ScrollPhysics? physics;
从注释能够了解:
physics
特点在 ScrollView 中操控翻滚行为的物理特性,例如翻滚速度、翻滚方向、翻滚是否会反弹等。
- 默许情况下,
physics
会依据渠道(iOS或Android)来挑选适宜的翻滚行为。假如primary
特点为false
,用户只要在内容满足多,足以翻滚时才干翻滚。假如primary
为true
,即便内容缺乏,用户也能够测验翻滚。 - 假如你想让ScrollView不管内容是否满足,都能够翻滚,你能够设置
physics
为AlwaysScrollableScrollPhysics。这种情况下,即便primary
不是true
,翻滚视图也总是能够翻滚。 - 假如你想让ScrollView严格依照渠道约定进行翻滚,即当内容缺乏时,不管
primary
的值怎么,都不能翻滚,你能够设置physics
为ScrollPhysics。 -
physics
特点能够动态改动,可是只要当你供给的物理目标的类产生改动时,新的物理特点才会收效。这是由于物理目标的创立可能会有必定的开支,假如每一帧都创立新的物理目标来查看是否需求更新物理特点,可能会导致性能问题。 - 假如你为
scrollBehavior
供给了一个ScrollBehavior目标,那么这个目标供给的ScrollPhysics会优先于ScrollView的physics
特点。
8. scrollBehavior特点部分
/// {@macro flutter.widgets.shadow.scrollBehavior}
///
/// [ScrollBehavior] 也供给 [ScrollPhysics]。假如在 [physics] 中供给了清晰的 [ScrollPhysics],它将优先,
/// 然后是 [scrollBehavior],然后是承继的先人 [ScrollBehavior]。
final ScrollBehavior? scrollBehavior;
9. shrinkWrap特点部分
/// {@template flutter.widgets.scroll_view.shrinkWrap}
/// 翻滚视图在 [scrollDirection] 中的范围是否应由正在查看的内容确认。
///
/// 假如翻滚视图没有缩短包装,则翻滚视图将扩展到 [scrollDirection] 中答应的最大巨细。
/// 假如翻滚视图在 [scrollDirection] 中的约束是无界的,则 [shrinkWrap] 有必要为 true。
///
/// 缩短包装翻滚视图的内容比扩展到答应的最大巨细要贵重得多,由于内容能够在翻滚过程中扩展和缩短,
/// 这意味着每逢翻滚方位改动时,都需求从头计算翻滚视图的巨细。
///
/// 默许为 false。
///
/// {@youtube 560 315 https://www.youtube.com/watch?v=LUqDNnv_dh0}
/// {@endtemplate}
final bool shrinkWrap;
10. center特点部分
/// [GrowthDirection.forward] 成长方向的第一个子元素。
///
/// [center] 之后的子元素将相关于 [center] 在由 [scrollDirection] 和 [reverse] 确认的 [AxisDirection] 中放置。
/// [center] 之前的子元素将相关于 [center] 放置在轴方向的相反方向。这使得 [center] 成为成长方向的拐点。
///
/// [center] 有必要是 [buildSlivers] 构建的滑块之一的键。
///
/// 在 [ScrollView] 的内置子类中,只要 [CustomScrollView] 支持 [center];
/// 关于该类,给定的键有必要是 [CustomScrollView.slivers] 列表中的滑块之一的键。
///
/// 大多数翻滚视图默许按 [GrowthDirection.forward] 排序。
/// 更改 [ScrollView.anchor]、[ScrollView.center] 或两者的默许值,能够为翻滚视图装备 [GrowthDirection.reverse]。
///
/// {@tool dartpad}
/// 此示例显现了一个 [CustomScrollView],在 [AppBar.bottom] 中有 [Radio] 按钮,
/// 能够改动 [AxisDirection] 来展现不同的装备。[CustomScrollView.anchor] 和 [CustomScrollView.center]
/// 特点也被设置为使 0 翻滚偏移坐落视口的中间,[GrowthDirection.forward] 和 [GrowthDirection.reverse]
/// 在两边显现。同享 [CustomScrollView.center] 键的滑块坐落 [CustomScrollView.anchor] 的方位。
///
/// ** 拜见 examples/api/lib/rendering/growth_direction/growth_direction.0.dart 中的代码 **
/// {@end-tool}
///
/// 另请拜见:
///
/// * [anchor],它操控 [center] 在视口中的对齐方式。
final Key? center;
11. anchor特点部分
/// {@template flutter.widgets.scroll_view.anchor}
/// 零翻滚偏移的相对方位。
///
/// 例如,假如 [anchor] 是 0.5,由 [scrollDirection] 和 [reverse] 确认的 [AxisDirection] 是 [AxisDirection.down] 或
/// [AxisDirection.up],那么零翻滚偏移在视口中笔直居中。假如 [anchor] 是 1.0,轴方向是 [AxisDirection.right],
/// 那么零翻滚偏移在视口的左边缘。
///
/// 大多数翻滚视图默许按 [GrowthDirection.forward] 排序。
/// 更改 [ScrollView.anchor]、[ScrollView.center] 或两者的默许值,能够为翻滚视图装备 [GrowthDirection.reverse]。
///
/// {@tool dartpad}
/// 此示例显现了一个 [CustomScrollView],在 [AppBar.bottom] 中有 [Radio] 按钮,
/// 能够改动 [AxisDirection] 来展现不同的装备。[CustomScrollView.anchor] 和 [CustomScrollView.center]
/// 特点也被设置为使 0 翻滚偏移坐落视口的中间,[GrowthDirection.forward] 和 [GrowthDirection.reverse]
/// 在两边显现。同享 [CustomScrollView.center] 键的滑块坐落 [CustomScrollView.anchor] 的方位。
///
/// ** 拜见 examples/api/lib/rendering/growth_direction/growth_direction.0.dart 中的代码 **
/// {@end-tool}
/// {@endtemplate}
final double anchor;
12. cacheExtent特点部分
/// {@macro flutter.rendering.RenderViewportBase.cacheExtent}
final double? cacheExtent;
13. semanticChildCount特点部分
/// 将供给语义信息的子元素数量。
///
/// [ScrollView] 的一些子类型能够主动揣度此值。例如 [ListView] 将运用子列表中的组件数量,
/// 而 [ListView.separated] 结构函数将运用该数量的一半。
///
/// 关于 [CustomScrollView] 和其他类型,它们不接收构建器或组件列表,有必要清晰供给子计数。假如数量不知道或无限,则应保留未设置或设置为 null。
///
/// 另请拜见:
///
/// * [SemanticsConfiguration.scrollChildCount],对应的语义特点。
final int? semanticChildCount;
14. dragStartBehavior特点部分
/// {@macro flutter.widgets.scrollable.dragStartBehavior}
final DragStartBehavior dragStartBehavior;
15. keyboardDismissBehavior特点部分
/// {@template flutter.widgets.scroll_view.keyboardDismissBehavior}
/// 界说此 [ScrollView] 怎么主动消除键盘的 [ScrollViewKeyboardDismissBehavior]。
/// {@endtemplate}
final ScrollViewKeyboardDismissBehavior keyboardDismissBehavior;
16. restorationId特点部分
/// {@macro flutter.widgets.scrollable.restorationId}
final String? restorationId;
17. clipBehavior特点部分
/// {@macro flutter.material.Material.clipBehavior}
///
/// 默许为 [Clip.hardEdge]。
final Clip clipBehavior;
18. getDirection办法部分
/// 回来翻滚视图翻滚的 [AxisDirection]。
///
/// 结合 [scrollDirection] 和 [reverse] 布尔值来获取详细的 [AxisDirection]。
///
/// 假如 [scrollDirection] 是 [Axis.horizontal],在挑选详细的 [AxisDirection] 时也会考虑环境 [Directionality]。
/// 例如,假如环境 [Directionality] 是 [TextDirection.rtl],那么非反向的 [AxisDirection] 是 [AxisDirection.left],
/// 反向的 [AxisDirection] 是 [AxisDirection.right]。
@protected
AxisDirection getDirection(BuildContext context) {
return getAxisDirectionFromAxisReverseAndDirectionality(context, scrollDirection, reverse);
}
19. buildSlivers办法部分
/// 构建放置在视口内的组件列表。
///
/// 子类应重写此办法,以构建视口内部的滑块。
///
/// 要了解更多关于滑块的信息,请拜见 [CustomScrollView.slivers]。
@protected
List<Widget> buildSlivers(BuildContext context);
20. buildViewport办法部分
/// 构建视口(viewport)。
///
/// 子类能够重写此办法来改动视口的构建方式。假如 [shrinkWrap] 为 true,那么默许完成运用 [ShrinkWrappingViewport],
/// 不然运用惯例的 [Viewport]。
///
/// `offset` 参数是从 [Scrollable.viewportBuilder] 获取的值。
///
/// `axisDirection` 参数是从 [getDirection] 获取的值,该值默许运用 [scrollDirection] 和 [reverse]。
///
/// `slivers` 参数是从 [buildSlivers] 获取的值。
@protected
Widget buildViewport(
BuildContext context,
ViewportOffset offset,
AxisDirection axisDirection,
List<Widget> slivers,
) {
assert(() {
switch (axisDirection) {
case AxisDirection.up:
case AxisDirection.down:
return debugCheckHasDirectionality(
context,
// 为了确认翻滚视图的交叉轴方向
why: 'to determine the cross-axis direction of the scroll view',
// 笔直翻滚视图创立试图从环境 Directionality 确认其交叉轴方向的 Viewport 组件。
hint: 'Vertical scroll views create Viewport widgets that try to determine their cross axis direction '
'from the ambient Directionality.',
);
case AxisDirection.left:
case AxisDirection.right:
return true;
}
}());
if (shrinkWrap) {
return ShrinkWrappingViewport(
axisDirection: axisDirection,
offset: offset,
slivers: slivers,
clipBehavior: clipBehavior,
);
}
return Viewport(
axisDirection: axisDirection,
offset: offset,
slivers: slivers,
cacheExtent: cacheExtent,
center: center,
anchor: anchor,
clipBehavior: clipBehavior,
);
}
buildViewport 办法用于构建 ScrollView 的视口。
视口是 ScrollView 中可见的部分,它决议了用户在屏幕上看到的内容。视口内的内容能够翻滚,而视口外的内容则不可见。
buildViewport
办法接收四个参数:context
、offset
、axisDirection
和slivers
。
参数 | 描述 |
---|---|
context | 是当前 BuildContext,它包括了当前 widget 的方位信息和状况 |
offset | 是从 Scrollable.viewportBuilder 获取的值,它表明当前翻滚的方位 |
axisDirection | 是从 getDirection 办法获取的值,它表明翻滚的方向。默许情况下,它运用 scrollDirection 和 reverse 特点来确认 |
slivers | 是从 buildSlivers 办法获取的值,它是一个 Widget 列表,表明视口内的内容 |
在buildViewport
办法中:
- 首要会依据
axisDirection
的值进行一些断语查看,以确保翻滚视图的交叉轴方向是正确的。 - 然后,假如
shrinkWrap
特点为true
,则运用ShrinkWrappingViewport来构建视口。ShrinkWrappingViewport是一种特殊的视口,它会依据其子组件的巨细来调整自己的巨细。 - 假如
shrinkWrap
特点为false
,则运用惯例的Viewport来构建视口。Viewport会尽可能地扩展到最大的可用空间。 - 最后,不管是ShrinkWrappingViewport还是Viewport,都会运用传入的
axisDirection
、offset
和slivers
参数,以及ScrollView的clipBehavior
、cacheExtent
、center
和anchor
特点来进行构建。
21. build办法部分
@override
Widget build(BuildContext context) {
final List<Widget> slivers = buildSlivers(context);
final AxisDirection axisDirection = getDirection(context);
final bool effectivePrimary = primary
?? controller == null && PrimaryScrollController.shouldInherit(context, scrollDirection);
final ScrollController? scrollController = effectivePrimary
? PrimaryScrollController.maybeOf(context)
: controller;
final Scrollable scrollable = Scrollable(
dragStartBehavior: dragStartBehavior,
axisDirection: axisDirection,
controller: scrollController,
physics: physics,
scrollBehavior: scrollBehavior,
semanticChildCount: semanticChildCount,
restorationId: restorationId,
viewportBuilder: (BuildContext context, ViewportOffset offset) {
return buildViewport(context, offset, axisDirection, slivers);
},
clipBehavior: clipBehavior,
);
final Widget scrollableResult = effectivePrimary && scrollController != null
// Further descendant ScrollViews will not inherit the same PrimaryScrollController
? PrimaryScrollController.none(child: scrollable)
: scrollable;
if (keyboardDismissBehavior == ScrollViewKeyboardDismissBehavior.onDrag) {
return NotificationListener<ScrollUpdateNotification>(
child: scrollableResult,
onNotification: (ScrollUpdateNotification notification) {
final FocusScopeNode focusScope = FocusScope.of(context);
if (notification.dragDetails != null && focusScope.hasFocus) {
focusScope.unfocus();
}
return false;
},
);
} else {
return scrollableResult;
}
}
ScrollView组件的build
办法中:
-
首要,它调用
buildSlivers
办法来构建视口内部的组件列表,然后调用getDirection
办法来获取翻滚的方向。 -
接着,它确认是否运用主翻滚操控器。假如
primary
特点为true
,或许没有供给controller
而且PrimaryScrollController.shouldInherit回来true
,那么effectivePrimary
就为true
。在这种情况下,翻滚操控器scrollController
将运用PrimaryScrollController.maybeOf(context) 获取,不然运用供给的controller
。 -
然后,它创立一个Scrollable组件,这个组件包括了翻滚的所有信息,如翻滚方向、翻滚操控器、翻滚物理等。
viewportBuilder
参数是一个函数,它回来视口组件,这个函数调用buildViewport
办法来构建视口。假如
effectivePrimary
为true
而且scrollController
不为null
,那么它会回来一个PrimaryScrollController.none组件,这样子孙的ScrollView就不会承继同一个PrimaryScrollController。不然,它直接回来Scrollable组件。 -
最后,假如
keyboardDismissBehavior
特点设置为ScrollViewKeyboardDismissBehavior.onDrag,那么它会回来一个NotificationListener组件,这个组件会在翻滚更新告诉产生时撤销焦点,然后躲藏键盘。不然,它直接回来Scrollable组件。
22. 其它代码
@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties.add(EnumProperty<Axis>('scrollDirection', scrollDirection));
properties.add(FlagProperty('reverse', value: reverse, ifTrue: 'reversed', showName: true));
properties.add(DiagnosticsProperty<ScrollController>('controller', controller, showName: false, defaultValue: null));
properties.add(FlagProperty('primary', value: primary, ifTrue: 'using primary controller', showName: true));
properties.add(DiagnosticsProperty<ScrollPhysics>('physics', physics, showName: false, defaultValue: null));
properties.add(FlagProperty('shrinkWrap', value: shrinkWrap, ifTrue: 'shrink-wrapping', showName: true));
}
debugFillProperties 办法是 Flutter 结构的一部分,用于在调试时供给有关 ScrollView 的信息。