diff --git a/packages/flutter/lib/src/cupertino/button.dart b/packages/flutter/lib/src/cupertino/button.dart index 58db983d2c7..7eda6460869 100644 --- a/packages/flutter/lib/src/cupertino/button.dart +++ b/packages/flutter/lib/src/cupertino/button.dart @@ -23,6 +23,11 @@ const EdgeInsets _kBackgroundButtonPadding = EdgeInsets.symmetric( /// Takes in a text or an icon that fades out and in on touch. May optionally have a /// background. /// +/// The [padding] defaults to 16.0 pixels. When using a [CupertinoButton] within +/// a fixed height parent, like a [CupertinoNavigationBar], a smaller, or even +/// [EdgeInsets.zero], should be used to prevent clipping larger [child] +/// widgets. +/// /// See also: /// /// * diff --git a/packages/flutter/lib/src/material/list_tile.dart b/packages/flutter/lib/src/material/list_tile.dart index 945ddec3024..28b75cbbed9 100644 --- a/packages/flutter/lib/src/material/list_tile.dart +++ b/packages/flutter/lib/src/material/list_tile.dart @@ -674,7 +674,8 @@ class ListTile extends StatelessWidget { /// /// Typically a [Text] widget. /// - /// This should not wrap. + /// This should not wrap. To enforce the single line limit, use + /// [Text.maxLines]. final Widget title; /// Additional content displayed below the title. @@ -684,7 +685,8 @@ class ListTile extends StatelessWidget { /// If [isThreeLine] is false, this should not wrap. /// /// If [isThreeLine] is true, this should be configured to take a maximum of - /// two lines. + /// two lines. For example, you can use [Text.maxLines] to enforce the number + /// of lines. final Widget subtitle; /// A widget to display after the title. @@ -705,6 +707,9 @@ class ListTile extends StatelessWidget { /// /// If false, the list tile is treated as having one line if the subtitle is /// null and treated as having two lines if the subtitle is non-null. + /// + /// When using a [Text] widget for [title] and [subtitle], you can enforce + /// line limits using [Text.maxLines]. final bool isThreeLine; /// Whether this list tile is part of a vertically dense list. diff --git a/packages/flutter/lib/src/material/text_form_field.dart b/packages/flutter/lib/src/material/text_form_field.dart index ab584553506..f91a9cc011f 100644 --- a/packages/flutter/lib/src/material/text_form_field.dart +++ b/packages/flutter/lib/src/material/text_form_field.dart @@ -36,6 +36,10 @@ export 'package:flutter/services.dart' show SmartQuotesType, SmartDashesType; /// Remember to [dispose] of the [TextEditingController] when it is no longer needed. /// This will ensure we discard any resources used by the object. /// +/// By default, [TextFormField.decoration] will apply the +/// [ThemeData.inputDecorationTheme] for the current context to the +/// [InputDecoration], see [InputDecoration.applyDefaults]. +/// /// For a documentation about the various parameters, see [TextField]. /// /// {@tool snippet} diff --git a/packages/flutter/lib/src/painting/box_border.dart b/packages/flutter/lib/src/painting/box_border.dart index f3e43fa4546..74b39c25a99 100644 --- a/packages/flutter/lib/src/painting/box_border.dart +++ b/packages/flutter/lib/src/painting/box_border.dart @@ -393,26 +393,21 @@ class Border extends BoxBorder { } @override - bool get isUniform { + bool get isUniform => _colorIsUniform && _widthIsUniform && _styleIsUniform; + + bool get _colorIsUniform { final Color topColor = top.color; - if (right.color != topColor || - bottom.color != topColor || - left.color != topColor) - return false; + return right.color == topColor && bottom.color == topColor && left.color == topColor; + } + bool get _widthIsUniform { final double topWidth = top.width; - if (right.width != topWidth || - bottom.width != topWidth || - left.width != topWidth) - return false; + return right.width == topWidth && bottom.width == topWidth && left.width == topWidth; + } + bool get _styleIsUniform { final BorderStyle topStyle = top.style; - if (right.style != topStyle || - bottom.style != topStyle || - left.style != topStyle) - return false; - - return true; + return right.style == topStyle && bottom.style == topStyle && left.style == topStyle; } @override @@ -522,8 +517,30 @@ class Border extends BoxBorder { } } - assert(borderRadius == null, 'A borderRadius can only be given for uniform borders.'); - assert(shape == BoxShape.rectangle, 'A border can only be drawn as a circle if it is uniform.'); + assert(() { + if (borderRadius != null) { + throw FlutterError.fromParts([ + ErrorSummary('A borderRadius can only be given for a uniform Border.'), + ErrorDescription('The following is not uniform:'), + if (!_colorIsUniform) ErrorDescription('BorderSide.color'), + if (!_widthIsUniform) ErrorDescription('BorderSide.width'), + if (!_styleIsUniform) ErrorDescription('BorderSide.style'), + ]); + } + return true; + }()); + assert(() { + if (shape != BoxShape.rectangle) { + throw FlutterError.fromParts([ + ErrorSummary('A Border can only be drawn as a circle if it is uniform'), + ErrorDescription('The following is not uniform:'), + if (!_colorIsUniform) ErrorDescription('BorderSide.color'), + if (!_widthIsUniform) ErrorDescription('BorderSide.width'), + if (!_styleIsUniform) ErrorDescription('BorderSide.style'), + ]); + } + return true; + }()); paintBorder(canvas, rect, top: top, right: right, bottom: bottom, left: left); } diff --git a/packages/flutter/lib/src/rendering/box.dart b/packages/flutter/lib/src/rendering/box.dart index 5eb57e790fc..1ad4cb9d965 100644 --- a/packages/flutter/lib/src/rendering/box.dart +++ b/packages/flutter/lib/src/rendering/box.dart @@ -1705,13 +1705,16 @@ abstract class RenderBox extends RenderObject { if (_size is _DebugSize) { assert(_size._owner == this); if (RenderObject.debugActiveLayout != null) { - // We are always allowed to access our own size (for print debugging - // and asserts if nothing else). Other than us, the only object that's - // allowed to read our size is our parent, if they've said they will. - // If you hit this assert trying to access a child's size, pass - // "parentUsesSize: true" to that child's layout(). - assert(debugDoingThisResize || debugDoingThisLayout || - (RenderObject.debugActiveLayout == parent && _size._canBeUsedByParent)); + assert( + debugDoingThisResize || debugDoingThisLayout || + (RenderObject.debugActiveLayout == parent && _size._canBeUsedByParent), + 'RenderBox.size accessed beyond the scope of resize, layout, or ' + 'permitted parent access. RenderBox can always access its own size, ' + 'otherwise, the only object that is allowed to read RenderBox.size ' + 'is its parent, if they have said they will. It you hit this assert ' + 'trying to access a child\'s size, pass "parentUsesSize: true" to ' + 'that child\'s layout().' + ); } assert(_size == this._size); } diff --git a/packages/flutter/lib/src/rendering/sliver_grid.dart b/packages/flutter/lib/src/rendering/sliver_grid.dart index a29fe119a8a..19622d130e8 100644 --- a/packages/flutter/lib/src/rendering/sliver_grid.dart +++ b/packages/flutter/lib/src/rendering/sliver_grid.dart @@ -414,7 +414,8 @@ class SliverGridDelegateWithMaxCrossAxisExtent extends SliverGridDelegate { /// The ratio of the cross-axis to the main-axis extent of each child. final double childAspectRatio; - bool _debugAssertIsValid() { + bool _debugAssertIsValid(double crossAxisExtent) { + assert(crossAxisExtent > 0.0); assert(maxCrossAxisExtent > 0.0); assert(mainAxisSpacing >= 0.0); assert(crossAxisSpacing >= 0.0); @@ -424,7 +425,7 @@ class SliverGridDelegateWithMaxCrossAxisExtent extends SliverGridDelegate { @override SliverGridLayout getLayout(SliverConstraints constraints) { - assert(_debugAssertIsValid()); + assert(_debugAssertIsValid(constraints.crossAxisExtent)); final int crossAxisCount = (constraints.crossAxisExtent / (maxCrossAxisExtent + crossAxisSpacing)).ceil(); final double usableCrossAxisExtent = constraints.crossAxisExtent - crossAxisSpacing * (crossAxisCount - 1); final double childCrossAxisExtent = usableCrossAxisExtent / crossAxisCount; diff --git a/packages/flutter/lib/src/rendering/stack.dart b/packages/flutter/lib/src/rendering/stack.dart index e0d3b1604b0..58c10e94679 100644 --- a/packages/flutter/lib/src/rendering/stack.dart +++ b/packages/flutter/lib/src/rendering/stack.dart @@ -276,6 +276,8 @@ enum StackFit { /// visible. enum Overflow { /// Overflowing children will be visible. + /// + /// The visible overflow area will not accept hit testing. visible, /// Overflowing children will be clipped to the bounds of their parent. diff --git a/packages/flutter/lib/src/widgets/animated_size.dart b/packages/flutter/lib/src/widgets/animated_size.dart index d6b8edfc42c..1b5de7e460c 100644 --- a/packages/flutter/lib/src/widgets/animated_size.dart +++ b/packages/flutter/lib/src/widgets/animated_size.dart @@ -13,6 +13,41 @@ import 'framework.dart'; /// Animated widget that automatically transitions its size over a given /// duration whenever the given child's size changes. /// +/// {@tool dartpad --template=stateful_widget_scaffold_center_freeform_state} +/// This example makes a [Container] react to being touched, causing the child +/// of the [AnimatedSize] widget, here a [FlutterLogo], to animate. +/// +/// ```dart +/// class _MyStatefulWidgetState extends State with SingleTickerProviderStateMixin { +/// double _size = 50.0; +/// bool _large = false; +/// +/// void _updateSize() { +/// setState(() { +/// _size = _large ? 250.0 : 100.0; +/// _large = !_large; +/// }); +/// } +/// +/// @override +/// Widget build(BuildContext context) { +/// return GestureDetector( +/// onTap: () => _updateSize(), +/// child: Container( +/// color: Colors.amberAccent, +/// child: AnimatedSize( +/// curve: Curves.easeIn, +/// vsync: this, +/// duration: Duration(seconds: 1), +/// child: FlutterLogo(size: _size), +/// ), +/// ), +/// ); +/// } +/// } +/// ``` +/// {@end-tool} +/// /// See also: /// /// * [SizeTransition], which changes its size based on an [Animation]. diff --git a/packages/flutter/lib/src/widgets/basic.dart b/packages/flutter/lib/src/widgets/basic.dart index bbdfe2d3210..a979d243045 100644 --- a/packages/flutter/lib/src/widgets/basic.dart +++ b/packages/flutter/lib/src/widgets/basic.dart @@ -3285,6 +3285,9 @@ class Stack extends MultiChildRenderObjectWidget { /// Some children in a stack might overflow its box. When this flag is set to /// [Overflow.clip], children cannot paint outside of the stack's box. /// + /// When set to [Overflow.visible], the visible overflow area will not accept + /// hit testing. + /// /// This overrides [clipBehavior] for now due to a staged roll out without /// breaking Google. We will remove it and only use [clipBehavior] soon. final Overflow overflow; diff --git a/packages/flutter/lib/src/widgets/localizations.dart b/packages/flutter/lib/src/widgets/localizations.dart index 9a052b06e60..d980d242bdd 100644 --- a/packages/flutter/lib/src/widgets/localizations.dart +++ b/packages/flutter/lib/src/widgets/localizations.dart @@ -300,6 +300,10 @@ class _LocalizationsScope extends InheritedWidget { /// `Localizations.of(context)` will be rebuilt after the resources /// for the new locale have been loaded. /// +/// The `Localizations` widget also instantiates [Directionality] in order to +/// support the appropriate [Directionality.textDirection] of the localized +/// resources. +/// /// {@tool snippet} /// /// This following class is defined in terms of the diff --git a/packages/flutter/lib/src/widgets/navigator.dart b/packages/flutter/lib/src/widgets/navigator.dart index 3dc8f47776b..5da966bce71 100644 --- a/packages/flutter/lib/src/widgets/navigator.dart +++ b/packages/flutter/lib/src/widgets/navigator.dart @@ -2404,7 +2404,11 @@ class _RouteEntry extends RouteTransitionRecord { assert(currentState == _RouteLifecycle.push || currentState == _RouteLifecycle.pushReplace || currentState == _RouteLifecycle.replace); assert(navigator != null); assert(navigator._debugLocked); - assert(route._navigator == null); + assert( + route._navigator == null, + 'The pushed route has already been used. When pushing a route, a new ' + 'Route object must be provided.', + ); final _RouteLifecycle previousState = currentState; route._navigator = navigator; route.install(); diff --git a/packages/flutter/lib/src/widgets/scroll_view.dart b/packages/flutter/lib/src/widgets/scroll_view.dart index 06b75926a59..c4341157565 100644 --- a/packages/flutter/lib/src/widgets/scroll_view.dart +++ b/packages/flutter/lib/src/widgets/scroll_view.dart @@ -1051,12 +1051,13 @@ class ListView extends BoxScrollView { /// The `itemBuilder` callback will be called only with indices greater than /// or equal to zero and less than `itemCount`. /// - /// The `itemBuilder` should actually create the widget instances when called. - /// Avoid using a builder that returns a previously-constructed widget; if the - /// list view's children are created in advance, or all at once when the - /// [ListView] itself is created, it is more efficient to use the [ListView] - /// constructor. Even more efficient, however, is to create the instances on - /// demand using this constructor's `itemBuilder` callback. + /// The `itemBuilder` should always return a non-null widget, and actually + /// create the widget instances when called. Avoid using a builder that + /// returns a previously-constructed widget; if the list view's children are + /// created in advance, or all at once when the [ListView] itself is created, + /// it is more efficient to use the [ListView] constructor. Even more + /// efficient, however, is to create the instances on demand using this + /// constructor's `itemBuilder` callback. /// /// The `addAutomaticKeepAlives` argument corresponds to the /// [SliverChildBuilderDelegate.addAutomaticKeepAlives] property. The @@ -1128,11 +1129,11 @@ class ListView extends BoxScrollView { /// The `separatorBuilder` callback will be called with indices greater than /// or equal to zero and less than `itemCount - 1`. /// - /// The `itemBuilder` and `separatorBuilder` callbacks should actually create - /// widget instances when called. Avoid using a builder that returns a - /// previously-constructed widget; if the list view's children are created in - /// advance, or all at once when the [ListView] itself is created, it is more - /// efficient to use the [ListView] constructor. + /// The `itemBuilder` and `separatorBuilder` callbacks should always return a + /// non-null widget, and actually create widget instances when called. Avoid + /// using a builder that returns a previously-constructed widget; if the list + /// view's children are created in advance, or all at once when the [ListView] + /// itself is created, it is more efficient to use the [ListView] constructor. /// /// {@tool snippet} /// @@ -1439,6 +1440,24 @@ class ListView extends BoxScrollView { /// extremities to avoid partial obstructions indicated by [MediaQuery]'s /// padding. To avoid this behavior, override with a zero [padding] property. /// +/// {@tool snippet} +/// The following example demonstrates how to override the default top padding +/// using [MediaQuery.removePadding]. +/// +/// ```dart +/// Widget myWidget(BuildContext context) { +/// return MediaQuery.removePadding( +/// context: context, +/// removeTop: true, +/// child: ListView.builder( +/// itemCount: 25, +/// itemBuilder: (BuildContext context, int index) => ListTile(title: Text('item $index')), +/// ) +/// ); +/// } +/// ``` +/// {@end-tool} +/// /// Once code has been ported to use [CustomScrollView], other slivers, such as /// [SliverList] or [SliverAppBar], can be put in the [CustomScrollView.slivers] /// list.