Add more docs and examples for implementers of RenderSliver (#15419)
* Add more docs and examples for implementers of RenderSliver
* add more typical scenarios to describe scrollOffset
* review
* tweak a word
diff --git a/packages/flutter/lib/src/rendering/sliver.dart b/packages/flutter/lib/src/rendering/sliver.dart
index 68e2947..1f65d06 100644
--- a/packages/flutter/lib/src/rendering/sliver.dart
+++ b/packages/flutter/lib/src/rendering/sliver.dart
@@ -196,7 +196,22 @@
/// the earliest visible part of this sliver in the [AxisDirection].
///
/// For example, if [AxisDirection] is [AxisDirection.down], then this is the
- /// scroll offset at the top of the visible portion of the sliver.
+ /// scroll offset at the top of the visible portion of the sliver or
+ /// equivalently the amount the top of the sliver has been scrolled past the
+ /// top of the viewport.
+ ///
+ /// This value is typically used to compute whether this sliver should still
+ /// protrude into the viewport via [SliverGeometry.paintExtent] and
+ /// [SliverGeometry.layoutExtent] considering how far the beginning of the
+ /// sliver is above the beginning of the viewport.
+ ///
+ /// For slivers whose top is not past the top of the viewport, the
+ /// [scrollOffset] is `0` when [AxisDirection] is [AxisDirection.down]. This
+ /// includes all the slivers that are below the bottom of the viewport.
+ ///
+ /// [SliverConstraints.remainingPaintExtent] is typically used to accomplish
+ /// the same goal of computing whether scrolled out slivers should still
+ /// partially 'protrude in' from the bottom of the viewport.
///
/// Whether this corresponds to the beginning or the end of the sliver's
/// contents depends on the [growthDirection].
@@ -438,9 +453,21 @@
/// A sliver that occupies no space at all.
static const SliverGeometry zero = const SliverGeometry();
- /// The (estimated) total scroll extent that this sliver has content for. In
- /// other words, the scroll offset of the end of the last bit of content of
- /// this sliver.
+ /// The (estimated) total scrollable extent that this sliver has content for.
+ ///
+ /// This is the amount of scrolling the user needs to do to get from the
+ /// beginning of this sliver to the end of this sliver.
+ ///
+ /// The value is used to calculate the [SliverConstraints.scrollOffset] of
+ /// all slivers in the scrollable and thus should be provided whether the
+ /// sliver is currently in the viewport or not.
+ ///
+ /// In a typical scrolling scenario, the [scrollExtent] is constant for a
+ /// sliver throughout the scrolling while [paintExtent] and [layoutExtent]
+ /// will progress from `0` when offscreen to between `0` and [scrollExtent]
+ /// as the sliver scrolls partially into and out of the screen and is
+ /// equal to [scrollExtent] while the sliver is entirely on screen. However,
+ /// these relationships can be customized to achieve more special effects.
///
/// This value must be accurate if the [paintExtent] is less than the
/// [SliverConstraints.remainingPaintExtent] provided during layout.
@@ -451,7 +478,16 @@
///
/// For example, if the sliver wishes to paint visually before its layout
/// position, the [paintOrigin] is negative. The coordinate system this sliver
- /// uses for painting is relative to this [paintOrigin].
+ /// uses for painting is relative to this [paintOrigin]. In other words,
+ /// when [RenderSliver.paint] is called, the (0, 0) position of the [Offset]
+ /// given to it is at this [paintOrigin].
+ ///
+ /// The coordinate system used for the [paintOrigin] itself is relative
+ /// to the start of this sliver's layout position rather than relative to
+ /// its current position on the viewport. In other words, in a typical
+ /// scrolling scenario, [paintOrigin] remains constant at 0.0 rather than
+ /// tracking from 0.0 to [SliverConstraints.viewportMainAxisExtent] as the
+ /// sliver scrolls past the viewport.
///
/// This value does not affect the layout of subsequent slivers. The next
/// sliver is still placed at [layoutExtent] after this sliver's layout
@@ -463,12 +499,22 @@
/// position by default.
final double paintOrigin;
- /// The amount of visual space that was taken by the sliver to render the
- /// subset of the sliver that covers all or part of the
- /// [SliverConstraints.remainingPaintExtent].
+ /// The amount of currently visible visual space that was taken by the sliver
+ /// to render the subset of the sliver that covers all or part of the
+ /// [SliverConstraints.remainingPaintExtent] in the current viewport.
+ ///
+ /// This value does not affect how the next sliver is positioned. In other
+ /// words, if this value was 100 and [layoutExtent] was 0, typical slivers
+ /// placed after it would end up drawing in the same 100 pixel space while
+ /// painting.
///
/// This must be between zero and [SliverConstraints.remainingPaintExtent].
///
+ /// This value is typically 0 when outside of the viewport and grows or
+ /// shrinks from 0 or to 0 as the sliver is being scrolled into and out of the
+ /// viewport unless the sliver wants to achieve a special effect and paint
+ /// even when scrolled away.
+ ///
/// This contributes to the calculation for the next sliver's
/// [SliverConstraints.overlap].
final double paintExtent;
@@ -478,6 +524,12 @@
/// [SliverConstraints.scrollOffset] is zero.
///
/// This must be between zero and [paintExtent]. It defaults to [paintExtent].
+ ///
+ /// This value is typically 0 when outside of the viewport and grows or
+ /// shrinks from 0 or to 0 as the sliver is being scrolled into and out of the
+ /// viewport unless then sliver wants to achieve a special effect and push
+ /// down the layout start position of subsequent slivers before the sliver is
+ /// even scrolled into the viewport.
final double layoutExtent;
/// The (estimated) total paint extent that this sliver would be able to
@@ -521,6 +573,13 @@
/// offset will be adjusted by the parent and then the entire layout of the
/// parent will be rerun.
///
+ /// When the value is non-zero, the [RenderSliver] does not need to compute
+ /// the rest of the values when constructing the [SliverGeometry] or call
+ /// [RenderObject.layout] on its children since [RenderSliver.performLayout]
+ /// will be called again on this sliver in the same frame after the
+ /// [SliverConstraints.scrollOffset] correction has ben applied, when the
+ /// proper [SliverGeometry] and layout of its children can be computed.
+ ///
/// If the parent is also a [RenderSliver], it must propagate this value
/// in its own [RenderSliver.geometry] property until a viewport which adjusts
/// its offset based on this value.