From 1f4f75bb503a8fd844fea382fb4b7c5ad0ce99dd Mon Sep 17 00:00:00 2001 From: Ian Hickson Date: Tue, 13 Jun 2017 09:52:13 -0700 Subject: [PATCH] More documentation. (#10653) --- dev/bots/analyze-sample-code.dart | 4 +- .../flutter/lib/src/animation/animations.dart | 9 +- .../flutter/lib/src/material/dropdown.dart | 6 + .../lib/src/painting/fractional_offset.dart | 6 + .../flutter/lib/src/painting/text_span.dart | 4 +- .../flutter/lib/src/painting/text_style.dart | 145 +++++++++++++++++- packages/flutter/lib/src/rendering/box.dart | 82 ++++++++-- .../flutter/lib/src/rendering/proxy_box.dart | 10 +- .../lib/src/widgets/animated_cross_fade.dart | 18 ++- packages/flutter/lib/src/widgets/basic.dart | 27 +++- .../flutter/lib/src/widgets/container.dart | 44 ++++++ .../lib/src/widgets/gesture_detector.dart | 17 ++ .../widgets/size_changed_layout_notifier.dart | 38 +++-- 13 files changed, 358 insertions(+), 52 deletions(-) diff --git a/dev/bots/analyze-sample-code.dart b/dev/bots/analyze-sample-code.dart index 7c63073d4eb..7aff93c54a7 100644 --- a/dev/bots/analyze-sample-code.dart +++ b/dev/bots/analyze-sample-code.dart @@ -90,7 +90,7 @@ Future 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 errors = await process.stdout.transform(UTF8.decoder).transform(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 ')) diff --git a/packages/flutter/lib/src/animation/animations.dart b/packages/flutter/lib/src/animation/animations.dart index b763b792cdc..82e104a977e 100644 --- a/packages/flutter/lib/src/animation/animations.dart +++ b/packages/flutter/lib/src/animation/animations.dart @@ -237,10 +237,11 @@ class ProxyAnimation extends Animation /// 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 with AnimationLazyListenerMixin, AnimationLocalStatusListenersMixin { diff --git a/packages/flutter/lib/src/material/dropdown.dart b/packages/flutter/lib/src/material/dropdown.dart index b0ff98253e9..a4a22b54553 100644 --- a/packages/flutter/lib/src/material/dropdown.dart +++ b/packages/flutter/lib/src/material/dropdown.dart @@ -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. diff --git a/packages/flutter/lib/src/painting/fractional_offset.dart b/packages/flutter/lib/src/painting/fractional_offset.dart index e0b0c725e23..90b4549986a 100644 --- a/packages/flutter/lib/src/painting/fractional_offset.dart +++ b/packages/flutter/lib/src/painting/fractional_offset.dart @@ -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. diff --git a/packages/flutter/lib/src/painting/text_span.dart b/packages/flutter/lib/src/painting/text_span.dart index 0a8258fe907..a7f068d7d80 100644 --- a/packages/flutter/lib/src/painting/text_span.dart +++ b/packages/flutter/lib/src/painting/text_span.dart @@ -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 diff --git a/packages/flutter/lib/src/painting/text_style.dart b/packages/flutter/lib/src/painting/text_style.dart index d56f82b3cfe..c7595b8fc15 100644 --- a/packages/flutter/lib/src/painting/text_style.dart +++ b/packages/flutter/lib/src/painting/text_style.dart @@ -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: [ +/// 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: [ +/// 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, ); } diff --git a/packages/flutter/lib/src/rendering/box.dart b/packages/flutter/lib/src/rendering/box.dart index f4b869ca8f7..82afc4d3b14 100644 --- a/packages/flutter/lib/src/rendering/box.dart +++ b/packages/flutter/lib/src/rendering/box.dart @@ -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 diff --git a/packages/flutter/lib/src/rendering/proxy_box.dart b/packages/flutter/lib/src/rendering/proxy_box.dart index 08f0db94775..06872dc648a 100644 --- a/packages/flutter/lib/src/rendering/proxy_box.dart +++ b/packages/flutter/lib/src/rendering/proxy_box.dart @@ -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({ diff --git a/packages/flutter/lib/src/widgets/animated_cross_fade.dart b/packages/flutter/lib/src/widgets/animated_cross_fade.dart index 21a77994106..b64447099f1 100644 --- a/packages/flutter/lib/src/widgets/animated_cross_fade.dart +++ b/packages/flutter/lib/src/widgets/animated_cross_fade.dart @@ -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( diff --git a/packages/flutter/lib/src/widgets/basic.dart b/packages/flutter/lib/src/widgets/basic.dart index e141999d5bd..f492c84a139 100644 --- a/packages/flutter/lib/src/widgets/basic.dart +++ b/packages/flutter/lib/src/widgets/basic.dart @@ -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 { /// ## 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 { diff --git a/packages/flutter/lib/src/widgets/container.dart b/packages/flutter/lib/src/widgets/container.dart index 98c0eec85fd..89bf1409b42 100644 --- a/packages/flutter/lib/src/widgets/container.dart +++ b/packages/flutter/lib/src/widgets/container.dart @@ -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 diff --git a/packages/flutter/lib/src/widgets/gesture_detector.dart b/packages/flutter/lib/src/widgets/gesture_detector.dart index b6d9ed9f40f..5c681f35a20 100644 --- a/packages/flutter/lib/src/widgets/gesture_detector.dart +++ b/packages/flutter/lib/src/widgets/gesture_detector.dart @@ -104,6 +104,23 @@ class GestureRecognizerFactoryWithHandlers 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. /// diff --git a/packages/flutter/lib/src/widgets/size_changed_layout_notifier.dart b/packages/flutter/lib/src/widgets/size_changed_layout_notifier.dart index bc26360d860..32c3bbd75de 100644 --- a/packages/flutter/lib/src/widgets/size_changed_layout_notifier.dart +++ b/packages/flutter/lib/src/widgets/size_changed_layout_notifier.dart @@ -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]. +/// +/// 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;