Commit 1f4f75bb authored by Ian Hickson's avatar Ian Hickson Committed by GitHub

More documentation. (#10653)

parent 272faba1
......@@ -90,7 +90,7 @@ Future<Null> main() async {
block.add(line.substring(3));
}
} else if (inSampleSection) {
if (!trimmedLine.startsWith(kDartDocPrefix) || trimmedLine.startsWith('/// ##')) {
if (!trimmedLine.startsWith(kDartDocPrefix) || trimmedLine.startsWith('/// ## ')) {
if (inDart)
throw '${file.path}:$lineNumber: Dart section inexplicably unterminated.';
if (!foundDart)
......@@ -160,6 +160,8 @@ dependencies:
);
stderr.addStream(process.stderr);
final List<String> errors = await process.stdout.transform<String>(UTF8.decoder).transform<String>(const LineSplitter()).toList();
if (errors.first == 'Building flutter tool...')
errors.removeAt(0);
if (errors.first.startsWith('Running "flutter packages get" in '))
errors.removeAt(0);
if (errors.first.startsWith('Analyzing '))
......
......@@ -237,10 +237,11 @@ class ProxyAnimation extends Animation<double>
/// An animation that is the reverse of another animation.
///
/// If the parent animation is running forward from 0.0 to 1.0, this animation
/// is running in reverse from 1.0 to 0.0. Notice that using a ReverseAnimation
/// is different from simply using a [Tween] with a begin of 1.0 and an end of
/// 0.0 because the tween does not change the status or direction of the
/// animation.
/// is running in reverse from 1.0 to 0.0.
///
/// Using a [ReverseAnimation] is different from simply using a [Tween] with a
/// begin of 1.0 and an end of 0.0 because the tween does not change the status
/// or direction of the animation.
class ReverseAnimation extends Animation<double>
with AnimationLazyListenerMixin, AnimationLocalStatusListenersMixin {
......
......@@ -398,10 +398,16 @@ class DropdownButtonHideUnderline extends InheritedWidget {
/// shows the currently selected item as well as an arrow that opens a menu for
/// selecting another item.
///
/// The type `T` is the type of the values the dropdown menu represents. All the
/// entries in a given menu must represent values with consistent types.
/// Typically, an enum is used. Each [DropdownMenuItem] in [items] must be
/// specialized with that same type argument.
///
/// Requires one of its ancestors to be a [Material] widget.
///
/// See also:
///
/// * [DropdownMenuItem], the class used to represent the [items].
/// * [DropdownButtonHideUnderline], which prevents its descendant dropdown buttons
/// from displaying their underlines.
/// * [RaisedButton], [FlatButton], ordinary buttons that trigger a single action.
......
......@@ -16,6 +16,12 @@ import 'basic_types.dart';
///
/// `FractionalOffset(0.5, 2.0)` represents a point half way across the [Size],
/// below the bottom of the rectangle by the height of the [Size].
///
/// A variety of widgets use [FractionalOffset] in their configuration, most
/// notably:
///
/// * [Align] positions a child according to a [FractionalOffset].
/// * [FractionalTranslation] moves a child according to a [FractionalOffset].
@immutable
class FractionalOffset {
/// Creates a fractional offset.
......
......@@ -98,7 +98,9 @@ class TextSpan {
/// object that manages the [TextSpan] painting is also responsible for
/// dispatching events. In the rendering library, that is the
/// [RenderParagraph] object, which corresponds to the [RichText] widget in
/// the widgets layer.
/// the widgets layer; these objects do not bubble events in [TextSpan]s, so a
/// [recognizer] is only effective for events that directly hit the [text] of
/// that [TextSpan], not any of its [children].
///
/// [TextSpan] also does not manage the lifetime of the gesture recognizer.
/// The code that owns the [GestureRecognizer] object must call
......
......@@ -9,6 +9,127 @@ import 'package:flutter/foundation.dart';
import 'basic_types.dart';
/// An immutable style in which paint text.
///
/// ## Sample code
///
/// ### Bold
///
/// Here, a single line of text in a [Text] widget is given a specific style
/// override. The style is mixed with the ambient [DefaultTextStyle] by the
/// [Text] widget.
///
/// ```dart
/// new Text(
/// 'No, we need bold strokes. We need this plan.',
/// style: new TextStyle(fontWeight: FontWeight.bold),
/// )
/// ```
///
/// ### Italics
///
/// As in the previous example, the [Text] widget is given a specific style
/// override which is implicitly mixed with the ambient [DefaultTextStyle].
///
/// ```dart
/// new Text(
/// 'Welcome to the present, we\'re running a real nation.',
/// style: new TextStyle(fontStyle: FontStyle.italic),
/// )
/// ```
///
/// ### Opacity
///
/// Each line here is progressively more opaque. The base color is
/// [Colors.black], and [Color.withOpacity] is used to create a derivative color
/// with the desired opacity. The root [TextSpan] for this [RichText] widget is
/// explicitly given the ambient [DefaultTextStyle], since [RichText] does not
/// do that automatically. The inner [TextStyle] objects are implicitly mixed
/// with the parent [TextSpan]'s [TextSpan.style].
///
/// ```dart
/// new RichText(
/// text: new TextSpan(
/// style: DefaultTextStyle.of(context).style,
/// children: <TextSpan>[
/// new TextSpan(
/// text: 'You don\'t have the votes.\n',
/// style: new TextStyle(color: Colors.black.withOpacity(0.6)),
/// ),
/// new TextSpan(
/// text: 'You don\'t have the votes!\n',
/// style: new TextStyle(color: Colors.black.withOpacity(0.8)),
/// ),
/// new TextSpan(
/// text: 'You\'re gonna need congressional approval and you don\'t have the votes!\n',
/// style: new TextStyle(color: Colors.black.withOpacity(1.0)),
/// ),
/// ],
/// ),
/// )
/// ```
///
/// ### Size
///
/// In this example, the ambient [DefaultTextStyle] is explicitly manipulated to
/// obtain a [TextStyle] that doubles the default font size.
///
/// ```dart
/// new Text(
/// 'These are wise words, enterprising men quote \'em.',
/// style: DefaultTextStyle.of(context).style.apply(fontSizeFactor: 2.0),
/// )
/// ```
///
/// ### Line height
///
/// The [height] property can be used to change the line height. Here, the line
/// height is set to 100 logical pixels, so that the text is very spaced out.
///
/// ```dart
/// new Text(
/// 'Don\'t act surprised, you guys, cuz I wrote \'em!',
/// style: new TextStyle(height: 100.0),
/// )
/// ```
///
/// ### Wavy red underline with black text
///
/// Styles can be combined. In this example, the misspelt word is drawn in black
/// text and underlined with a wavy red line to indicate a spelling error. (The
/// remainder is styled according to the Flutter default text styles, not the
/// ambient [DefaultTextStyle], since no explicit style is given and [RichText]
/// does not automatically use the ambient [DefaultTextStyle].)
///
/// ```dart
/// new RichText(
/// text: new TextSpan(
/// text: 'Don\'t tax the South ',
/// children: <TextSpan>[
/// new TextSpan(
/// text: 'cuz',
/// style: new TextStyle(
/// color: Colors.black,
/// decoration: TextDecoration.underline,
/// decorationColor: Colors.red,
/// decorationStyle: TextDecorationStyle.wavy,
/// ),
/// ),
/// new TextSpan(
/// text: ' we got it made in the shade',
/// ),
/// ],
/// ),
/// )
/// ```
///
/// See also:
///
/// * [Text], the widget for showing text in a single style.
/// * [DefaultTextStyle], the widget that specifies the default text styles for
/// [Text] widgets, configured using a [TextStyle].
/// * [RichText], the widget for showing a paragraph of mix-style text.
/// * [TextSpan], the class that wraps a [TextStyle] for the purposes of
/// passing it to a [RichText].
@immutable
class TextStyle {
/// Creates a text style.
......@@ -25,10 +146,15 @@ class TextStyle {
this.height,
this.decoration,
this.decorationColor,
this.decorationStyle
this.decorationStyle,
}) : assert(inherit != null);
/// Whether null values are replaced with their value in an ancestor text style (e.g., in a [TextSpan] tree).
/// Whether null values are replaced with their value in an ancestor text
/// style (e.g., in a [TextSpan] tree).
///
/// If this is false, properties that don't have explicit values will revert
/// to the defaults: white in color, a font size of 10 pixels, in a sans-serif
/// font face.
final bool inherit;
/// The color to use when painting the text.
......@@ -54,11 +180,13 @@ class TextStyle {
/// A negative value can be used to bring the letters closer.
final double letterSpacing;
/// The amount of space (in logical pixels) to add at each sequence of white-space (i.e. between each word).
/// A negative value can be used to bring the words closer.
/// The amount of space (in logical pixels) to add at each sequence of
/// white-space (i.e. between each word). A negative value can be used to
/// bring the words closer.
final double wordSpacing;
/// The common baseline that should be aligned between this text span and its parent text span, or, for the root text spans, with the line box.
/// The common baseline that should be aligned between this text span and its
/// parent text span, or, for the root text spans, with the line box.
final TextBaseline textBaseline;
/// The height of this text span, as a multiple of the font size.
......@@ -77,7 +205,8 @@ class TextStyle {
/// The style in which to paint the text decorations (e.g., dashed).
final TextDecorationStyle decorationStyle;
/// Creates a copy of this text style but with the given fields replaced with the new values.
/// Creates a copy of this text style but with the given fields replaced with
/// the new values.
TextStyle copyWith({
Color color,
String fontFamily,
......@@ -90,7 +219,7 @@ class TextStyle {
double height,
TextDecoration decoration,
Color decorationColor,
TextDecorationStyle decorationStyle
TextDecorationStyle decorationStyle,
}) {
return new TextStyle(
inherit: inherit,
......@@ -105,7 +234,7 @@ class TextStyle {
height: height ?? this.height,
decoration: decoration ?? this.decoration,
decorationColor: decorationColor ?? this.decorationColor,
decorationStyle: decorationStyle ?? this.decorationStyle
decorationStyle: decorationStyle ?? this.decorationStyle,
);
}
......
......@@ -23,18 +23,63 @@ class _DebugSize extends Size {
/// Immutable layout constraints for [RenderBox] layout.
///
/// A size respects a [BoxConstraints] if, and only if, all of the following
/// A [Size] respects a [BoxConstraints] if, and only if, all of the following
/// relations hold:
///
/// * `minWidth <= size.width <= maxWidth`
/// * `minHeight <= size.height <= maxHeight`
/// * [minWidth] <= [Size.width] <= [maxWidth]
/// * [minHeight] <= [Size.height] <= [maxHeight]
///
/// The constraints themselves must satisfy these relations:
///
/// * `0.0 <= minWidth <= maxWidth <= double.INFINITY`
/// * `0.0 <= minHeight <= maxHeight <= double.INFINITY`
/// * 0.0 <= [minWidth] <= [maxWidth] <= [double.INFINITY]
/// * 0.0 <= [minHeight] <= [maxHeight] <= [double.INFINITY]
///
/// [double.INFINITY] is a legal value for each constraint.
///
/// ## The box layout model
///
/// Render objects in the Flutter framework are laid out by a one-pass layout
/// model which walks down the render tree passing constraints, then walks back
/// up the render tree passing concrete geometry.
///
/// For boxes, the constraints are [BoxConstraints], which, as described herein,
/// consist of four numbers: a minimum width [minWidth], a maximum width
/// [maxWidth], a minimum height [minHeight], and a maximum height [maxHeight].
///
/// The geometry for boxes consists of a [Size], which must satisfy the
/// constraints described above.
///
/// Each [RenderBox] (the objects that provide the layout models for box
/// widgets) receives [BoxConstraints] from its parent, then lays out each of
/// its children, then picks a [Size] that satisfies the [BoxConstraints].
///
/// Render objects position their children independently of laying them out.
/// Frequently, the parent will use the children's sizes to determine their
/// position. A child does not know its position and will not necessarily be
/// laid out again, or repainted, if its position changes.
///
/// ## Terminology
///
/// When the minimum constraints and the maximum constraint in an axis are the
/// same, that axis is _tightly_ constrained. See: [new
/// BoxConstraints.tightFor], [new BoxConstraints.tightForFinite], [tighten],
/// [hasTightWidth], [hasTightHeight], [isTight].
///
/// An axis with a minimum constraint of 0.0 is _loose_ (regardless of the
/// maximum constraint; if it is also 0.0, then the axis is simultaneously tight
/// and loose!). See: [new BoxConstraints.loose], [loosen].
///
/// An axis whose maximum constraint is not infinite is _bounded_. See:
/// [hasBoundedWidth], [hasBoundedHeight].
///
/// An axis whose maximum constraint is infinite is _unbounded_. An axis is
/// _expanding_ if it is tightly infinite (its minimum and maximum constraints
/// are both infinite). See: [new BoxConstraints.expand].
///
/// A size is _constrained_ when it satisfies a [BoxConstraints] description.
/// See: [constrain], [constrainWidth], [constrainHeight],
/// [constrainDimensions], [constrainSizeAndAttemptToPreserveAspectRatio],
/// [isSatisfiedBy].
class BoxConstraints extends Constraints {
/// Creates box constraints with the given constraints.
const BoxConstraints({
......@@ -68,6 +113,12 @@ class BoxConstraints extends Constraints {
maxHeight = size.height;
/// Creates box constraints that require the given width or height.
///
/// See also:
///
/// * [new BoxConstraints.tightForFinite], which is similar but instead of
/// being tight if the value is non-null, is tight if the value is not
/// infinite.
const BoxConstraints.tightFor({
double width,
double height
......@@ -76,7 +127,13 @@ class BoxConstraints extends Constraints {
minHeight = height != null ? height : 0.0,
maxHeight = height != null ? height : double.INFINITY;
/// Creates box constraints that require the given width or height, except if they are infinite.
/// Creates box constraints that require the given width or height, except if
/// they are infinite.
///
/// See also:
///
/// * [new BoxConstraints.tightFor], which is similar but instead of being
/// tight if the value is not infinite, is tight if the value is non-null.
const BoxConstraints.tightForFinite({
double width: double.INFINITY,
double height: double.INFINITY
......@@ -230,10 +287,10 @@ class BoxConstraints extends Constraints {
/// Returns a size that attempts to meet the following conditions, in order:
///
/// - The size must satisfy these constraints.
/// - The aspect ratio of the returned size matches the aspect ratio of the
/// * The size must satisfy these constraints.
/// * The aspect ratio of the returned size matches the aspect ratio of the
/// given size.
/// - The returned size as big as possible while still being equal to or
/// * The returned size as big as possible while still being equal to or
/// smaller than the given size.
Size constrainSizeAndAttemptToPreserveAspectRatio(Size size) {
if (isTight) {
......@@ -1698,9 +1755,10 @@ abstract class RenderBox extends RenderObject {
/// Determines the set of render objects located at the given position.
///
/// Returns true if the given point is contained in this render object or one
/// of its descendants. Adds any render objects that contain the point to the
/// given hit test result.
/// Returns true, and adds any render objects that contain the point to the
/// given hit test result, if this render object or one of its descendants
/// absorbs the hit (preventing objects below this one from being hit).
/// Returns false if the hit can continue to other objects below this one.
///
/// The caller is responsible for transforming [position] into the local
/// coordinate space of the callee. The callee is responsible for checking
......
......@@ -544,7 +544,10 @@ class RenderAspectRatio extends RenderProxyBox {
/// you would like a child that would otherwise attempt to expand infinitely to
/// instead size itself to a more reasonable width.
///
/// This class is relatively expensive. Avoid using it where possible.
/// This class is relatively expensive, because it adds a speculative layout
/// pass before the final layout phase. Avoid using it where possible. In the
/// worst case, this render object can result in a layout that is O(N²) in the
/// depth of the tree.
class RenderIntrinsicWidth extends RenderProxyBox {
/// Creates a render object that sizes itself to its child's intrinsic width.
RenderIntrinsicWidth({
......@@ -650,7 +653,10 @@ class RenderIntrinsicWidth extends RenderProxyBox {
/// you would like a child that would otherwise attempt to expand infinitely to
/// instead size itself to a more reasonable height.
///
/// This class is relatively expensive. Avoid using it where possible.
/// This class is relatively expensive, because it adds a speculative layout
/// pass before the final layout phase. Avoid using it where possible. In the
/// worst case, this render object can result in a layout that is O(N²) in the
/// depth of the tree.
class RenderIntrinsicHeight extends RenderProxyBox {
/// Creates a render object that sizes itself to its child's intrinsic height.
RenderIntrinsicHeight({
......
......@@ -29,21 +29,27 @@ enum CrossFadeState {
///
/// The animation is controlled through the [crossFadeState] parameter.
/// [firstCurve] and [secondCurve] represent the opacity curves of the two
/// children. Note that [firstCurve] is inverted, i.e. it fades out when
/// providing a growing curve like [Curves.linear]. [sizeCurve] is the curve
/// used to animated between the size of the fading out child and the size of
/// the fading in child.
/// children. The [firstCurve] is inverted, i.e. it fades out when providing a
/// growing curve like [Curves.linear]. The [sizeCurve] is the curve used to
/// animated between the size of the fading out child and the size of the fading
/// in child.
///
/// This widget is intended to be used to fade a pair of widgets with the same
/// width. In the case where the two children have different heights, the
/// animation crops overflowing children during the animation by aligning their
/// top edge, which means that the bottom will be clipped.
///
/// The animation is automatically triggered when an existing
/// [AnimatedCrossFade] is rebuilt with a different value for the
/// [crossFadeState] property.
///
/// ## Sample code
///
/// This code fades between two representations of the Flutter logo. It depends
/// on a global boolean `_on`; when `_on` is true, the first logo is shown,
/// otherwise the second logo is shown.
/// on a boolean field `_on`; when `_on` is true, the first logo is shown,
/// otherwise the second logo is shown. When the field changes state, the
/// [AnimatedCrossFade] widget cross-fades between the two forms of the logo
/// over three seconds.
///
/// ```dart
/// new AnimatedCrossFade(
......
......@@ -330,7 +330,7 @@ class CustomPaint extends SingleChildRenderObjectWidget {
/// custom [clipper].
///
/// [ClipRect] is commonly used with these widgets, which commonly paint outside
/// their bounds.
/// their bounds:
///
/// * [CustomPaint]
/// * [CustomSingleChildLayout]
......@@ -342,8 +342,8 @@ class CustomPaint extends SingleChildRenderObjectWidget {
///
/// ## Sample code
///
/// For example, use a clip to show the top half of an [Image], you can use a
/// [ClipRect] combined with an [Align]:
/// For example, by combining a [ClipRect] with an [Align], one can show just
/// the top half of an [Image]:
///
/// ```dart
/// new ClipRect(
......@@ -1693,7 +1693,10 @@ class AspectRatio extends SingleChildRenderObjectWidget {
/// you would like a child that would otherwise attempt to expand infinitely to
/// instead size itself to a more reasonable width.
///
/// This class is relatively expensive. Avoid using it where possible.
/// This class is relatively expensive, because it adds a speculative layout
/// pass before the final layout phase. Avoid using it where possible. In the
/// worst case, this widget can result in a layout that is O(N²) in the depth of
/// the tree.
class IntrinsicWidth extends SingleChildRenderObjectWidget {
/// Creates a widget that sizes its child to the child's intrinsic width.
///
......@@ -1724,7 +1727,10 @@ class IntrinsicWidth extends SingleChildRenderObjectWidget {
/// you would like a child that would otherwise attempt to expand infinitely to
/// instead size itself to a more reasonable height.
///
/// This class is relatively expensive. Avoid using it where possible.
/// This class is relatively expensive, because it adds a speculative layout
/// pass before the final layout phase. Avoid using it where possible. In the
/// worst case, this widget can result in a layout that is O(N²) in the depth of
/// the tree.
class IntrinsicHeight extends SingleChildRenderObjectWidget {
/// Creates a widget that sizes its child to the child's intrinsic height.
///
......@@ -2236,6 +2242,7 @@ class Positioned extends ParentDataWidget<Stack> {
/// ## Layout algorithm
///
/// _This section describes how a [Flex] is rendered by the framework._
/// _See [BoxConstraints] for an introduction to box layout models._
///
/// Layout for a [Flex] proceeds in six steps:
///
......@@ -2459,6 +2466,7 @@ class Flex extends MultiChildRenderObjectWidget {
/// ## Layout algorithm
///
/// _This section describes how a [Row] is rendered by the framework._
/// _See [BoxConstraints] for an introduction to box layout models._
///
/// Layout for a [Row] proceeds in six steps:
///
......@@ -2583,6 +2591,7 @@ class Row extends Flex {
/// ## Layout algorithm
///
/// _This section describes how a [Column] is rendered by the framework._
/// _See [BoxConstraints] for an introduction to box layout models._
///
/// Layout for a [Column] proceeds in six steps:
///
......@@ -3000,7 +3009,8 @@ class Flow extends MultiChildRenderObjectWidget {
///
/// Text displayed in a [RichText] widget must be explicitly styled. When
/// picking which style to use, consider using [DefaultTextStyle.of] the current
/// [BuildContext] to provide defaults.
/// [BuildContext] to provide defaults. For more details on how to style text in
/// a [RichText] widget, see the documentation for [TextStyle].
///
/// When all the text uses the same style, consider using the [Text] widget,
/// which is less verbose and integrates with [DefaultTextStyle] for default
......@@ -3023,6 +3033,7 @@ class Flow extends MultiChildRenderObjectWidget {
///
/// See also:
///
/// * [TextStyle], which discusses how to style text.
/// * [TextSpan], which is used to describe the text in a paragraph.
/// * [Text], which automatically applies the ambient styles described by a
/// [DefaultTextStyle] to a single string.
......@@ -3323,6 +3334,10 @@ class WidgetToRenderBoxAdapter extends LeafRenderObjectWidget {
/// Rather than listening for raw pointer events, consider listening for
/// higher-level gestures using [GestureDetector].
///
/// ## Layout behavior
///
/// _See [BoxConstraints] for an introduction to box layout models._
///
/// If it has a child, this widget defers to the child for sizing behavior. If
/// it does not have a child, it grows to fit the parent instead.
class Listener extends SingleChildRenderObjectWidget {
......
......@@ -124,6 +124,50 @@ class DecoratedBox extends SingleChildRenderObjectWidget {
/// `width`, `height`, and [constraints] arguments to the constructor override
/// this.
///
/// ## Layout behavior
///
/// _See [BoxConstraints] for an introduction to box layout models._
///
/// Since [Container] combines a number of other widgets each with their own
/// layout behavior, [Container]'s layout behaviour is somewhat complicated.
///
/// tl;dr: [Container] tries, in order: to honor [alignment], to size itself to
/// the [child], to honor the `width`, `height`, and [constraints], to expand to
/// fit the parent, to be as small as possible.
///
/// More specifically:
///
/// If the widget has no child, no `height`, no `width`, no [constraints],
/// and the parent provides unbounded constraints, then [Container] tries to
/// size as small as possible.
///
/// If the widget has no child and no [alignment], but a `height`, `width`, or
/// [constraints] are provided, then the [Container] tries to be as small as
/// possible given the combination of those constraints and the parent's
/// constraints.
///
/// If the widget has no child, no `height`, no `width`, no [constraints], and
/// no [alignment], but the parent provides bounded constraints, then
/// [Container] expands to fit the constraints provided by the parent.
///
/// If the widget has an [alignment], and the parent provides unbounded
/// constraints, then the [Container] tries to size itself around the child.
///
/// If the widget has an [alignment], and the parent provides bounded
/// constraints, then the [Container] tries to expand to fit the parent, and
/// then positions the child within itself as per the [alignment].
///
/// Otherwise, the widget has a [child] but no `height`, no `width`, no
/// [constraints], and no [alignment], and the [Container] passes the
/// constraints from the parent to the child and sizes itself to match the
/// child.
///
/// The [margin] and [padding] properties also affect the layout, as described
/// in the documentation for those properties. (Their effects merely augment the
/// rules described above.) The [decoration] can implicitly increase the
/// [padding] (e.g. borders in a [BoxDecoration] contribute to the [padding]);
/// see [Decoration.padding].
///
/// ## Sample code
///
/// This example shows a 48x48 green square (placed inside a [Center] widget in
......
......@@ -104,6 +104,23 @@ class GestureRecognizerFactoryWithHandlers<T extends GestureRecognizer> extends
/// Material design applications typically react to touches with ink splash
/// effects. The [InkWell] class implements this effect and can be used in place
/// of a [GestureDetector] for handling taps.
///
/// ## Sample code
///
/// This example makes a rectangle react to being tapped by setting the
/// `_lights` field:
///
/// ```dart
/// new GestureDetector(
/// onTap: () {
/// setState(() { _lights = true; });
/// },
/// child: new Container(
/// color: Colors.yellow,
/// child: new Text('TURN LIGHTS ON'),
/// ),
/// )
/// ```
class GestureDetector extends StatelessWidget {
/// Creates a widget that detects gestures.
///
......
......@@ -10,15 +10,15 @@ import 'package:flutter/widgets.dart';
/// this notification has changed, and that therefore any assumptions about that
/// layout are no longer valid.
///
/// For example, sent by [SizeChangedLayoutNotifier] whenever
/// [SizeChangedLayoutNotifier] changes size.
/// For example, sent by the [SizeChangedLayoutNotifier] widget whenever that
/// widget changes size.
///
/// This notification for triggering repaints, but if you use this notification
/// to trigger rebuilds or relayouts, you'll create a backwards dependency in
/// the frame pipeline because [SizeChangedLayoutNotification]s are generated
/// during layout, which is after the build phase and in the middle of the
/// layout phase. This backwards dependency can lead to visual corruption or
/// lags.
/// This notification can be used for triggering repaints, but if you use this
/// notification to trigger rebuilds or relayouts, you'll create a backwards
/// dependency in the frame pipeline because [SizeChangedLayoutNotification]s
/// are generated during layout, which is after the build phase and in the
/// middle of the layout phase. This backwards dependency can lead to visual
/// corruption or lags.
///
/// See [LayoutChangedNotification] for additional discussion of layout
/// notifications such as this one.
......@@ -26,16 +26,28 @@ import 'package:flutter/widgets.dart';
/// See also:
///
/// * [SizeChangedLayoutNotifier], which sends this notification.
/// * [LayoutChangedNotification], of which this is a subclass.
class SizeChangedLayoutNotification extends LayoutChangedNotification { }
/// A widget that automatically dispatches a [SizeChangedLayoutNotification]
/// when the layout of its child changes.
///
/// Useful especially when having some complex, layout-changing animation within
/// [Material] that is also interactive.
/// when the layout dimensions of its child change.
///
/// The notification is not sent for the initial layout (since the size doesn't
/// change in that case, it's just established).
///
/// To listen for the notification dispatched by this widget, use a
/// [NotificationListener<SizeChangedLayoutNotification>].
///
/// The [Material] class listens for [LayoutChangedNotification]s, including
/// [SizeChangedLayoutNotification]s, to repaint [InkResponse] and [InkWell] ink
/// effects. When a widget is likely to change size, wrapping it in a
/// [SizeChangedLayoutNotifier] will cause the ink effects to correctly repaint
/// when the child changes size.
///
/// See also:
///
/// * [Notification], the base class for notifications that bubble through the
/// widget tree.
class SizeChangedLayoutNotifier extends SingleChildRenderObjectWidget {
/// Creates a [SizeChangedLayoutNotifier] that dispatches layout changed
/// notifications when [child] changes layout size.
......@@ -73,6 +85,8 @@ class _RenderSizeChangedWithCallback extends RenderProxyBox {
@override
void performLayout() {
super.performLayout();
// Don't send the initial notification, or this will be SizeObserver all
// over again!
if (_oldSize != null && size != _oldSize)
onLayoutChangedCallback();
_oldSize = size;
......
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