Commit 6f824bce authored by Ian Hickson's avatar Ian Hickson Committed by GitHub

More documentation (#10519)

parent 18d1be4a
...@@ -448,6 +448,25 @@ class ElasticInOutCurve extends Curve { ...@@ -448,6 +448,25 @@ class ElasticInOutCurve extends Curve {
// PREDEFINED CURVES // PREDEFINED CURVES
/// A collection of common animation curves. /// A collection of common animation curves.
///
/// ![](https://flutter.github.io/assets-for-api-docs/animation/curve_bounce_in.png)
/// ![](https://flutter.github.io/assets-for-api-docs/animation/curve_bounce_in_out.png)
/// ![](https://flutter.github.io/assets-for-api-docs/animation/curve_bounce_out.png)
/// ![](https://flutter.github.io/assets-for-api-docs/animation/curve_decelerate.png)
/// ![](https://flutter.github.io/assets-for-api-docs/animation/curve_ease.png)
/// ![](https://flutter.github.io/assets-for-api-docs/animation/curve_ease_in.png)
/// ![](https://flutter.github.io/assets-for-api-docs/animation/curve_ease_in_out.png)
/// ![](https://flutter.github.io/assets-for-api-docs/animation/curve_ease_out.png)
/// ![](https://flutter.github.io/assets-for-api-docs/animation/curve_elastic_in.png)
/// ![](https://flutter.github.io/assets-for-api-docs/animation/curve_elastic_in_out.png)
/// ![](https://flutter.github.io/assets-for-api-docs/animation/curve_elastic_out.png)
/// ![](https://flutter.github.io/assets-for-api-docs/animation/curve_fast_out_slow_in.png)
/// ![](https://flutter.github.io/assets-for-api-docs/animation/curve_linear.png)
///
/// See also:
///
/// * [Curve], the interface implemented by the constants available from the
/// [Curves] class.
class Curves { class Curves {
Curves._(); Curves._();
......
...@@ -15,7 +15,7 @@ const double _kTabBarHeight = 50.0; ...@@ -15,7 +15,7 @@ const double _kTabBarHeight = 50.0;
const Color _kDefaultTabBarBackgroundColor = const Color(0xCCF8F8F8); const Color _kDefaultTabBarBackgroundColor = const Color(0xCCF8F8F8);
const Color _kDefaultTabBarBorderColor = const Color(0x4C000000); const Color _kDefaultTabBarBorderColor = const Color(0x4C000000);
/// An iOS styled bottom navigation tab bar. /// An iOS-styled bottom navigation tab bar.
/// ///
/// Displays multiple tabs using [BottomNavigationBarItem] with one tab being /// Displays multiple tabs using [BottomNavigationBarItem] with one tab being
/// active, the first tab by default. /// active, the first tab by default.
...@@ -29,9 +29,10 @@ const Color _kDefaultTabBarBorderColor = const Color(0x4C000000); ...@@ -29,9 +29,10 @@ const Color _kDefaultTabBarBorderColor = const Color(0x4C000000);
/// ///
/// If the given [backgroundColor]'s opacity is not 1.0 (which is the case by /// If the given [backgroundColor]'s opacity is not 1.0 (which is the case by
/// default), it will produce a blurring effect to the content behind it. /// default), it will produce a blurring effect to the content behind it.
/// //
// TODO(xster): document using with a CupertinoScaffold. // TODO(xster): document using with a CupertinoScaffold.
class CupertinoTabBar extends StatelessWidget { class CupertinoTabBar extends StatelessWidget {
/// Creates a tab bar in the iOS style.
CupertinoTabBar({ CupertinoTabBar({
Key key, Key key,
@required this.items, @required this.items,
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
import 'dart:ui' show Color; import 'dart:ui' show Color;
/// [Color] constants that describe colors commonly used in iOS applications.
class CupertinoColors { class CupertinoColors {
CupertinoColors._(); CupertinoColors._();
......
...@@ -15,7 +15,7 @@ const double _kNavBarHeight = 44.0; ...@@ -15,7 +15,7 @@ const double _kNavBarHeight = 44.0;
const Color _kDefaultNavBarBackgroundColor = const Color(0xCCF8F8F8); const Color _kDefaultNavBarBackgroundColor = const Color(0xCCF8F8F8);
const Color _kDefaultNavBarBorderColor = const Color(0x4C000000); const Color _kDefaultNavBarBorderColor = const Color(0x4C000000);
/// An iOS styled navigation bar. /// An iOS-styled navigation bar.
/// ///
/// The navigation bar is a toolbar that minimally consists of a widget, normally /// The navigation bar is a toolbar that minimally consists of a widget, normally
/// a page title, in the [middle] of the toolbar. /// a page title, in the [middle] of the toolbar.
...@@ -28,11 +28,12 @@ const Color _kDefaultNavBarBorderColor = const Color(0x4C000000); ...@@ -28,11 +28,12 @@ const Color _kDefaultNavBarBorderColor = const Color(0x4C000000);
/// ///
/// If the given [backgroundColor]'s opacity is not 1.0 (which is the case by /// If the given [backgroundColor]'s opacity is not 1.0 (which is the case by
/// default), it will produce a blurring effect to the content behind it. /// default), it will produce a blurring effect to the content behind it.
/// //
// TODO(xster): document automatic addition of a CupertinoBackButton. // TODO(xster): document automatic addition of a CupertinoBackButton.
// TODO(xster): add sample code using icons. // TODO(xster): add sample code using icons.
// TODO(xster): document integration into a CupertinoScaffold. // TODO(xster): document integration into a CupertinoScaffold.
class CupertinoNavigationBar extends StatelessWidget implements PreferredSizeWidget { class CupertinoNavigationBar extends StatelessWidget implements PreferredSizeWidget {
/// Creates a navigation bar in the iOS style.
const CupertinoNavigationBar({ const CupertinoNavigationBar({
Key key, Key key,
this.leading, this.leading,
......
...@@ -10,6 +10,8 @@ import 'theme.dart'; ...@@ -10,6 +10,8 @@ import 'theme.dart';
/// A "back" icon that's appropriate for the current [TargetPlatform]. /// A "back" icon that's appropriate for the current [TargetPlatform].
/// ///
/// The current platform is determined by querying for the ambient [Theme].
///
/// See also: /// See also:
/// ///
/// * [BackButton], an [IconButton] with a [BackButtonIcon] that calls /// * [BackButton], an [IconButton] with a [BackButtonIcon] that calls
...@@ -17,7 +19,10 @@ import 'theme.dart'; ...@@ -17,7 +19,10 @@ import 'theme.dart';
/// * [IconButton], which is a more general widget for creating buttons /// * [IconButton], which is a more general widget for creating buttons
/// with icons. /// with icons.
/// * [Icon], a material design icon. /// * [Icon], a material design icon.
/// * [ThemeData.platform], which specifies the current platform.
class BackButtonIcon extends StatelessWidget { class BackButtonIcon extends StatelessWidget {
/// Creates an icon that shows the appropriate "back" image for
/// the current platform (as obtained from the [Theme]).
const BackButtonIcon({ Key key }) : super(key: key); const BackButtonIcon({ Key key }) : super(key: key);
/// Returns tha appropriate "back" icon for the given `platform`. /// Returns tha appropriate "back" icon for the given `platform`.
......
...@@ -31,6 +31,9 @@ import 'theme.dart'; ...@@ -31,6 +31,9 @@ import 'theme.dart';
/// [secondary] widget is placed on the opposite side. This maps to the /// [secondary] widget is placed on the opposite side. This maps to the
/// [ListTile.leading] and [ListTile.trailing] properties of [ListTile]. /// [ListTile.leading] and [ListTile.trailing] properties of [ListTile].
/// ///
/// To show the [CheckboxListTile] as disabled, pass null as the [onChanged]
/// callback.
///
/// ## Sample code /// ## Sample code
/// ///
/// This widget shows a checkbox that, when checked, slows down all animations /// This widget shows a checkbox that, when checked, slows down all animations
......
...@@ -34,6 +34,9 @@ import 'theme.dart'; ...@@ -34,6 +34,9 @@ import 'theme.dart';
/// [secondary] widget is placed on the opposite side. This maps to the /// [secondary] widget is placed on the opposite side. This maps to the
/// [ListTile.leading] and [ListTile.trailing] properties of [ListTile]. /// [ListTile.leading] and [ListTile.trailing] properties of [ListTile].
/// ///
/// To show the [RadioListTile] as disabled, pass null as the [onChanged]
/// callback.
///
/// ## Sample code /// ## Sample code
/// ///
/// This widget shows a pair of radio buttons that control the `_character` /// This widget shows a pair of radio buttons that control the `_character`
......
...@@ -32,6 +32,9 @@ import 'theme.dart'; ...@@ -32,6 +32,9 @@ import 'theme.dart';
/// [ListTile.leading] slot. This cannot be changed; there is not sufficient /// [ListTile.leading] slot. This cannot be changed; there is not sufficient
/// space in a [ListTile]'s [ListTile.leading] slot for a [Switch]. /// space in a [ListTile]'s [ListTile.leading] slot for a [Switch].
/// ///
/// To show the [SwitchListTile] as disabled, pass null as the [onChanged]
/// callback.
///
/// ## Sample code /// ## Sample code
/// ///
/// This widget shows a switch that, when toggled, changes the state of a [bool] /// This widget shows a switch that, when toggled, changes the state of a [bool]
......
...@@ -1411,7 +1411,7 @@ class DecorationImage { ...@@ -1411,7 +1411,7 @@ class DecorationImage {
/// ///
/// The [BoxDecoration] class provides a variety of ways to draw a box. /// The [BoxDecoration] class provides a variety of ways to draw a box.
/// ///
/// The box has a [border], a body, and may cast a [shadow]. /// The box has a [border], a body, and may cast a [boxShadow].
/// ///
/// The [shape] of the box can be a circle or a rectangle. If it is a rectangle, /// The [shape] of the box can be a circle or a rectangle. If it is a rectangle,
/// then the [borderRadius] property controls the roundness of the corners. /// then the [borderRadius] property controls the roundness of the corners.
...@@ -1421,7 +1421,7 @@ class DecorationImage { ...@@ -1421,7 +1421,7 @@ class DecorationImage {
/// the box. Finally there is the [image], the precise alignment of which is /// the box. Finally there is the [image], the precise alignment of which is
/// controlled by the [DecorationImage] class. /// controlled by the [DecorationImage] class.
/// ///
/// The [border] paints over the body; the [shadow], naturally, paints below it. /// The [border] paints over the body; the [boxShadow], naturally, paints below it.
/// ///
/// ## Sample code /// ## Sample code
/// ///
......
...@@ -58,7 +58,32 @@ class TextSelectionPoint { ...@@ -58,7 +58,32 @@ class TextSelectionPoint {
} }
} }
/// Displays some text in a scrollable container with a potentially blinking
/// cursor and with gesture recognizers.
///
/// This is the renderer for an editable text field. It does not directly
/// provide affordances for editing the text, but it does handle text selection
/// and manipulation of the text cursor.
///
/// The [text] is displayed, scrolled by the given [offset], aligned according
/// to [textAlign]. The [maxLines] property controls whether the text displays
/// on one line or many. The [selection], if it is not collapsed, is painted in
/// the [selectionColor]. If it _is_ collapsed, then it represents the cursor
/// position. The cursor is shown while [showCursor] is true. It is painted in
/// the [cursorColor].
///
/// If, when the render object paints, the caret is found to have changed
/// location, [onCaretChanged] is called.
///
/// The user may interact with the render object by tapping or long-pressing.
/// When the user does so, the selection is updated, and [onSelectionChanged] is
/// called.
///
/// Keyboard handling, IME handling, scrolling, toggling the [showCursor] value
/// to actually blink the cursor, and other features not mentioned above are the
/// responsibility of higher layers and not handled by this object.
class RenderEditable extends RenderBox { class RenderEditable extends RenderBox {
/// Creates a render object that implements the visual aspects of a text field.
RenderEditable({ RenderEditable({
TextSpan text, TextSpan text,
TextAlign textAlign, TextAlign textAlign,
......
...@@ -1233,8 +1233,8 @@ class PipelineOwner { ...@@ -1233,8 +1233,8 @@ class PipelineOwner {
/// Update the semantics for render objects marked as needing a semantics /// Update the semantics for render objects marked as needing a semantics
/// update. /// update.
/// ///
/// Initially, only the root node, as scheduled by [scheduleInitialSemantics], /// Initially, only the root node, as scheduled by
/// needs a semantics update. /// [RenderObjectscheduleInitialSemantics], needs a semantics update.
/// ///
/// This function is one of the core stages of the rendering pipeline. The /// This function is one of the core stages of the rendering pipeline. The
/// semantics are compiled after painting and only after /// semantics are compiled after painting and only after
......
...@@ -1509,7 +1509,7 @@ class RenderTransform extends RenderProxyBox { ...@@ -1509,7 +1509,7 @@ class RenderTransform extends RenderProxyBox {
/// child as it is painted. When set to false, hit tests are performed /// child as it is painted. When set to false, hit tests are performed
/// ignoring the transformation. /// ignoring the transformation.
/// ///
/// applyPaintTransform(), and therefore localToGlobal() and globalToLocal(), /// [applyPaintTransform], and therefore [localToGlobal] and [globalToLocal],
/// always honor the transformation, regardless of the value of this property. /// always honor the transformation, regardless of the value of this property.
bool transformHitTests; bool transformHitTests;
...@@ -2890,12 +2890,14 @@ class RenderSemanticsAnnotations extends RenderProxyBox { ...@@ -2890,12 +2890,14 @@ class RenderSemanticsAnnotations extends RenderProxyBox {
} }
} }
/// Causes the semantics of all siblings and cousins painted before it in the /// Causes the semantics of all earlier render objects below the same semantic
/// same semantic container to be dropped. /// boundary to be dropped.
/// ///
/// This is useful in a stack where an overlay should prevent interactions /// This is useful in a stack where an opaque mask should prevent interactions
/// with the underlying layers. /// with the render objects painted below the mask.
class RenderBlockSemantics extends RenderProxyBox { class RenderBlockSemantics extends RenderProxyBox {
/// Create a render object that blocks semantics for nodes below it in paint
/// order.
RenderBlockSemantics({ RenderBox child }) : super(child); RenderBlockSemantics({ RenderBox child }) : super(child);
@override @override
......
...@@ -35,6 +35,7 @@ abstract class RenderSliverPersistentHeader extends RenderSliver with RenderObje ...@@ -35,6 +35,7 @@ abstract class RenderSliverPersistentHeader extends RenderSliver with RenderObje
/// child changes its intrinsic dimensions. /// child changes its intrinsic dimensions.
double get minExtent; double get minExtent;
/// The dimension of the child in the main axis.
@protected @protected
double get childExtent { double get childExtent {
if (child == null) if (child == null)
......
...@@ -19,6 +19,13 @@ import 'image_stream.dart'; ...@@ -19,6 +19,13 @@ import 'image_stream.dart';
/// Configuration information passed to the [ImageProvider.resolve] method to /// Configuration information passed to the [ImageProvider.resolve] method to
/// select a specific image. /// select a specific image.
///
/// See also:
///
/// * [createLocalImageConfiguration], which creates an [ImageConfiguration]
/// based on ambient configuration in a [Widget] environment.
/// * [ImageProvider], which uses [ImageConfiguration] objects to determine
/// which image to obtain.
@immutable @immutable
class ImageConfiguration { class ImageConfiguration {
/// Creates an object holding the configuration information for an [ImageProvider]. /// Creates an object holding the configuration information for an [ImageProvider].
...@@ -149,6 +156,80 @@ class ImageConfiguration { ...@@ -149,6 +156,80 @@ class ImageConfiguration {
/// ///
/// The type argument does not have to be specified when using the type as an /// The type argument does not have to be specified when using the type as an
/// argument (where any image provider is acceptable). /// argument (where any image provider is acceptable).
///
/// ## Sample code
///
/// The following shows the code required to write a widget that fully conforms
/// to the [ImageProvider] and [Widget] protocols.
///
/// ```dart
/// class Picture extends StatefulWidget {
/// const Picture({
/// Key key,
/// @required this.imageProvider,
/// }) : assert(imageProvider != null),
/// super(key: key);
///
/// final ImageProvider imageProvider;
///
/// @override
/// _PictureState createState() => new _PictureState();
/// }
///
/// class _PictureState extends State<Picture> {
/// ImageStream _imageStream;
/// ImageInfo _imageInfo;
///
/// @override
/// void didChangeDependencies() {
/// super.didChangeDependencies();
/// // We call _getImage here because createLocalImageConfiguration() needs to
/// // be called again if the dependencies changed, in case the changes relate
/// // to the DefaultAssetBundle, MediaQuery, etc, which that method uses.
/// _getImage();
/// }
///
/// @override
/// void didUpdateWidget(Picture oldWidget) {
/// super.didUpdateWidget(oldWidget);
/// if (widget.imageProvider != oldWidget.imageProvider)
/// _getImage();
/// }
///
/// void _getImage() {
/// final ImageStream oldImageStream = _imageStream;
/// _imageStream = widget.imageProvider.resolve(createLocalImageConfiguration(context));
/// if (_imageStream.key != oldImageStream?.key) {
/// // If the keys are the same, then we got the same image back, and so we don't
/// // need to update the listeners. If the key changed, though, we must make sure
/// // to switch our listeners to the new image stream.
/// oldImageStream?.removeListener(_updateImage);
/// _imageStream.addListener(_updateImage);
/// }
/// }
///
/// void _updateImage(ImageInfo imageInfo, bool synchronousCall) {
/// setState(() {
/// // Trigger a build whenever the image changes.
/// _imageInfo = imageInfo;
/// });
/// }
///
/// @override
/// void dispose() {
/// _imageStream.removeListener(_updateImage);
/// super.dispose();
/// }
///
/// @override
/// Widget build(BuildContext context) {
/// return new RawImage(
/// image: _imageInfo?.image, // this is a dart:ui Image object
/// scale: _imageInfo?.scale ?? 1.0,
/// );
/// }
/// }
/// ```
@optionalTypeArgs @optionalTypeArgs
abstract class ImageProvider<T> { abstract class ImageProvider<T> {
/// Abstract const constructor. This constructor enables subclasses to provide /// Abstract const constructor. This constructor enables subclasses to provide
......
...@@ -44,10 +44,14 @@ class ImageInfo { ...@@ -44,10 +44,14 @@ class ImageInfo {
/// Signature for callbacks reporting that an image is available. /// Signature for callbacks reporting that an image is available.
/// ///
/// synchronousCall is true if the listener is being invoked during the call
/// to addListener.
///
/// Used by [ImageStream]. /// Used by [ImageStream].
///
/// The `synchronousCall` argument is true if the listener is being invoked
/// during the call to addListener. This can be useful if, for example,
/// [ImageStream.addListener] is invoked during a frame, so that a new rendering
/// frame is requested if the call was asynchronous (after the current frame)
/// and no rendering frame is requested if the call was synchronous (within the
/// same stack frame as the call to [ImageStream.addListener]).
typedef void ImageListener(ImageInfo image, bool synchronousCall); typedef void ImageListener(ImageInfo image, bool synchronousCall);
/// A handle to an image resource. /// A handle to an image resource.
...@@ -61,6 +65,11 @@ typedef void ImageListener(ImageInfo image, bool synchronousCall); ...@@ -61,6 +65,11 @@ typedef void ImageListener(ImageInfo image, bool synchronousCall);
/// loading. /// loading.
/// ///
/// ImageStream objects are backed by [ImageStreamCompleter] objects. /// ImageStream objects are backed by [ImageStreamCompleter] objects.
///
/// See also:
///
/// * [ImageProvider], which has an example that includes the use of an
/// [ImageStream] in a [Widget].
class ImageStream { class ImageStream {
/// Create an initially unbound image stream. /// Create an initially unbound image stream.
/// ///
......
...@@ -38,6 +38,26 @@ enum CrossFadeState { ...@@ -38,6 +38,26 @@ enum CrossFadeState {
/// width. In the case where the two children have different heights, the /// width. In the case where the two children have different heights, the
/// animation crops overflowing children during the animation by aligning their /// animation crops overflowing children during the animation by aligning their
/// top edge, which means that the bottom will be clipped. /// top edge, which means that the bottom will be clipped.
///
/// ## 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.
///
/// ```dart
/// new AnimatedCrossFade(
/// duration: const Duration(seconds: 3),
/// firstChild: const FlutterLogo(style: FlutterLogoStyle.horizontal, size: 100.0),
/// secondChild: const FlutterLogo(style: FlutterLogoStyle.stacked, size: 100.0),
/// crossFadeState: _on ? CrossFadeState.showFirst : CrossFadeState.showSecond,
/// )
/// ```
///
/// See also:
///
/// * [AnimatedSize], the lower-level widget which [AnimatedCrossFade] uses to
/// automatically change size.
class AnimatedCrossFade extends StatefulWidget { class AnimatedCrossFade extends StatefulWidget {
/// Creates a cross-fade animation widget. /// Creates a cross-fade animation widget.
/// ///
...@@ -99,6 +119,14 @@ class AnimatedCrossFade extends StatefulWidget { ...@@ -99,6 +119,14 @@ class AnimatedCrossFade extends StatefulWidget {
@override @override
_AnimatedCrossFadeState createState() => new _AnimatedCrossFadeState(); _AnimatedCrossFadeState createState() => new _AnimatedCrossFadeState();
@override
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
description.add('$crossFadeState');
if (alignment != FractionalOffset.topCenter)
description.add('alignment: $alignment');
}
} }
class _AnimatedCrossFadeState extends State<AnimatedCrossFade> with TickerProviderStateMixin { class _AnimatedCrossFadeState extends State<AnimatedCrossFade> with TickerProviderStateMixin {
...@@ -212,4 +240,13 @@ class _AnimatedCrossFadeState extends State<AnimatedCrossFade> with TickerProvid ...@@ -212,4 +240,13 @@ class _AnimatedCrossFadeState extends State<AnimatedCrossFade> with TickerProvid
), ),
); );
} }
@override
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
description.add('${widget.crossFadeState}');
description.add('$_controller');
if (widget.alignment != FractionalOffset.topCenter)
description.add('alignment: ${widget.alignment}');
}
} }
...@@ -80,6 +80,8 @@ export 'package:flutter/rendering.dart' show ...@@ -80,6 +80,8 @@ export 'package:flutter/rendering.dart' show
/// See also: /// See also:
/// ///
/// * [ShaderMask], which can apply more elaborate effects to its child. /// * [ShaderMask], which can apply more elaborate effects to its child.
/// * [Transform], which applies an arbitrary transform to its child widget at
/// paint time.
class Opacity extends SingleChildRenderObjectWidget { class Opacity extends SingleChildRenderObjectWidget {
/// Creates a widget that makes its child partially transparent. /// Creates a widget that makes its child partially transparent.
/// ///
...@@ -147,6 +149,7 @@ class Opacity extends SingleChildRenderObjectWidget { ...@@ -147,6 +149,7 @@ class Opacity extends SingleChildRenderObjectWidget {
/// * [Opacity], which can apply a uniform alpha effect to its child. /// * [Opacity], which can apply a uniform alpha effect to its child.
/// * [CustomPaint], which lets you draw directly on the canvas. /// * [CustomPaint], which lets you draw directly on the canvas.
/// * [DecoratedBox], for another approach at decorating child widgets. /// * [DecoratedBox], for another approach at decorating child widgets.
/// * [BackdropFilter], which applies an image filter to the background.
class ShaderMask extends SingleChildRenderObjectWidget { class ShaderMask extends SingleChildRenderObjectWidget {
/// Creates a widget that applies a mask generated by a [Shader] to its child. /// Creates a widget that applies a mask generated by a [Shader] to its child.
/// ///
...@@ -196,6 +199,11 @@ class ShaderMask extends SingleChildRenderObjectWidget { ...@@ -196,6 +199,11 @@ class ShaderMask extends SingleChildRenderObjectWidget {
/// ///
/// This effect is relatively expensive, especially if the filter is non-local, /// This effect is relatively expensive, especially if the filter is non-local,
/// such as a blur. /// such as a blur.
///
/// See also:
///
/// * [DecoratedBox], which draws a background under (or over) a widget.
/// * [Opacity], which changes the opacity of the widget itself.
class BackdropFilter extends SingleChildRenderObjectWidget { class BackdropFilter extends SingleChildRenderObjectWidget {
/// Creates a backdrop filter. /// Creates a backdrop filter.
/// ///
...@@ -547,6 +555,11 @@ class ClipPath extends SingleChildRenderObjectWidget { ...@@ -547,6 +555,11 @@ class ClipPath extends SingleChildRenderObjectWidget {
/// ///
/// Physical layers cast shadows based on an [elevation] which is nominally in /// Physical layers cast shadows based on an [elevation] which is nominally in
/// logical pixels, coming vertically out of the rendering surface. /// logical pixels, coming vertically out of the rendering surface.
///
/// See also:
///
/// * [DecoratedBox], which can apply more arbitrary shadow effects.
/// * [ClipRect], which applies a clip to its child.
class PhysicalModel extends SingleChildRenderObjectWidget { class PhysicalModel extends SingleChildRenderObjectWidget {
/// Creates a physical model with a rounded-rectangular clip. /// Creates a physical model with a rounded-rectangular clip.
/// ///
...@@ -607,6 +620,32 @@ class PhysicalModel extends SingleChildRenderObjectWidget { ...@@ -607,6 +620,32 @@ class PhysicalModel extends SingleChildRenderObjectWidget {
// POSITIONING AND SIZING NODES // POSITIONING AND SIZING NODES
/// A widget that applies a transformation before painting its child. /// A widget that applies a transformation before painting its child.
///
/// ## Sample code
///
/// This example rotates and skews an orange box containing text, keeping the
/// top right corner pinned to its original position.
///
/// ```dart
/// new Container(
/// color: Colors.black,
/// child: new Transform(
/// alignment: FractionalOffset.topRight,
/// transform: new Matrix4.skewY(0.3)..rotateZ(-math.PI / 12.0),
/// child: new Container(
/// padding: const EdgeInsets.all(8.0),
/// color: const Color(0xFFE8581C),
/// child: const Text('Apartment for rent!'),
/// ),
/// ),
/// )
/// ```
///
/// See also:
/// * [RotatedBox], which rotates the child widget during layout, not just
/// during painting.
/// * [FittedBox], which sizes and positions its child widget to fit the parent
/// according to a given [BoxFit] discipline.
class Transform extends SingleChildRenderObjectWidget { class Transform extends SingleChildRenderObjectWidget {
/// Creates a widget that transforms its child. /// Creates a widget that transforms its child.
/// ///
...@@ -617,10 +656,41 @@ class Transform extends SingleChildRenderObjectWidget { ...@@ -617,10 +656,41 @@ class Transform extends SingleChildRenderObjectWidget {
this.origin, this.origin,
this.alignment, this.alignment,
this.transformHitTests: true, this.transformHitTests: true,
Widget child Widget child,
}) : assert(transform != null), }) : assert(transform != null),
super(key: key, child: child); super(key: key, child: child);
/// Creates a widget that transforms its child using a rotation around the
/// center.
///
/// The `angle` argument must not be null. It gives the rotation in clockwise
/// radians.
///
/// ## Sample code
///
/// This example rotates an orange box containing text around its center by
/// fifteen degrees.
///
/// ```dart
/// new Transform.rotate(
/// angle: -math.PI / 12.0,
/// child: new Container(
/// padding: const EdgeInsets.all(8.0),
/// color: const Color(0xFFE8581C),
/// child: const Text('Apartment for rent!'),
/// ),
/// )
/// ```
Transform.rotate({
Key key,
@required double angle,
this.origin,
this.alignment: FractionalOffset.center,
this.transformHitTests: true,
Widget child,
}) : transform = new Matrix4.rotationZ(angle),
super(key: key, child: child);
/// The matrix to transform the child by during painting. /// The matrix to transform the child by during painting.
final Matrix4 transform; final Matrix4 transform;
...@@ -659,6 +729,11 @@ class Transform extends SingleChildRenderObjectWidget { ...@@ -659,6 +729,11 @@ class Transform extends SingleChildRenderObjectWidget {
} }
/// Scales and positions its child within itself according to [fit]. /// Scales and positions its child within itself according to [fit].
///
/// See also:
///
/// * [Transform], which applies an arbitrary transform to its child widget at
/// paint time.
class FittedBox extends SingleChildRenderObjectWidget { class FittedBox extends SingleChildRenderObjectWidget {
/// Creates a widget that scales and positions its child within itself according to [fit]. /// Creates a widget that scales and positions its child within itself according to [fit].
/// ///
......
...@@ -27,6 +27,50 @@ export 'dart:ui' show AppLifecycleState, Locale; ...@@ -27,6 +27,50 @@ export 'dart:ui' show AppLifecycleState, Locale;
/// handlers, or can used with the `implements` keyword, in which case all the /// handlers, or can used with the `implements` keyword, in which case all the
/// handlers must be implemented (and the analyzer will list those that have /// handlers must be implemented (and the analyzer will list those that have
/// been omitted). /// been omitted).
///
/// ## Sample code
///
/// This [StatefulWidget] implements the parts of the [State] and
/// [WidgetsBindingObserver] protocols necessary to react to application
/// lifecycle messages. See [didChangeAppLifecycleState].
///
/// ```dart
/// class Reactor extends StatefulWidget {
/// const Reactor({ Key key }) : super(key: key);
///
/// @override
/// _ReactorState createState() => new _ReactorState();
/// }
///
/// class _ReactorState extends State<Reactor> with WidgetsBindingObserver {
/// @override
/// void initState() {
/// super.initState();
/// WidgetsBinding.instance.addObserver(this);
/// }
///
/// @override
/// void dispose() {
/// WidgetsBinding.instance.removeObserver(this);
/// super.dispose();
/// }
///
/// AppLifecycleState _notification;
///
/// @override
/// void didChangeAppLifecycleState(AppLifecycleState state) {
/// setState(() { _notification = state; });
/// }
///
/// @override
/// Widget build(BuildContext context) {
/// return new Text('Last notification: $_notification');
/// }
/// }
/// ```
///
/// To respond to other notifications, replace the [didChangeAppLifecycleState]
/// method above with other methods from this class.
abstract class WidgetsBindingObserver { abstract class WidgetsBindingObserver {
/// Called when the system tells the app to pop the current route. /// Called when the system tells the app to pop the current route.
/// For example, on Android, this is called when the user presses /// For example, on Android, this is called when the user presses
...@@ -52,6 +96,56 @@ abstract class WidgetsBindingObserver { ...@@ -52,6 +96,56 @@ abstract class WidgetsBindingObserver {
/// Called when the application's dimensions change. For example, /// Called when the application's dimensions change. For example,
/// when a phone is rotated. /// when a phone is rotated.
///
/// ## Sample code
///
/// This [StatefulWidget] implements the parts of the [State] and
/// [WidgetsBindingObserver] protocols necessary to react when the device is
/// rotated (or otherwise changes dimensions).
///
/// ```dart
/// class Reactor extends StatefulWidget {
/// const Reactor({ Key key }) : super(key: key);
///
/// @override
/// _ReactorState createState() => new _ReactorState();
/// }
///
/// class _ReactorState extends State<Reactor> with WidgetsBindingObserver {
/// @override
/// void initState() {
/// super.initState();
/// WidgetsBinding.instance.addObserver(this);
/// }
///
/// @override
/// void dispose() {
/// WidgetsBinding.instance.removeObserver(this);
/// super.dispose();
/// }
///
/// Size _lastSize;
///
/// @override
/// void didChangeMetrics() {
/// setState(() { _lastSize = ui.window.physicalSize; });
/// }
///
/// @override
/// Widget build(BuildContext context) {
/// return new Text('Last size: $_lastSize');
/// }
/// }
/// ```
///
/// In general, this is unnecessary as the layout system takes care of
/// automatically recomputing the application geometry when the application
/// size changes.
///
/// See also:
///
/// * [MediaQuery.of], which provides a similar service with less
/// boilerplate.
void didChangeMetrics() { } void didChangeMetrics() { }
/// Called when the system tells the app that the user's locale has /// Called when the system tells the app that the user's locale has
...@@ -61,6 +155,9 @@ abstract class WidgetsBindingObserver { ...@@ -61,6 +155,9 @@ abstract class WidgetsBindingObserver {
/// Called when the system puts the app in the background or returns /// Called when the system puts the app in the background or returns
/// the app to the foreground. /// the app to the foreground.
///
/// An example of implementing this method is provided in the class-level
/// documentation for the [WidgetsBindingObserver] class.
void didChangeAppLifecycleState(AppLifecycleState state) { } void didChangeAppLifecycleState(AppLifecycleState state) { }
/// Called when the system is running low on memory. /// Called when the system is running low on memory.
...@@ -159,11 +256,21 @@ abstract class WidgetsBinding extends BindingBase with GestureBinding, RendererB ...@@ -159,11 +256,21 @@ abstract class WidgetsBinding extends BindingBase with GestureBinding, RendererB
/// [MediaQuery.of] static method and (implicitly) the /// [MediaQuery.of] static method and (implicitly) the
/// [InheritedWidget] mechanism to be notified whenever the screen /// [InheritedWidget] mechanism to be notified whenever the screen
/// size changes (e.g. whenever the screen rotates). /// size changes (e.g. whenever the screen rotates).
///
/// See also:
///
/// * [removeObserver], to release the resources reserved by this method.
/// * [WidgetsBindingObserver], which has an example of using this method.
void addObserver(WidgetsBindingObserver observer) => _observers.add(observer); void addObserver(WidgetsBindingObserver observer) => _observers.add(observer);
/// Unregisters the given observer. This should be used sparingly as /// Unregisters the given observer. This should be used sparingly as
/// it is relatively expensive (O(N) in the number of registered /// it is relatively expensive (O(N) in the number of registered
/// observers). /// observers).
///
/// See also:
///
/// * [addObserver], for the method that adds observers in the first place.
/// * [WidgetsBindingObserver], which has an example of using this method.
bool removeObserver(WidgetsBindingObserver observer) => _observers.remove(observer); bool removeObserver(WidgetsBindingObserver observer) => _observers.remove(observer);
/// Called when the system metrics change. /// Called when the system metrics change.
......
...@@ -146,7 +146,7 @@ class DecoratedBox extends SingleChildRenderObjectWidget { ...@@ -146,7 +146,7 @@ class DecoratedBox extends SingleChildRenderObjectWidget {
/// The [constraints] are set to fit the font size plus ample headroom /// The [constraints] are set to fit the font size plus ample headroom
/// vertically, while expanding horizontally to fit the parent. The [padding] is /// vertically, while expanding horizontally to fit the parent. The [padding] is
/// used to make sure there is space between the contents and the text. The /// used to make sure there is space between the contents and the text. The
/// [color] makes the box teal. The [alignment] causes the [child] to be /// `color` makes the box teal. The [alignment] causes the [child] to be
/// centered in the box. The [foregroundDecoration] overlays a nine-patch image /// centered in the box. The [foregroundDecoration] overlays a nine-patch image
/// onto the text. Finally, the [transform] applies a slight rotation to the /// onto the text. Finally, the [transform] applies a slight rotation to the
/// entire contraption to complete the effect. /// entire contraption to complete the effect.
......
...@@ -1452,7 +1452,7 @@ abstract class ParentDataWidget<T extends RenderObjectWidget> extends ProxyWidge ...@@ -1452,7 +1452,7 @@ abstract class ParentDataWidget<T extends RenderObjectWidget> extends ProxyWidge
/// ///
/// Sometimes, the `of` method returns the data rather than the inherited /// Sometimes, the `of` method returns the data rather than the inherited
/// widget; for example, in this case it could have returned a [Color] instead /// widget; for example, in this case it could have returned a [Color] instead
/// of the [FrogColor] widget. /// of the `FrogColor` widget.
/// ///
/// Occasionally, the inherited widget is an implementation detail of another /// Occasionally, the inherited widget is an implementation detail of another
/// class, and is therefore private. The `of` method in that case is typically /// class, and is therefore private. The `of` method in that case is typically
......
...@@ -25,6 +25,15 @@ export 'package:flutter/services.dart' show ...@@ -25,6 +25,15 @@ export 'package:flutter/services.dart' show
/// ///
/// This is the object that must be passed to [BoxPainter.paint] and to /// This is the object that must be passed to [BoxPainter.paint] and to
/// [ImageProvider.resolve]. /// [ImageProvider.resolve].
///
/// If this is not called from a build method, then it should be reinvoked
/// whenever the dependencies change, e.g. by calling it from
/// [State.didChangeDependencies], so that any changes in the environement are
/// picked up (e.g. if the device pixel ratio changes).
///
/// See also:
///
/// * [ImageProvider], which has an example showing how this might be used.
ImageConfiguration createLocalImageConfiguration(BuildContext context, { Size size }) { ImageConfiguration createLocalImageConfiguration(BuildContext context, { Size size }) {
return new ImageConfiguration( return new ImageConfiguration(
bundle: DefaultAssetBundle.of(context), bundle: DefaultAssetBundle.of(context),
......
...@@ -13,7 +13,7 @@ import 'framework.dart'; ...@@ -13,7 +13,7 @@ import 'framework.dart';
/// widgets along a horizontal axis that's sensible for an application's /// widgets along a horizontal axis that's sensible for an application's
/// navigation bar such as in Material Design and in iOS. /// navigation bar such as in Material Design and in iOS.
/// ///
/// [leading] and [trailing] widgets occupy the edges of the widget with /// The [leading] and [trailing] widgets occupy the edges of the widget with
/// reasonable size constraints while the [middle] widget occupies the remaining /// reasonable size constraints while the [middle] widget occupies the remaining
/// space in either a center aligned or start aligned fashion. /// space in either a center aligned or start aligned fashion.
/// ///
...@@ -21,6 +21,8 @@ import 'framework.dart'; ...@@ -21,6 +21,8 @@ import 'framework.dart';
/// the iOS [CupertinoNavigationBar] or wrap this widget with more theming /// the iOS [CupertinoNavigationBar] or wrap this widget with more theming
/// specifications for your own custom app bar. /// specifications for your own custom app bar.
class NavigationToolbar extends StatelessWidget { class NavigationToolbar extends StatelessWidget {
/// Creates a widget that lays out its children in a manner suitable for a
/// toolbar.
const NavigationToolbar({ const NavigationToolbar({
Key key, Key key,
this.leading, this.leading,
......
...@@ -25,6 +25,11 @@ import 'sliver.dart'; ...@@ -25,6 +25,11 @@ import 'sliver.dart';
import 'ticker_provider.dart'; import 'ticker_provider.dart';
/// Signature used by [NestedScrollView] for building its header. /// Signature used by [NestedScrollView] for building its header.
///
/// The `innerBoxIsScrolled` argument is typically used to control the
/// [SliverAppBar.forceElevated] property to ensure that the app bar shows a
/// shadow, since it would otherwise not necessarily be aware that it had
/// content ostensibly below it.
typedef List<Widget> NestedScrollViewHeaderSliversBuilder(BuildContext context, bool innerBoxIsScrolled); typedef List<Widget> NestedScrollViewHeaderSliversBuilder(BuildContext context, bool innerBoxIsScrolled);
// TODO(abarth): Make this configurable with a controller. // TODO(abarth): Make this configurable with a controller.
...@@ -73,8 +78,18 @@ class NestedScrollView extends StatefulWidget { ...@@ -73,8 +78,18 @@ class NestedScrollView extends StatefulWidget {
/// Defaults to matching platform conventions. /// Defaults to matching platform conventions.
final ScrollPhysics physics; final ScrollPhysics physics;
/// A builder for any widgets that are to precede the inner scroll views (as
/// given by [body]).
///
/// Typically this is used to create a [SliverAppBar] with a [TabBar].
final NestedScrollViewHeaderSliversBuilder headerSliverBuilder; final NestedScrollViewHeaderSliversBuilder headerSliverBuilder;
/// The widget to show inside the [NestedScrollView].
///
/// Typically this will be [TabBarView].
///
/// The [body] is built in a context that provides a [PrimaryScrollController]
/// that interacts with the [NestedScrollView]'s scroll controller.
final Widget body; final Widget body;
List<Widget> _buildSlivers(BuildContext context, ScrollController innerController, bool bodyIsScrolled) { List<Widget> _buildSlivers(BuildContext context, ScrollController innerController, bool bodyIsScrolled) {
......
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'dart:math' as math;
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
...@@ -171,4 +173,26 @@ void main() { ...@@ -171,4 +173,26 @@ void main() {
final Matrix4 transform = layer.transform; final Matrix4 transform = layer.transform;
expect(transform.getTranslation(), equals(new Vector3(100.0, 75.0, 0.0))); expect(transform.getTranslation(), equals(new Vector3(100.0, 75.0, 0.0)));
}); });
testWidgets('Transform.rotate', (WidgetTester tester) async {
await tester.pumpWidget(
new Transform.rotate(
angle: math.PI / 2.0,
child: new Opacity(opacity: 0.5, child: new Container()),
),
);
final List<Layer> layers = tester.layers
..retainWhere((Layer layer) => layer is TransformLayer);
expect(layers.length, 2);
// The first transform is from the render view.
final TransformLayer layer = layers[1];
final Matrix4 transform = layer.transform;
expect(transform.storage, <dynamic>[
moreOrLessEquals(0.0), 1.0, 0.0, 0.0,
-1.0, moreOrLessEquals(0.0), 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
700.0, -100.0, 0.0, 1.0,
]);
});
} }
...@@ -16,7 +16,6 @@ class GetHealth extends Command { ...@@ -16,7 +16,6 @@ class GetHealth extends Command {
GetHealth.deserialize(Map<String, String> json) : super.deserialize(json); GetHealth.deserialize(Map<String, String> json) : super.deserialize(json);
} }
/// Application health status.
enum HealthStatus { enum HealthStatus {
/// Application is known to be in a good shape and should be able to respond. /// Application is known to be in a good shape and should be able to respond.
ok, ok,
...@@ -28,7 +27,6 @@ enum HealthStatus { ...@@ -28,7 +27,6 @@ enum HealthStatus {
final EnumIndex<HealthStatus> _healthStatusIndex = final EnumIndex<HealthStatus> _healthStatusIndex =
new EnumIndex<HealthStatus>(HealthStatus.values); new EnumIndex<HealthStatus>(HealthStatus.values);
/// Application health status.
class Health extends Result { class Health extends Result {
/// Creates a [Health] object with the given [status]. /// Creates a [Health] object with the given [status].
Health(this.status) { Health(this.status) {
...@@ -40,7 +38,6 @@ class Health extends Result { ...@@ -40,7 +38,6 @@ class Health extends Result {
return new Health(_healthStatusIndex.lookupBySimpleName(json['status'])); return new Health(_healthStatusIndex.lookupBySimpleName(json['status']));
} }
/// Health status
final HealthStatus status; final HealthStatus status;
@override @override
......
...@@ -17,7 +17,7 @@ import 'package:flutter/widgets.dart'; ...@@ -17,7 +17,7 @@ import 'package:flutter/widgets.dart';
/// one, for example the results of calling `where` on this iterable /// one, for example the results of calling `where` on this iterable
/// are also cached. /// are also cached.
Iterable<Element> collectAllElementsFrom(Element rootElement, { Iterable<Element> collectAllElementsFrom(Element rootElement, {
@required bool skipOffstage @required bool skipOffstage,
}) { }) {
return new CachingIterable<Element>(new _DepthFirstChildIterator(rootElement, skipOffstage)); return new CachingIterable<Element>(new _DepthFirstChildIterator(rootElement, skipOffstage));
} }
......
...@@ -89,6 +89,10 @@ abstract class TestWidgetsFlutterBinding extends BindingBase ...@@ -89,6 +89,10 @@ abstract class TestWidgetsFlutterBinding extends BindingBase
// Services binding omitted to avoid dragging in the licenses code. // Services binding omitted to avoid dragging in the licenses code.
WidgetsBinding { WidgetsBinding {
/// Constructor for [TestWidgetsFlutterBinding].
///
/// This constructor overrides the [debugPrint] global hook to point to
/// [debugPrintOverride], which can be overridden by subclasses.
TestWidgetsFlutterBinding() { TestWidgetsFlutterBinding() {
debugPrint = debugPrintOverride; debugPrint = debugPrintOverride;
} }
......
...@@ -236,6 +236,9 @@ abstract class Finder { ...@@ -236,6 +236,9 @@ abstract class Finder {
/// [Offstage] widgets, as well as children of inactive [Route]s. /// [Offstage] widgets, as well as children of inactive [Route]s.
final bool skipOffstage; final bool skipOffstage;
/// Returns all the [Element]s that will be considered by this finder.
///
/// See [collectAllElementsFrom].
@protected @protected
Iterable<Element> get allCandidates { Iterable<Element> get allCandidates {
return collectAllElementsFrom( return collectAllElementsFrom(
......
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