Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
1faaf8ea
Commit
1faaf8ea
authored
May 03, 2017
by
Adam Barth
Committed by
GitHub
May 03, 2017
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Document Viewport and NestedScrollView (#9735)
parent
9fe68ef7
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
230 additions
and
45 deletions
+230
-45
object.dart
packages/flutter/lib/src/rendering/object.dart
+8
-8
viewport.dart
packages/flutter/lib/src/rendering/viewport.dart
+76
-24
nested_scroll_view.dart
packages/flutter/lib/src/widgets/nested_scroll_view.dart
+27
-6
viewport.dart
packages/flutter/lib/src/widgets/viewport.dart
+119
-7
No files found.
packages/flutter/lib/src/rendering/object.dart
View file @
1faaf8ea
...
...
@@ -1356,14 +1356,14 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget {
/// 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 parent data field must not be directly set, except by calling
/// [setupParentData] on the parent node.
///
-
The parent data can be set before the child is added to the parent, by
/// calling [setupParentData] on the future parent node.
///
-
The conventions for using the parent data depend on the layout protocol
/// used between the parent and child. For example, in box layout, the
/// parent data is completely opaque but in sector layout the child is
/// permitted to read some fields of the parent data.
///
*
The parent data field must not be directly set, except by calling
///
[setupParentData] on the parent node.
///
*
The parent data can be set before the child is added to the parent, by
///
calling [setupParentData] on the future parent node.
///
*
The conventions for using the parent data depend on the layout protocol
///
used between the parent and child. For example, in box layout, the
///
parent data is completely opaque but in sector layout the child is
///
permitted to read some fields of the parent data.
ParentData
parentData
;
/// Override to setup parent data correctly for your children.
...
...
packages/flutter/lib/src/rendering/viewport.dart
View file @
1faaf8ea
...
...
@@ -50,16 +50,29 @@ abstract class RenderAbstractViewport implements RenderObject {
double
getOffsetToReveal
(
RenderObject
target
,
double
alignment
);
}
// ///
// /// 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).
/// A base class for render objects that are bigger on the inside.
///
/// This render object provides the shared code for render objects that host
/// [RenderSliver] render objects inside a [RenderBox]. The viewport establishes
/// an [axisDirection], which orients the sliver's coordinate system, which is
/// based on scroll offsets rather than cartesian coordinates.
///
/// 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
>>
extends
RenderBox
with
ContainerRenderObjectMixin
<
RenderSliver
,
ParentDataClass
>
implements
RenderAbstractViewport
{
/// Initializes fields for subclasses.
RenderViewportBase
({
AxisDirection
axisDirection:
AxisDirection
.
down
,
@required
ViewportOffset
offset
,
...
...
@@ -525,15 +538,37 @@ abstract class RenderViewportBase<ParentDataClass extends ContainerParentDataMix
Iterable
<
RenderSliver
>
get
childrenInHitTestOrder
;
}
// ///
// /// 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.
/// A render object that is bigger on the inside.
///
/// [RenderViewport] 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.
///
/// [RenderViewport] 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].
///
/// [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
>
{
/// Creates a viewport for [RenderSliver] objects.
///
...
...
@@ -944,14 +979,31 @@ class RenderViewport extends RenderViewportBase<SliverPhysicalContainerParentDat
}
}
// ///
// /// 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).
/// A render object that is bigger on the inside and shrink wraps its children
/// in the main axis.
///
/// [RenderShrinkWrappingViewport] 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.
///
/// [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
>
{
/// Creates a viewport (for [RenderSliver] objects) that shrink-wraps its
/// contents.
...
...
packages/flutter/lib/src/widgets/nested_scroll_view.dart
View file @
1faaf8ea
...
...
@@ -27,6 +27,9 @@ import 'ticker_provider.dart';
/// Signature used by [NestedScrollView] for building its header.
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
{
NestedScrollView
({
Key
key
,
...
...
@@ -44,20 +47,38 @@ class NestedScrollView extends StatefulWidget {
// 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
;
/// 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
;
/// 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
NestedScrollViewHeaderSliversBuilder
headerSliverBuilder
;
final
Widget
body
;
double
get
initialScrollOffset
=>
0.0
;
@protected
List
<
Widget
>
buildSlivers
(
BuildContext
context
,
ScrollController
innerController
,
bool
bodyIsScrolled
)
{
List
<
Widget
>
_buildSlivers
(
BuildContext
context
,
ScrollController
innerController
,
bool
bodyIsScrolled
)
{
final
List
<
Widget
>
slivers
=
<
Widget
>[];
slivers
.
addAll
(
headerSliverBuilder
(
context
,
bodyIsScrolled
));
slivers
.
add
(
new
SliverFillRemaining
(
...
...
@@ -79,7 +100,7 @@ class _NestedScrollViewState extends State<NestedScrollView> {
@override
void
initState
()
{
super
.
initState
();
_coordinator
=
new
_NestedScrollCoordinator
(
context
,
widget
.
i
nitialScrollOffset
);
_coordinator
=
new
_NestedScrollCoordinator
(
context
,
_kI
nitialScrollOffset
);
}
@override
...
...
@@ -102,7 +123,7 @@ class _NestedScrollViewState extends State<NestedScrollView> {
reverse:
widget
.
reverse
,
physics:
new
ClampingScrollPhysics
(
parent:
widget
.
physics
),
controller:
_coordinator
.
_outerController
,
slivers:
widget
.
buildSlivers
(
context
,
_coordinator
.
_innerController
,
_coordinator
.
hasScrolledBody
),
slivers:
widget
.
_
buildSlivers
(
context
,
_coordinator
.
_innerController
,
_coordinator
.
hasScrolledBody
),
);
}
}
...
...
packages/flutter/lib/src/widgets/viewport.dart
View file @
1faaf8ea
...
...
@@ -11,7 +11,44 @@ export 'package:flutter/rendering.dart' show
AxisDirection
,
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
{
/// 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
({
Key
key
,
this
.
axisDirection
:
AxisDirection
.
down
,
...
...
@@ -24,9 +61,39 @@ class Viewport extends MultiChildRenderObjectWidget {
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
;
/// 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
;
/// 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
;
/// 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
;
@override
...
...
@@ -46,7 +113,7 @@ class Viewport extends MultiChildRenderObjectWidget {
}
@override
ViewportElement
createElement
()
=>
new
ViewportElement
(
this
);
_ViewportElement
createElement
()
=>
new
_
ViewportElement
(
this
);
@override
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.
ViewportElement
(
Viewport
widget
)
:
super
(
widget
);
_
ViewportElement
(
Viewport
widget
)
:
super
(
widget
);
@override
Viewport
get
widget
=>
super
.
widget
;
...
...
@@ -75,17 +142,16 @@ class ViewportElement extends MultiChildRenderObjectElement {
@override
void
mount
(
Element
parent
,
dynamic
newSlot
)
{
super
.
mount
(
parent
,
newSlot
);
updateCenter
();
_
updateCenter
();
}
@override
void
update
(
MultiChildRenderObjectWidget
newWidget
)
{
super
.
update
(
newWidget
);
updateCenter
();
_
updateCenter
();
}
@protected
void
updateCenter
()
{
void
_updateCenter
()
{
// TODO(ianh): cache the keys to make this faster
if
(
widget
.
center
!=
null
)
{
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
{
/// 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
({
Key
key
,
this
.
axisDirection
:
AxisDirection
.
down
,
...
...
@@ -109,7 +207,21 @@ class ShrinkWrappingViewport extends MultiChildRenderObjectWidget {
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
;
/// 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
;
@override
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment