Commit af170c8e authored by Adam Barth's avatar Adam Barth Committed by GitHub

Add more dartdocs (#9183)

Mostly related to semantics and scrolling.
parent f46dd406
...@@ -862,6 +862,22 @@ class _ForkingSemanticsFragment extends _SemanticsFragment { ...@@ -862,6 +862,22 @@ class _ForkingSemanticsFragment extends _SemanticsFragment {
} }
} }
/// A reference to the semantics tree.
///
/// The framework maintains the semantics tree (used for accessibility and
/// indexing) only when there is at least one client holding an open
/// [SemanticsHandle].
///
/// The framework notifies the client that it has updated the semantics tree by
/// calling the [listener] callback. When the client no longer needs the
/// semantics tree, the client can call [dispose] on the [SemanticsHandle],
/// which stops these callbacks and closes the [SemanticsHandle]. When all the
/// outstanding [SemanticsHandle] objects are closed, the framework stops
/// updating the semantics tree.
///
/// To obtain a [SemanticsHandle], call [PipelineOwner.ensureSemantics] on the
/// [PipelineOwner] for the render tree from which you wish to read semantics.
/// You can obtain the [PipelineOwner] using the [RenderObject.owner] property.
class SemanticsHandle { class SemanticsHandle {
SemanticsHandle._(this._owner, this.listener) { SemanticsHandle._(this._owner, this.listener) {
assert(_owner != null); assert(_owner != null);
...@@ -870,8 +886,16 @@ class SemanticsHandle { ...@@ -870,8 +886,16 @@ class SemanticsHandle {
} }
PipelineOwner _owner; PipelineOwner _owner;
/// The callback that will be notified when the semantics tree updates.
final VoidCallback listener; final VoidCallback listener;
/// Closes the semantics handle and stops calling [listener] when the
/// semantics updates.
///
/// When all the outstanding [SemanticsHandle] objects for a given
/// [PipelineOwner] are closed, the [PipelineOwner] will stop updating the
/// semantics tree.
@mustCallSuper @mustCallSuper
void dispose() { void dispose() {
assert(() { assert(() {
...@@ -1096,6 +1120,18 @@ class PipelineOwner { ...@@ -1096,6 +1120,18 @@ class PipelineOwner {
int _outstandingSemanticsHandle = 0; int _outstandingSemanticsHandle = 0;
/// Opens a [SemanticsHandle] and calls [listener] whenever the semantics tree
/// updates.
///
/// The [PipelineOwner] updates the semantics tree only when there are clients
/// that wish to use the semantics tree. These clients express their interest
/// by holding [SemanticsHandle] objects that notify them whenever the
/// semantics tree updates.
///
/// Clients can close their [SemanticsHandle] by calling
/// [SemanticsHandle.dispose]. Once all the outstanding [SemanticsHandle]
/// objects for a given [PipelineOwner] are closed, the [PipelineOwner] stops
/// maintaining the semantics tree.
SemanticsHandle ensureSemantics({ VoidCallback listener }) { SemanticsHandle ensureSemantics({ VoidCallback listener }) {
if (_outstandingSemanticsHandle++ == 0) { if (_outstandingSemanticsHandle++ == 0) {
assert(_semanticsOwner == null); assert(_semanticsOwner == null);
......
...@@ -21,7 +21,7 @@ import 'viewport_offset.dart'; ...@@ -21,7 +21,7 @@ import 'viewport_offset.dart';
/// the framework recognize such render objects and interact with them without /// the framework recognize such render objects and interact with them without
/// having specific knowledge of all the various types of viewports. /// having specific knowledge of all the various types of viewports.
abstract class RenderAbstractViewport implements RenderObject { abstract class RenderAbstractViewport implements RenderObject {
/// Returns the [RenderAbstractViewport] that most closely encloses the given /// Returns the [RenderAbstractViewport] that most tightly encloses the given
/// render object. /// render object.
/// ///
/// If the object does not have a [RenderAbstractViewport] as an ancestor, /// If the object does not have a [RenderAbstractViewport] as an ancestor,
......
...@@ -7,24 +7,24 @@ import 'dart:async'; ...@@ -7,24 +7,24 @@ import 'dart:async';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
/// A leaf node in the focus tree that can receive focus. /// A leaf node in the focus tree that can receive focus.
/// ///
/// The focus tree keeps track of which widget is the user's current focus. The /// The focus tree keeps track of which widget is the user's current focus. The
/// focused widget often listens for keyboard events. /// focused widget often listens for keyboard events.
/// ///
/// To request focus, find the [FocusScopeNode] for the current [BuildContext] /// To request focus, find the [FocusScopeNode] for the current [BuildContext]
/// and call the [FocusScopeNode.requestFocus] method: /// and call the [FocusScopeNode.requestFocus] method:
/// ///
/// ```dart /// ```dart
/// FocusScope.of(context).requestFocus(focusNode); /// FocusScope.of(context).requestFocus(focusNode);
/// ``` /// ```
/// ///
/// If your widget requests focus, be sure to call /// If your widget requests focus, be sure to call
/// `FocusScope.of(context).reparentIfNeeded(focusNode);` in your `build` /// `FocusScope.of(context).reparentIfNeeded(focusNode);` in your `build`
/// method to reparent your [FocusNode] if your widget moves from one /// method to reparent your [FocusNode] if your widget moves from one
/// location in the tree to another. /// location in the tree to another.
/// ///
/// See also: /// See also:
/// ///
/// * [FocusScopeNode], which is an interior node in the focus tree. /// * [FocusScopeNode], which is an interior node in the focus tree.
/// * [FocusScope.of], which provides the [FocusScopeNode] for a given /// * [FocusScope.of], which provides the [FocusScopeNode] for a given
/// [BuildContext]. /// [BuildContext].
...@@ -33,25 +33,25 @@ class FocusNode extends ChangeNotifier { ...@@ -33,25 +33,25 @@ class FocusNode extends ChangeNotifier {
FocusManager _manager; FocusManager _manager;
/// Whether this node has the overall focus. /// Whether this node has the overall focus.
/// ///
/// A [FocusNode] has the overall focus when the node is focused in its /// A [FocusNode] has the overall focus when the node is focused in its
/// parent [FocusScopeNode] and [FocusScopeNode.isFirstFocus] is true for /// parent [FocusScopeNode] and [FocusScopeNode.isFirstFocus] is true for
/// that scope and all its ancestor scopes. /// that scope and all its ancestor scopes.
/// ///
/// To request focus, find the [FocusScopeNode] for the current [BuildContext] /// To request focus, find the [FocusScopeNode] for the current [BuildContext]
/// and call the [FocusScopeNode.requestFocus] method: /// and call the [FocusScopeNode.requestFocus] method:
/// ///
/// ```dart /// ```dart
/// FocusScope.of(context).requestFocus(focusNode); /// FocusScope.of(context).requestFocus(focusNode);
/// ``` /// ```
/// ///
/// This object notifies its listeners whenever this value changes. /// This object notifies its listeners whenever this value changes.
bool get hasFocus => _manager?._currentFocus == this; bool get hasFocus => _manager?._currentFocus == this;
/// Cancels any oustanding requests for focus. /// Cancels any outstanding requests for focus.
/// ///
/// This method is safe to call regardless of whether this node has ever /// This method is safe to call regardless of whether this node has ever
/// requested focus. /// requested focus.
void unfocus() { void unfocus() {
_parent?._resignFocus(this); _parent?._resignFocus(this);
assert(_parent == null); assert(_parent == null);
...@@ -76,21 +76,21 @@ class FocusNode extends ChangeNotifier { ...@@ -76,21 +76,21 @@ class FocusNode extends ChangeNotifier {
} }
/// An interior node in the focus tree. /// An interior node in the focus tree.
/// ///
/// The focus tree keeps track of which widget is the user's current focus. The /// The focus tree keeps track of which widget is the user's current focus. The
/// focused widget often listens for keyboard events. /// focused widget often listens for keyboard events.
/// ///
/// The interior nodes in the focus tree cannot themselves be focused but /// The interior nodes in the focus tree cannot themselves be focused but
/// instead remember previous focus states. A scope is currently active in its /// instead remember previous focus states. A scope is currently active in its
/// parent whenever [isFirstFocus] is true. If that scope is detached from its /// parent whenever [isFirstFocus] is true. If that scope is detached from its
/// parent, its previous sibling becomes the parent's first focus. /// parent, its previous sibling becomes the parent's first focus.
/// ///
/// A [FocusNode] has the overall focus when the node is focused in its /// A [FocusNode] has the overall focus when the node is focused in its
/// parent [FocusScopeNode] and [FocusScopeNode.isFirstFocus] is true for /// parent [FocusScopeNode] and [FocusScopeNode.isFirstFocus] is true for
/// that scope and all its ancestor scopes. /// that scope and all its ancestor scopes.
/// ///
/// See also: /// See also:
/// ///
/// * [FocusNode], which is a leaf node in the focus tree that can receive /// * [FocusNode], which is a leaf node in the focus tree that can receive
/// focus. /// focus.
/// * [FocusScope.of], which provides the [FocusScopeNode] for a given /// * [FocusScope.of], which provides the [FocusScopeNode] for a given
...@@ -206,10 +206,10 @@ class FocusScopeNode extends Object with TreeDiagnosticsMixin { ...@@ -206,10 +206,10 @@ class FocusScopeNode extends Object with TreeDiagnosticsMixin {
} }
/// Requests that the given node becomes the focus for this scope. /// Requests that the given node becomes the focus for this scope.
/// ///
/// If the given node is currently focused in another scope, the node will /// If the given node is currently focused in another scope, the node will
/// first be unfocused in that scope. /// first be unfocused in that scope.
/// ///
/// The node will receive the overall focus if this [isFirstFocus] is true /// The node will receive the overall focus if this [isFirstFocus] is true
/// in this scope and all its ancestor scopes. The node is notified that it /// in this scope and all its ancestor scopes. The node is notified that it
/// has received the overall focus in a microtask. /// has received the overall focus in a microtask.
...@@ -228,10 +228,10 @@ class FocusScopeNode extends Object with TreeDiagnosticsMixin { ...@@ -228,10 +228,10 @@ class FocusScopeNode extends Object with TreeDiagnosticsMixin {
/// If this scope lacks a focus, request that the given node becomes the /// If this scope lacks a focus, request that the given node becomes the
/// focus. /// focus.
/// ///
/// Useful for widgets that wish to grab the focus if no other widget already /// Useful for widgets that wish to grab the focus if no other widget already
/// has the focus. /// has the focus.
/// ///
/// The node is notified that it has received the overall focus in a /// The node is notified that it has received the overall focus in a
/// microtask. /// microtask.
void autofocus(FocusNode node) { void autofocus(FocusNode node) {
...@@ -241,7 +241,7 @@ class FocusScopeNode extends Object with TreeDiagnosticsMixin { ...@@ -241,7 +241,7 @@ class FocusScopeNode extends Object with TreeDiagnosticsMixin {
} }
/// Adopts the given node if it is focused in another scope. /// Adopts the given node if it is focused in another scope.
/// ///
/// A widget that requests that a node is focused should call this method /// A widget that requests that a node is focused should call this method
/// during its `build` method in case the widget is moved from one location /// during its `build` method in case the widget is moved from one location
/// in the tree to another location that has a different focus scope. /// in the tree to another location that has a different focus scope.
...@@ -265,7 +265,7 @@ class FocusScopeNode extends Object with TreeDiagnosticsMixin { ...@@ -265,7 +265,7 @@ class FocusScopeNode extends Object with TreeDiagnosticsMixin {
} }
/// Makes the given child the first focus of this scope. /// Makes the given child the first focus of this scope.
/// ///
/// If the child has another parent scope, the child is first removed from /// If the child has another parent scope, the child is first removed from
/// that scope. After this method returns [isFirstFocus] will be true for /// that scope. After this method returns [isFirstFocus] will be true for
/// the child. /// the child.
...@@ -281,12 +281,12 @@ class FocusScopeNode extends Object with TreeDiagnosticsMixin { ...@@ -281,12 +281,12 @@ class FocusScopeNode extends Object with TreeDiagnosticsMixin {
} }
/// Adopts the given scope if it is the first focus of another scope. /// Adopts the given scope if it is the first focus of another scope.
/// ///
/// A widget that sets a scope as the first focus of another scope should /// A widget that sets a scope as the first focus of another scope should
/// call this method during its `build` method in case the widget is moved /// call this method during its `build` method in case the widget is moved
/// from one location in the tree to another location that has a different /// from one location in the tree to another location that has a different
/// focus scope. /// focus scope.
/// ///
/// If the given scope is not the first focus of its old parent, the scope /// If the given scope is not the first focus of its old parent, the scope
/// is simply detached from its old parent. /// is simply detached from its old parent.
void reparentScopeIfNeeded(FocusScopeNode child) { void reparentScopeIfNeeded(FocusScopeNode child) {
...@@ -300,9 +300,9 @@ class FocusScopeNode extends Object with TreeDiagnosticsMixin { ...@@ -300,9 +300,9 @@ class FocusScopeNode extends Object with TreeDiagnosticsMixin {
} }
/// Remove this scope from its parent child list. /// Remove this scope from its parent child list.
/// ///
/// This method is safe to call even if this scope does not have a parent. /// This method is safe to call even if this scope does not have a parent.
/// ///
/// A widget that sets a scope as the first focus of another scope should /// A widget that sets a scope as the first focus of another scope should
/// call this method during [State.dispose] to avoid leaving dangling /// call this method during [State.dispose] to avoid leaving dangling
/// children in their parent scope. /// children in their parent scope.
...@@ -343,18 +343,18 @@ class FocusScopeNode extends Object with TreeDiagnosticsMixin { ...@@ -343,18 +343,18 @@ class FocusScopeNode extends Object with TreeDiagnosticsMixin {
/// ///
/// The focus tree keeps track of which widget is the user's current focus. The /// The focus tree keeps track of which widget is the user's current focus. The
/// focused widget often listens for keyboard events. /// focused widget often listens for keyboard events.
/// ///
/// The focus manager is responsible for holding the [FocusScopeNode] that is /// The focus manager is responsible for holding the [FocusScopeNode] that is
/// the root of the focus tree and tracking which [FocusNode] has the overall /// the root of the focus tree and tracking which [FocusNode] has the overall
/// focus. /// focus.
/// ///
/// The [FocusManager] is held by the [WidgetBinding] as /// The [FocusManager] is held by the [WidgetBinding] as
/// [WidgetBinding.focusManager]. The [FocusManager] is rarely accessed /// [WidgetBinding.focusManager]. The [FocusManager] is rarely accessed
/// directly. Instead, to find the [FocusScopeNode] for a given [BuildContext], /// directly. Instead, to find the [FocusScopeNode] for a given [BuildContext],
/// use [FocusScope.of]. /// use [FocusScope.of].
/// ///
/// See also: /// See also:
/// ///
/// * [FocusNode], which is a leaf node in the focus tree that can receive /// * [FocusNode], which is a leaf node in the focus tree that can receive
/// focus. /// focus.
/// * [FocusScopeNode], which is an interior node in the focus tree. /// * [FocusScopeNode], which is an interior node in the focus tree.
...@@ -362,7 +362,7 @@ class FocusScopeNode extends Object with TreeDiagnosticsMixin { ...@@ -362,7 +362,7 @@ class FocusScopeNode extends Object with TreeDiagnosticsMixin {
/// [BuildContext]. /// [BuildContext].
class FocusManager { class FocusManager {
/// Creates an object that manages the focus tree. /// Creates an object that manages the focus tree.
/// ///
/// This constructor is rarely called directly. To access the [FocusManager], /// This constructor is rarely called directly. To access the [FocusManager],
/// consider using [WidgetBinding.focusManager] instead. /// consider using [WidgetBinding.focusManager] instead.
FocusManager() { FocusManager() {
...@@ -372,7 +372,7 @@ class FocusManager { ...@@ -372,7 +372,7 @@ class FocusManager {
} }
/// The root [FocusScopeNode] in the focus tree. /// The root [FocusScopeNode] in the focus tree.
/// ///
/// This field is rarely used direction. Instead, to find the /// This field is rarely used direction. Instead, to find the
/// [FocusScopeNode] for a given [BuildContext], use [FocusScope.of]. /// [FocusScopeNode] for a given [BuildContext], use [FocusScope.of].
final FocusScopeNode rootScope = new FocusScopeNode(); final FocusScopeNode rootScope = new FocusScopeNode();
......
...@@ -27,31 +27,31 @@ class _FocusScopeMarker extends InheritedWidget { ...@@ -27,31 +27,31 @@ class _FocusScopeMarker extends InheritedWidget {
} }
/// Establishes a scope in which widgets can receive focus. /// Establishes a scope in which widgets can receive focus.
/// ///
/// The focus tree keeps track of which widget is the user's current focus. The /// The focus tree keeps track of which widget is the user's current focus. The
/// focused widget often listens for keyboard events. /// focused widget often listens for keyboard events.
/// ///
/// The a focus scope does not itself receive focus but instead helps remember /// The a focus scope does not itself receive focus but instead helps remember
/// previous focus states. A scope is currently active when its [node] is the /// previous focus states. A scope is currently active when its [node] is the
/// first focus of its parent scope. To activate a [FocusScope], either use the /// first focus of its parent scope. To activate a [FocusScope], either use the
/// [autofocus] property or explicitly make the [node] the first focus in the /// [autofocus] property or explicitly make the [node] the first focus in the
/// parent scope: /// parent scope:
/// ///
/// ```dart /// ```dart
/// FocusScope.of(context).setFirstFocus(node); /// FocusScope.of(context).setFirstFocus(node);
/// ``` /// ```
/// ///
/// When a [FocusScope] is removed from the tree, the previously active /// When a [FocusScope] is removed from the tree, the previously active
/// [FocusScope] becomes active again. /// [FocusScope] becomes active again.
/// ///
/// See also: /// See also:
/// ///
/// * [FocusScopeNode], which is the associated node in the focus tree. /// * [FocusScopeNode], which is the associated node in the focus tree.
/// * [FocusNode], which is a leaf node in the focus tree that can receive /// * [FocusNode], which is a leaf node in the focus tree that can receive
/// focus. /// focus.
class FocusScope extends StatefulWidget { class FocusScope extends StatefulWidget {
/// Creates a scope in which widgets can receive focus. /// Creates a scope in which widgets can receive focus.
/// ///
/// The [node] argument must not be null. /// The [node] argument must not be null.
FocusScope({ FocusScope({
Key key, Key key,
...@@ -73,6 +73,8 @@ class FocusScope extends StatefulWidget { ...@@ -73,6 +73,8 @@ class FocusScope extends StatefulWidget {
/// The widget below this widget in the tree. /// The widget below this widget in the tree.
final Widget child; final Widget child;
/// Returns the [node] of the [FocusScope] that most tightly encloses the
/// given [BuildContext].
static FocusScopeNode of(BuildContext context) { static FocusScopeNode of(BuildContext context) {
final _FocusScopeMarker scope = context.inheritFromWidgetOfExactType(_FocusScopeMarker); final _FocusScopeMarker scope = context.inheritFromWidgetOfExactType(_FocusScopeMarker);
return scope?.node ?? WidgetsBinding.instance.focusManager.rootScope; return scope?.node ?? WidgetsBinding.instance.focusManager.rootScope;
......
...@@ -24,6 +24,9 @@ import 'viewport.dart'; ...@@ -24,6 +24,9 @@ import 'viewport.dart';
/// A controller for [PageView]. /// A controller for [PageView].
/// ///
/// A page controller lets you manipulate which page is visible in a [PageView]. /// A page controller lets you manipulate which page is visible in a [PageView].
/// In addition to being able to control the pixel offset of the content inside
/// the [PageView], a [PageController] also lets you control the offset in terms
/// of pages, which are increments of the viewport size.
/// ///
/// See also: /// See also:
/// ///
...@@ -252,14 +255,33 @@ final PageController _defaultPageController = new PageController(); ...@@ -252,14 +255,33 @@ final PageController _defaultPageController = new PageController();
const PageScrollPhysics _kPagePhysics = const PageScrollPhysics(); const PageScrollPhysics _kPagePhysics = const PageScrollPhysics();
/// A scrollable list that works page by page. /// A scrollable list that works page by page.
// TODO(ianh): More documentation here. ///
/// Each child of a page view is forced to be the same size as the viewport.
///
/// You can use a [PageController] to control which page is visible in the view.
/// In addition to being able to control the pixel offset of the content inside
/// the [PageView], a [PageController] also lets you control the offset in terms
/// of pages, which are increments of the viewport size.
///
/// The [PageController] can also be used to control the
/// [PageController.initialPage], which determines which page is shown when the
/// [PageView] is first constructed, and the [PageController.viewportFraction],
/// which determines the size of the pages as a fraction of the viewport size.
/// ///
/// See also: /// See also:
/// ///
/// * [SingleChildScrollView], when you need to make a single child scrollable. /// * [PageController], which controls which page is visible in the view.
/// * [ListView], for a scrollable list of boxes. /// * [SingleChildScrollView], when you need to make a single child scrollable.
/// * [GridView], for a scrollable grid of boxes. /// * [ListView], for a scrollable list of boxes.
/// * [GridView], for a scrollable grid of boxes.
class PageView extends StatefulWidget { class PageView extends StatefulWidget {
/// Creates a scrollable list that works page by page from an explicit [List]
/// of widgets.
///
/// This constructor is appropriate for page views with a small number of
/// children because constructing the [List] requires doing work for every
/// child that could possibly be displayed in the page view, instead of just
/// those children that are actually visible.
PageView({ PageView({
Key key, Key key,
this.scrollDirection: Axis.horizontal, this.scrollDirection: Axis.horizontal,
...@@ -272,6 +294,18 @@ class PageView extends StatefulWidget { ...@@ -272,6 +294,18 @@ class PageView extends StatefulWidget {
childrenDelegate = new SliverChildListDelegate(children), childrenDelegate = new SliverChildListDelegate(children),
super(key: key); super(key: key);
/// Creates a scrollable list that works page by page using widgets that are
/// created on demand.
///
/// This constructor is appropriate for page views with a large (or infinite)
/// number of children because the builder is called only for those children
/// that are actually visible.
///
/// Providing a non-null [itemCount] lets the [PageView] compute the maximum
/// scroll extent.
///
/// [itemBuilder] will be called only with indices greater than or equal to
/// zero and less than [itemCount].
PageView.builder({ PageView.builder({
Key key, Key key,
this.scrollDirection: Axis.horizontal, this.scrollDirection: Axis.horizontal,
...@@ -285,6 +319,8 @@ class PageView extends StatefulWidget { ...@@ -285,6 +319,8 @@ class PageView extends StatefulWidget {
childrenDelegate = new SliverChildBuilderDelegate(itemBuilder, childCount: itemCount), childrenDelegate = new SliverChildBuilderDelegate(itemBuilder, childCount: itemCount),
super(key: key); super(key: key);
/// Creates a scrollable list that works page by page with a custom child
/// model.
PageView.custom({ PageView.custom({
Key key, Key key,
this.scrollDirection: Axis.horizontal, this.scrollDirection: Axis.horizontal,
...@@ -297,16 +333,49 @@ class PageView extends StatefulWidget { ...@@ -297,16 +333,49 @@ class PageView extends StatefulWidget {
assert(childrenDelegate != null); assert(childrenDelegate != null);
} }
/// The axis along which the page view scrolls.
///
/// Defaults to [Axis.horizontal].
final Axis scrollDirection; final Axis scrollDirection;
/// Whether the page view scrolls in the reading direction.
///
/// For example, if the reading direction is left-to-right and
/// [scrollDirection] is [Axis.horizontal], then the page 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 page 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;
/// An object that can be used to control the position to which this page
/// view is scrolled.
final PageController controller; final PageController controller;
/// How the page view should respond to user input.
///
/// For example, determines how the page view continues to animate after the
/// user stops dragging the page view.
///
/// The physics are modified to snap to page boundaries using
/// [PageScrollPhysics] prior to being used.
///
/// Defaults to matching platform conventions.
final ScrollPhysics physics; final ScrollPhysics physics;
/// Called whenever the page in the center of the viewport changes.
final ValueChanged<int> onPageChanged; final ValueChanged<int> onPageChanged;
/// A delegate that provides the children for the [PageView].
///
/// The [PageView.custom] constructor lets you specify this delegate
/// explicitly. The [PageView] and [PageView.builder] constructors create a
/// [childrenDelegate] that wraps the given [List] and [IndexedWidgetBuilder],
/// respectively.
final SliverChildDelegate childrenDelegate; final SliverChildDelegate childrenDelegate;
@override @override
......
...@@ -61,6 +61,16 @@ class ScrollBehavior { ...@@ -61,6 +61,16 @@ class ScrollBehavior {
return null; return null;
} }
/// Called whenever a [ScrollConfiguration] is rebuilt with a new
/// [ScrollBehavior] of the same [runtimeType].
///
/// If the new instance represents different information than the old
/// instance, then the method should return true, otherwise it should return
/// false.
///
/// If this method returns true, all the widgets that inherit from the
/// [ScrollConfiguration] will rebuild using the new [ScrollBehavior]. If this
/// method returns false, the rebuilds might be optimized away.
bool shouldNotify(covariant ScrollBehavior oldDelegate) => false; bool shouldNotify(covariant ScrollBehavior oldDelegate) => false;
} }
...@@ -88,9 +98,9 @@ class ScrollConfiguration extends InheritedWidget { ...@@ -88,9 +98,9 @@ class ScrollConfiguration extends InheritedWidget {
} }
@override @override
bool updateShouldNotify(ScrollConfiguration old) { bool updateShouldNotify(ScrollConfiguration oldWidget) {
assert(behavior != null); assert(behavior != null);
return behavior.runtimeType != old.behavior.runtimeType return behavior.runtimeType != oldWidget.behavior.runtimeType
|| behavior.shouldNotify(old.behavior); || (behavior != oldWidget.behavior && behavior.shouldNotify(oldWidget.behavior));
} }
} }
...@@ -75,7 +75,7 @@ abstract class ScrollView extends StatelessWidget { ...@@ -75,7 +75,7 @@ abstract class ScrollView extends StatelessWidget {
/// left to right when [reverse] is false and from right to left when /// left to right when [reverse] is false and from right to left when
/// [reverse] is true. /// [reverse] is true.
/// ///
/// Similarly, if [scrollDirection] is [Axis.vertical], then scroll view /// Similarly, if [scrollDirection] is [Axis.vertical], then the scroll view
/// scrolls from top to bottom when [reverse] is false and from bottom to top /// scrolls from top to bottom when [reverse] is false and from bottom to top
/// when [reverse] is true. /// when [reverse] is true.
/// ///
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment