Document Viewport and NestedScrollView (#9735)
This commit is contained in:
parent
9fe68ef7b3
commit
1faaf8ead6
@ -1356,11 +1356,11 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget {
|
|||||||
/// relevant to itself and to any other nodes who happen to know exactly what
|
/// relevant to itself and to any other nodes who happen to know exactly what
|
||||||
/// the data means. The parent data is opaque to the child.
|
/// the data means. The parent data is opaque to the child.
|
||||||
///
|
///
|
||||||
/// - The parent data field must not be directly set, except by calling
|
/// * The parent data field must not be directly set, except by calling
|
||||||
/// [setupParentData] on the parent node.
|
/// [setupParentData] on the parent node.
|
||||||
/// - The parent data can be set before the child is added to the parent, by
|
/// * The parent data can be set before the child is added to the parent, by
|
||||||
/// calling [setupParentData] on the future parent node.
|
/// calling [setupParentData] on the future parent node.
|
||||||
/// - The conventions for using the parent data depend on the layout protocol
|
/// * The conventions for using the parent data depend on the layout protocol
|
||||||
/// used between the parent and child. For example, in box layout, the
|
/// used between the parent and child. For example, in box layout, the
|
||||||
/// parent data is completely opaque but in sector layout the child is
|
/// parent data is completely opaque but in sector layout the child is
|
||||||
/// permitted to read some fields of the parent data.
|
/// permitted to read some fields of the parent data.
|
||||||
|
@ -50,16 +50,29 @@ abstract class RenderAbstractViewport implements RenderObject {
|
|||||||
double getOffsetToReveal(RenderObject target, double alignment);
|
double getOffsetToReveal(RenderObject target, double alignment);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ///
|
/// A base class for render objects that are bigger on the inside.
|
||||||
// /// See also:
|
///
|
||||||
// ///
|
/// This render object provides the shared code for render objects that host
|
||||||
// /// - [RenderSliver], which explains more about the Sliver protocol.
|
/// [RenderSliver] render objects inside a [RenderBox]. The viewport establishes
|
||||||
// /// - [RenderBox], which explains more about the Box protocol.
|
/// an [axisDirection], which orients the sliver's coordinate system, which is
|
||||||
// /// - [RenderSliverToBoxAdapter], which allows a [RenderBox] object to be
|
/// based on scroll offsets rather than cartesian coordinates.
|
||||||
// /// placed inside a [RenderSliver] (the opposite of this class).
|
///
|
||||||
|
/// The viewport also listens to an [offset], which determines the
|
||||||
|
/// [SliverConstraints.scrollOffset] input to the sliver layout protocol.
|
||||||
|
///
|
||||||
|
/// Subclasses typically override [performLayout] and call
|
||||||
|
/// [layoutChildSequence], perhaps multiple times.
|
||||||
|
///
|
||||||
|
/// See also:
|
||||||
|
///
|
||||||
|
/// * [RenderSliver], which explains more about the Sliver protocol.
|
||||||
|
/// * [RenderBox], which explains more about the Box protocol.
|
||||||
|
/// * [RenderSliverToBoxAdapter], which allows a [RenderBox] object to be
|
||||||
|
/// placed inside a [RenderSliver] (the opposite of this class).
|
||||||
abstract class RenderViewportBase<ParentDataClass extends ContainerParentDataMixin<RenderSliver>>
|
abstract class RenderViewportBase<ParentDataClass extends ContainerParentDataMixin<RenderSliver>>
|
||||||
extends RenderBox with ContainerRenderObjectMixin<RenderSliver, ParentDataClass>
|
extends RenderBox with ContainerRenderObjectMixin<RenderSliver, ParentDataClass>
|
||||||
implements RenderAbstractViewport {
|
implements RenderAbstractViewport {
|
||||||
|
/// Initializes fields for subclasses.
|
||||||
RenderViewportBase({
|
RenderViewportBase({
|
||||||
AxisDirection axisDirection: AxisDirection.down,
|
AxisDirection axisDirection: AxisDirection.down,
|
||||||
@required ViewportOffset offset,
|
@required ViewportOffset offset,
|
||||||
@ -525,15 +538,37 @@ abstract class RenderViewportBase<ParentDataClass extends ContainerParentDataMix
|
|||||||
Iterable<RenderSliver> get childrenInHitTestOrder;
|
Iterable<RenderSliver> get childrenInHitTestOrder;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ///
|
/// A render object that is bigger on the inside.
|
||||||
// /// See also:
|
///
|
||||||
// ///
|
/// [RenderViewport] is the visual workhorse of the scrolling machinery. It
|
||||||
// /// - [RenderSliver], which explains more about the Sliver protocol.
|
/// displays a subset of its children according to its own dimensions and the
|
||||||
// /// - [RenderBox], which explains more about the Box protocol.
|
/// given [offset]. As the offset varies, different children are visible through
|
||||||
// /// - [RenderSliverToBoxAdapter], which allows a [RenderBox] object to be
|
/// the viewport.
|
||||||
// /// placed inside a [RenderSliver] (the opposite of this class).
|
///
|
||||||
// /// - [RenderShrinkWrappingViewport], a variant of [RenderViewport] that
|
/// [RenderViewport] hosts a bidirectional list of slivers, anchored on a
|
||||||
// /// shrink-wraps its contents along the main axis.
|
/// [center] sliver, which is placed at the zero scroll offset. The center
|
||||||
|
/// widget is displayed in the viewport according to the [anchor] property.
|
||||||
|
///
|
||||||
|
/// Slivers that are earlier in the child list than [center] are displayed in
|
||||||
|
/// reverse order in the reverse [axisDirection] starting from the [center]. For
|
||||||
|
/// example, if the [axisDirection] is [AxisDirection.down], the first sliver
|
||||||
|
/// before [center] is placed above the [center]. The slivers that are later in
|
||||||
|
/// the child list than [center] are placed in order in the [axisDirection]. For
|
||||||
|
/// example, in the preceeding scenario, the first sliver after [center] is
|
||||||
|
/// placed below the [center].
|
||||||
|
///
|
||||||
|
/// [RenderViewport] cannot contain [RenderBox] children directly. Instead, use
|
||||||
|
/// a [RenderSliverList], [RenderSliverFixedExtentList], [RenderSliverGrid], or
|
||||||
|
/// a [RenderSliverToBoxAdapter], for example.
|
||||||
|
///
|
||||||
|
/// See also:
|
||||||
|
///
|
||||||
|
/// * [RenderSliver], which explains more about the Sliver protocol.
|
||||||
|
/// * [RenderBox], which explains more about the Box protocol.
|
||||||
|
/// * [RenderSliverToBoxAdapter], which allows a [RenderBox] object to be
|
||||||
|
/// placed inside a [RenderSliver] (the opposite of this class).
|
||||||
|
/// * [RenderShrinkWrappingViewport], a variant of [RenderViewport] that
|
||||||
|
/// shrink-wraps its contents along the main axis.
|
||||||
class RenderViewport extends RenderViewportBase<SliverPhysicalContainerParentData> {
|
class RenderViewport extends RenderViewportBase<SliverPhysicalContainerParentData> {
|
||||||
/// Creates a viewport for [RenderSliver] objects.
|
/// Creates a viewport for [RenderSliver] objects.
|
||||||
///
|
///
|
||||||
@ -944,14 +979,31 @@ class RenderViewport extends RenderViewportBase<SliverPhysicalContainerParentDat
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ///
|
/// A render object that is bigger on the inside and shrink wraps its children
|
||||||
// /// See also:
|
/// in the main axis.
|
||||||
// ///
|
///
|
||||||
// /// - [RenderViewport], a viewport that does not shrink-wrap its contents
|
/// [RenderShrinkWrappingViewport] displays a subset of its children according
|
||||||
// /// - [RenderSliver], which explains more about the Sliver protocol.
|
/// to its own dimensions and the given [offset]. As the offset varies, different
|
||||||
// /// - [RenderBox], which explains more about the Box protocol.
|
/// children are visible through the viewport.
|
||||||
// /// - [RenderSliverToBoxAdapter], which allows a [RenderBox] object to be
|
///
|
||||||
// /// placed inside a [RenderSliver] (the opposite of this class).
|
/// [RenderShrinkWrappingViewport] differs from [RenderViewport] in that
|
||||||
|
/// [RenderViewport] expands to fill the main axis whereas
|
||||||
|
/// [RenderShrinkWrappingViewport] sizes itself to match its children in the
|
||||||
|
/// main axis. This shrink wrapping behavior is expensive because the children,
|
||||||
|
/// and hence the viewport, could potentially change size whenever the [offset]
|
||||||
|
/// changes (e.g., because of a collapsing header).
|
||||||
|
///
|
||||||
|
/// [RenderShrinkWrappingViewport] cannot contain [RenderBox] children directly.
|
||||||
|
/// Instead, use a [RenderSliverList], [RenderSliverFixedExtentList],
|
||||||
|
/// [RenderSliverGrid], or a [RenderSliverToBoxAdapter], for example.
|
||||||
|
///
|
||||||
|
/// See also:
|
||||||
|
///
|
||||||
|
/// * [RenderViewport], a viewport that does not shrink-wrap its contents
|
||||||
|
/// * [RenderSliver], which explains more about the Sliver protocol.
|
||||||
|
/// * [RenderBox], which explains more about the Box protocol.
|
||||||
|
/// * [RenderSliverToBoxAdapter], which allows a [RenderBox] object to be
|
||||||
|
/// placed inside a [RenderSliver] (the opposite of this class).
|
||||||
class RenderShrinkWrappingViewport extends RenderViewportBase<SliverLogicalContainerParentData> {
|
class RenderShrinkWrappingViewport extends RenderViewportBase<SliverLogicalContainerParentData> {
|
||||||
/// Creates a viewport (for [RenderSliver] objects) that shrink-wraps its
|
/// Creates a viewport (for [RenderSliver] objects) that shrink-wraps its
|
||||||
/// contents.
|
/// contents.
|
||||||
|
@ -27,6 +27,9 @@ import 'ticker_provider.dart';
|
|||||||
/// Signature used by [NestedScrollView] for building its header.
|
/// Signature used by [NestedScrollView] for building its header.
|
||||||
typedef List<Widget> NestedScrollViewHeaderSliversBuilder(BuildContext context, bool innerBoxIsScrolled);
|
typedef List<Widget> NestedScrollViewHeaderSliversBuilder(BuildContext context, bool innerBoxIsScrolled);
|
||||||
|
|
||||||
|
// TODO(abarth): Make this configurable with a controller.
|
||||||
|
const double _kInitialScrollOffset = 0.0;
|
||||||
|
|
||||||
class NestedScrollView extends StatefulWidget {
|
class NestedScrollView extends StatefulWidget {
|
||||||
NestedScrollView({
|
NestedScrollView({
|
||||||
Key key,
|
Key key,
|
||||||
@ -44,20 +47,38 @@ class NestedScrollView extends StatefulWidget {
|
|||||||
|
|
||||||
// TODO(ianh): we should expose a controller so you can call animateTo, etc.
|
// TODO(ianh): we should expose a controller so you can call animateTo, etc.
|
||||||
|
|
||||||
|
/// The axis along which the scroll view scrolls.
|
||||||
|
///
|
||||||
|
/// Defaults to [Axis.vertical].
|
||||||
final Axis scrollDirection;
|
final Axis scrollDirection;
|
||||||
|
|
||||||
|
/// Whether the scroll view scrolls in the reading direction.
|
||||||
|
///
|
||||||
|
/// For example, if the reading direction is left-to-right and
|
||||||
|
/// [scrollDirection] is [Axis.horizontal], then the scroll view scrolls from
|
||||||
|
/// left to right when [reverse] is false and from right to left when
|
||||||
|
/// [reverse] is true.
|
||||||
|
///
|
||||||
|
/// Similarly, if [scrollDirection] is [Axis.vertical], then the scroll view
|
||||||
|
/// scrolls from top to bottom when [reverse] is false and from bottom to top
|
||||||
|
/// when [reverse] is true.
|
||||||
|
///
|
||||||
|
/// Defaults to false.
|
||||||
final bool reverse;
|
final bool reverse;
|
||||||
|
|
||||||
|
/// How the scroll view should respond to user input.
|
||||||
|
///
|
||||||
|
/// For example, determines how the scroll view continues to animate after the
|
||||||
|
/// user stops dragging the scroll view.
|
||||||
|
///
|
||||||
|
/// Defaults to matching platform conventions.
|
||||||
final ScrollPhysics physics;
|
final ScrollPhysics physics;
|
||||||
|
|
||||||
final NestedScrollViewHeaderSliversBuilder headerSliverBuilder;
|
final NestedScrollViewHeaderSliversBuilder headerSliverBuilder;
|
||||||
|
|
||||||
final Widget body;
|
final Widget body;
|
||||||
|
|
||||||
double get initialScrollOffset => 0.0;
|
List<Widget> _buildSlivers(BuildContext context, ScrollController innerController, bool bodyIsScrolled) {
|
||||||
|
|
||||||
@protected
|
|
||||||
List<Widget> buildSlivers(BuildContext context, ScrollController innerController, bool bodyIsScrolled) {
|
|
||||||
final List<Widget> slivers = <Widget>[];
|
final List<Widget> slivers = <Widget>[];
|
||||||
slivers.addAll(headerSliverBuilder(context, bodyIsScrolled));
|
slivers.addAll(headerSliverBuilder(context, bodyIsScrolled));
|
||||||
slivers.add(new SliverFillRemaining(
|
slivers.add(new SliverFillRemaining(
|
||||||
@ -79,7 +100,7 @@ class _NestedScrollViewState extends State<NestedScrollView> {
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
_coordinator = new _NestedScrollCoordinator(context, widget.initialScrollOffset);
|
_coordinator = new _NestedScrollCoordinator(context, _kInitialScrollOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -102,7 +123,7 @@ class _NestedScrollViewState extends State<NestedScrollView> {
|
|||||||
reverse: widget.reverse,
|
reverse: widget.reverse,
|
||||||
physics: new ClampingScrollPhysics(parent: widget.physics),
|
physics: new ClampingScrollPhysics(parent: widget.physics),
|
||||||
controller: _coordinator._outerController,
|
controller: _coordinator._outerController,
|
||||||
slivers: widget.buildSlivers(context, _coordinator._innerController, _coordinator.hasScrolledBody),
|
slivers: widget._buildSlivers(context, _coordinator._innerController, _coordinator.hasScrolledBody),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,44 @@ export 'package:flutter/rendering.dart' show
|
|||||||
AxisDirection,
|
AxisDirection,
|
||||||
GrowthDirection;
|
GrowthDirection;
|
||||||
|
|
||||||
|
/// A widget that is bigger on the inside.
|
||||||
|
///
|
||||||
|
/// [Viewport] is the visual workhorse of the scrolling machinery. It displays a
|
||||||
|
/// subset of its children according to its own dimensions and the given
|
||||||
|
/// [offset]. As the offset varies, different children are visible through
|
||||||
|
/// the viewport.
|
||||||
|
///
|
||||||
|
/// [Viewport] hosts a bidirectional list of slivers, anchored on a [center]
|
||||||
|
/// sliver, which is placed at the zero scroll offset. The center widget is
|
||||||
|
/// displayed in the viewport according to the [anchor] property.
|
||||||
|
///
|
||||||
|
/// Slivers that are earlier in the child list than [center] are displayed in
|
||||||
|
/// reverse order in the reverse [axisDirection] starting from the [center]. For
|
||||||
|
/// example, if the [axisDirection] is [AxisDirection.down], the first sliver
|
||||||
|
/// before [center] is placed above the [center]. The slivers that are later in
|
||||||
|
/// the child list than [center] are placed in order in the [axisDirection]. For
|
||||||
|
/// example, in the preceeding scenario, the first sliver after [center] is
|
||||||
|
/// placed below the [center].
|
||||||
|
///
|
||||||
|
/// [Viewport] cannot contain box children directly. Instead, use a
|
||||||
|
/// [SliverList], [SliverFixedExtentList], [SliverGrid], or a
|
||||||
|
/// [SliverToBoxAdapter], for example.
|
||||||
|
///
|
||||||
|
/// See also:
|
||||||
|
///
|
||||||
|
/// * [ListView], [PageView], [GridView], and [CustomScrollView], which combine
|
||||||
|
/// [Scrollable] and [Viewport] into widgets that are easier to use.
|
||||||
|
/// * [SliverToBoxAdapter], which allows a box widget to be placed inside a
|
||||||
|
/// sliver context (the opposite of this widget).
|
||||||
|
/// * [ShrinkWrappingViewport], a variant of [Viewport] that shrink-wraps its
|
||||||
|
/// contents along the main axis.
|
||||||
class Viewport extends MultiChildRenderObjectWidget {
|
class Viewport extends MultiChildRenderObjectWidget {
|
||||||
|
/// Creates a widget that is bigger on the inside.
|
||||||
|
///
|
||||||
|
/// The viewport listens to the [offset], which means you do not need to
|
||||||
|
/// rebuild this widget when the [offset] changes.
|
||||||
|
///
|
||||||
|
/// The [offset] argument must not be null.
|
||||||
Viewport({
|
Viewport({
|
||||||
Key key,
|
Key key,
|
||||||
this.axisDirection: AxisDirection.down,
|
this.axisDirection: AxisDirection.down,
|
||||||
@ -24,9 +61,39 @@ class Viewport extends MultiChildRenderObjectWidget {
|
|||||||
assert(center == null || children.where((Widget child) => child.key == center).length == 1);
|
assert(center == null || children.where((Widget child) => child.key == center).length == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The direction in which the [scrollOffset] increases.
|
||||||
|
///
|
||||||
|
/// For example, if the [axisDirection] is [AxisDirection.down], a scroll
|
||||||
|
/// offset of zero is at the top of the viewport and increases towards the
|
||||||
|
/// bottom of the viewport.
|
||||||
final AxisDirection axisDirection;
|
final AxisDirection axisDirection;
|
||||||
|
|
||||||
|
/// The relative position of the zero scroll offset.
|
||||||
|
///
|
||||||
|
/// For example, if [anchor] is 0.5 and the [axisDirection] is
|
||||||
|
/// [AxisDirection.down] or [AxisDirection.up], then the zero scroll offset is
|
||||||
|
/// vertically centered within the viewport. If the [anchor] is 1.0, and the
|
||||||
|
/// [axisDirection] is [AxisDirection.right], then the zero scroll offset is
|
||||||
|
/// on the left edge of the viewport.
|
||||||
final double anchor;
|
final double anchor;
|
||||||
|
|
||||||
|
/// Which part of the content inside the viewport should be visible.
|
||||||
|
///
|
||||||
|
/// The [ViewportOffset.pixels] value determines the scroll offset that the
|
||||||
|
/// viewport uses to select which part of its content to display. As the user
|
||||||
|
/// scrolls the viewport, this value changes, which changes the content that
|
||||||
|
/// is displayed.
|
||||||
|
///
|
||||||
|
/// Typically a [ScrollPosition].
|
||||||
final ViewportOffset offset;
|
final ViewportOffset offset;
|
||||||
|
|
||||||
|
/// The first child in the [GrowthDirection.forward] growth direction.
|
||||||
|
///
|
||||||
|
/// Children after [center] will be placed in the [axisDirection] relative to
|
||||||
|
/// the [center]. Children before [center] will be placed in the opposite of
|
||||||
|
/// the [axisDirection] relative to the [center].
|
||||||
|
///
|
||||||
|
/// The [center] must be the key of a child of the viewport.
|
||||||
final Key center;
|
final Key center;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -46,7 +113,7 @@ class Viewport extends MultiChildRenderObjectWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
ViewportElement createElement() => new ViewportElement(this);
|
_ViewportElement createElement() => new _ViewportElement(this);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void debugFillDescription(List<String> description) {
|
void debugFillDescription(List<String> description) {
|
||||||
@ -62,9 +129,9 @@ class Viewport extends MultiChildRenderObjectWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ViewportElement extends MultiChildRenderObjectElement {
|
class _ViewportElement extends MultiChildRenderObjectElement {
|
||||||
/// Creates an element that uses the given widget as its configuration.
|
/// Creates an element that uses the given widget as its configuration.
|
||||||
ViewportElement(Viewport widget) : super(widget);
|
_ViewportElement(Viewport widget) : super(widget);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Viewport get widget => super.widget;
|
Viewport get widget => super.widget;
|
||||||
@ -75,17 +142,16 @@ class ViewportElement extends MultiChildRenderObjectElement {
|
|||||||
@override
|
@override
|
||||||
void mount(Element parent, dynamic newSlot) {
|
void mount(Element parent, dynamic newSlot) {
|
||||||
super.mount(parent, newSlot);
|
super.mount(parent, newSlot);
|
||||||
updateCenter();
|
_updateCenter();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void update(MultiChildRenderObjectWidget newWidget) {
|
void update(MultiChildRenderObjectWidget newWidget) {
|
||||||
super.update(newWidget);
|
super.update(newWidget);
|
||||||
updateCenter();
|
_updateCenter();
|
||||||
}
|
}
|
||||||
|
|
||||||
@protected
|
void _updateCenter() {
|
||||||
void updateCenter() {
|
|
||||||
// TODO(ianh): cache the keys to make this faster
|
// TODO(ianh): cache the keys to make this faster
|
||||||
if (widget.center != null) {
|
if (widget.center != null) {
|
||||||
renderObject.center = children.singleWhere(
|
renderObject.center = children.singleWhere(
|
||||||
@ -99,7 +165,39 @@ class ViewportElement extends MultiChildRenderObjectElement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A widget that is bigger on the inside and shrink wraps its children in the
|
||||||
|
/// main axis.
|
||||||
|
///
|
||||||
|
/// [ShrinkWrappingViewport] displays a subset of its children according to its
|
||||||
|
/// own dimensions and the given [offset]. As the offset varies, different
|
||||||
|
/// children are visible through the viewport.
|
||||||
|
///
|
||||||
|
/// [ShrinkWrappingViewport] differs from [Viewport] in that [Viewport] expands
|
||||||
|
/// to fill the main axis whereas [ShrinkWrappingViewport] sizes itself to match
|
||||||
|
/// its children in the main axis. This shrink wrapping behavior is expensive
|
||||||
|
/// because the children, and hence the viewport, could potentially change size
|
||||||
|
/// whenever the [offset] changes (e.g., because of a collapsing header).
|
||||||
|
///
|
||||||
|
/// [ShrinkWrappingViewport] cannot contain box children directly. Instead, use
|
||||||
|
/// a [SliverList], [SliverFixedExtentList], [SliverGrid], or a
|
||||||
|
/// [SliverToBoxAdapter], for example.
|
||||||
|
///
|
||||||
|
/// See also:
|
||||||
|
///
|
||||||
|
/// * [ListView], [PageView], [GridView], and [CustomScrollView], which combine
|
||||||
|
/// [Scrollable] and [ShrinkWrappingViewport] into widgets that are easier to
|
||||||
|
/// use.
|
||||||
|
/// * [SliverToBoxAdapter], which allows a box widget to be placed inside a
|
||||||
|
/// sliver context (the opposite of this widget).
|
||||||
|
/// * [Viewport], a viewport that does not shrink-wrap its contents
|
||||||
class ShrinkWrappingViewport extends MultiChildRenderObjectWidget {
|
class ShrinkWrappingViewport extends MultiChildRenderObjectWidget {
|
||||||
|
/// Creates a widget that is bigger on the inside and shrink wraps its
|
||||||
|
/// children in the main axis.
|
||||||
|
///
|
||||||
|
/// The viewport listens to the [offset], which means you do not need to
|
||||||
|
/// rebuild this widget when the [offset] changes.
|
||||||
|
///
|
||||||
|
/// The [offset] argument must not be null.
|
||||||
ShrinkWrappingViewport({
|
ShrinkWrappingViewport({
|
||||||
Key key,
|
Key key,
|
||||||
this.axisDirection: AxisDirection.down,
|
this.axisDirection: AxisDirection.down,
|
||||||
@ -109,7 +207,21 @@ class ShrinkWrappingViewport extends MultiChildRenderObjectWidget {
|
|||||||
assert(offset != null);
|
assert(offset != null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The direction in which the [scrollOffset] increases.
|
||||||
|
///
|
||||||
|
/// For example, if the [axisDirection] is [AxisDirection.down], a scroll
|
||||||
|
/// offset of zero is at the top of the viewport and increases towards the
|
||||||
|
/// bottom of the viewport.
|
||||||
final AxisDirection axisDirection;
|
final AxisDirection axisDirection;
|
||||||
|
|
||||||
|
/// Which part of the content inside the viewport should be visible.
|
||||||
|
///
|
||||||
|
/// The [ViewportOffset.pixels] value determines the scroll offset that the
|
||||||
|
/// viewport uses to select which part of its content to display. As the user
|
||||||
|
/// scrolls the viewport, this value changes, which changes the content that
|
||||||
|
/// is displayed.
|
||||||
|
///
|
||||||
|
/// Typically a [ScrollPosition].
|
||||||
final ViewportOffset offset;
|
final ViewportOffset offset;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
Loading…
x
Reference in New Issue
Block a user