Unverified Commit 3176232c authored by Kate Lovett's avatar Kate Lovett Committed by GitHub

Doc and Error Message Improvements (#60726)

parent e8e1eb51
...@@ -23,6 +23,11 @@ const EdgeInsets _kBackgroundButtonPadding = EdgeInsets.symmetric( ...@@ -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 /// Takes in a text or an icon that fades out and in on touch. May optionally have a
/// background. /// 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: /// See also:
/// ///
/// * <https://developer.apple.com/ios/human-interface-guidelines/controls/buttons/> /// * <https://developer.apple.com/ios/human-interface-guidelines/controls/buttons/>
......
...@@ -674,7 +674,8 @@ class ListTile extends StatelessWidget { ...@@ -674,7 +674,8 @@ class ListTile extends StatelessWidget {
/// ///
/// Typically a [Text] widget. /// Typically a [Text] widget.
/// ///
/// This should not wrap. /// This should not wrap. To enforce the single line limit, use
/// [Text.maxLines].
final Widget title; final Widget title;
/// Additional content displayed below the title. /// Additional content displayed below the title.
...@@ -684,7 +685,8 @@ class ListTile extends StatelessWidget { ...@@ -684,7 +685,8 @@ class ListTile extends StatelessWidget {
/// If [isThreeLine] is false, this should not wrap. /// If [isThreeLine] is false, this should not wrap.
/// ///
/// If [isThreeLine] is true, this should be configured to take a maximum of /// 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; final Widget subtitle;
/// A widget to display after the title. /// A widget to display after the title.
...@@ -705,6 +707,9 @@ class ListTile extends StatelessWidget { ...@@ -705,6 +707,9 @@ class ListTile extends StatelessWidget {
/// ///
/// If false, the list tile is treated as having one line if the subtitle is /// 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. /// 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; final bool isThreeLine;
/// Whether this list tile is part of a vertically dense list. /// Whether this list tile is part of a vertically dense list.
......
...@@ -36,6 +36,10 @@ export 'package:flutter/services.dart' show SmartQuotesType, SmartDashesType; ...@@ -36,6 +36,10 @@ export 'package:flutter/services.dart' show SmartQuotesType, SmartDashesType;
/// Remember to [dispose] of the [TextEditingController] when it is no longer needed. /// Remember to [dispose] of the [TextEditingController] when it is no longer needed.
/// This will ensure we discard any resources used by the object. /// 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]. /// For a documentation about the various parameters, see [TextField].
/// ///
/// {@tool snippet} /// {@tool snippet}
......
...@@ -393,26 +393,21 @@ class Border extends BoxBorder { ...@@ -393,26 +393,21 @@ class Border extends BoxBorder {
} }
@override @override
bool get isUniform { bool get isUniform => _colorIsUniform && _widthIsUniform && _styleIsUniform;
bool get _colorIsUniform {
final Color topColor = top.color; final Color topColor = top.color;
if (right.color != topColor || return right.color == topColor && bottom.color == topColor && left.color == topColor;
bottom.color != topColor || }
left.color != topColor)
return false;
bool get _widthIsUniform {
final double topWidth = top.width; final double topWidth = top.width;
if (right.width != topWidth || return right.width == topWidth && bottom.width == topWidth && left.width == topWidth;
bottom.width != topWidth || }
left.width != topWidth)
return false;
bool get _styleIsUniform {
final BorderStyle topStyle = top.style; final BorderStyle topStyle = top.style;
if (right.style != topStyle || return right.style == topStyle && bottom.style == topStyle && left.style == topStyle;
bottom.style != topStyle ||
left.style != topStyle)
return false;
return true;
} }
@override @override
...@@ -522,8 +517,30 @@ class Border extends BoxBorder { ...@@ -522,8 +517,30 @@ class Border extends BoxBorder {
} }
} }
assert(borderRadius == null, 'A borderRadius can only be given for uniform borders.'); assert(() {
assert(shape == BoxShape.rectangle, 'A border can only be drawn as a circle if it is uniform.'); if (borderRadius != null) {
throw FlutterError.fromParts(<DiagnosticsNode>[
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(<DiagnosticsNode>[
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); paintBorder(canvas, rect, top: top, right: right, bottom: bottom, left: left);
} }
......
...@@ -1705,13 +1705,16 @@ abstract class RenderBox extends RenderObject { ...@@ -1705,13 +1705,16 @@ abstract class RenderBox extends RenderObject {
if (_size is _DebugSize) { if (_size is _DebugSize) {
assert(_size._owner == this); assert(_size._owner == this);
if (RenderObject.debugActiveLayout != null) { if (RenderObject.debugActiveLayout != null) {
// We are always allowed to access our own size (for print debugging assert(
// and asserts if nothing else). Other than us, the only object that's debugDoingThisResize || debugDoingThisLayout ||
// allowed to read our size is our parent, if they've said they will. (RenderObject.debugActiveLayout == parent && _size._canBeUsedByParent),
// If you hit this assert trying to access a child's size, pass 'RenderBox.size accessed beyond the scope of resize, layout, or '
// "parentUsesSize: true" to that child's layout(). 'permitted parent access. RenderBox can always access its own size, '
assert(debugDoingThisResize || debugDoingThisLayout || 'otherwise, the only object that is allowed to read RenderBox.size '
(RenderObject.debugActiveLayout == parent && _size._canBeUsedByParent)); '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); assert(_size == this._size);
} }
......
...@@ -414,7 +414,8 @@ class SliverGridDelegateWithMaxCrossAxisExtent extends SliverGridDelegate { ...@@ -414,7 +414,8 @@ class SliverGridDelegateWithMaxCrossAxisExtent extends SliverGridDelegate {
/// The ratio of the cross-axis to the main-axis extent of each child. /// The ratio of the cross-axis to the main-axis extent of each child.
final double childAspectRatio; final double childAspectRatio;
bool _debugAssertIsValid() { bool _debugAssertIsValid(double crossAxisExtent) {
assert(crossAxisExtent > 0.0);
assert(maxCrossAxisExtent > 0.0); assert(maxCrossAxisExtent > 0.0);
assert(mainAxisSpacing >= 0.0); assert(mainAxisSpacing >= 0.0);
assert(crossAxisSpacing >= 0.0); assert(crossAxisSpacing >= 0.0);
...@@ -424,7 +425,7 @@ class SliverGridDelegateWithMaxCrossAxisExtent extends SliverGridDelegate { ...@@ -424,7 +425,7 @@ class SliverGridDelegateWithMaxCrossAxisExtent extends SliverGridDelegate {
@override @override
SliverGridLayout getLayout(SliverConstraints constraints) { SliverGridLayout getLayout(SliverConstraints constraints) {
assert(_debugAssertIsValid()); assert(_debugAssertIsValid(constraints.crossAxisExtent));
final int crossAxisCount = (constraints.crossAxisExtent / (maxCrossAxisExtent + crossAxisSpacing)).ceil(); final int crossAxisCount = (constraints.crossAxisExtent / (maxCrossAxisExtent + crossAxisSpacing)).ceil();
final double usableCrossAxisExtent = constraints.crossAxisExtent - crossAxisSpacing * (crossAxisCount - 1); final double usableCrossAxisExtent = constraints.crossAxisExtent - crossAxisSpacing * (crossAxisCount - 1);
final double childCrossAxisExtent = usableCrossAxisExtent / crossAxisCount; final double childCrossAxisExtent = usableCrossAxisExtent / crossAxisCount;
......
...@@ -276,6 +276,8 @@ enum StackFit { ...@@ -276,6 +276,8 @@ enum StackFit {
/// visible. /// visible.
enum Overflow { enum Overflow {
/// Overflowing children will be visible. /// Overflowing children will be visible.
///
/// The visible overflow area will not accept hit testing.
visible, visible,
/// Overflowing children will be clipped to the bounds of their parent. /// Overflowing children will be clipped to the bounds of their parent.
......
...@@ -13,6 +13,41 @@ import 'framework.dart'; ...@@ -13,6 +13,41 @@ import 'framework.dart';
/// Animated widget that automatically transitions its size over a given /// Animated widget that automatically transitions its size over a given
/// duration whenever the given child's size changes. /// 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<MyStatefulWidget> 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: /// See also:
/// ///
/// * [SizeTransition], which changes its size based on an [Animation]. /// * [SizeTransition], which changes its size based on an [Animation].
......
...@@ -3285,6 +3285,9 @@ class Stack extends MultiChildRenderObjectWidget { ...@@ -3285,6 +3285,9 @@ class Stack extends MultiChildRenderObjectWidget {
/// Some children in a stack might overflow its box. When this flag is set to /// 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. /// [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 /// This overrides [clipBehavior] for now due to a staged roll out without
/// breaking Google. We will remove it and only use [clipBehavior] soon. /// breaking Google. We will remove it and only use [clipBehavior] soon.
final Overflow overflow; final Overflow overflow;
......
...@@ -300,6 +300,10 @@ class _LocalizationsScope extends InheritedWidget { ...@@ -300,6 +300,10 @@ class _LocalizationsScope extends InheritedWidget {
/// `Localizations.of(context)` will be rebuilt after the resources /// `Localizations.of(context)` will be rebuilt after the resources
/// for the new locale have been loaded. /// 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} /// {@tool snippet}
/// ///
/// This following class is defined in terms of the /// This following class is defined in terms of the
......
...@@ -2404,7 +2404,11 @@ class _RouteEntry extends RouteTransitionRecord { ...@@ -2404,7 +2404,11 @@ class _RouteEntry extends RouteTransitionRecord {
assert(currentState == _RouteLifecycle.push || currentState == _RouteLifecycle.pushReplace || currentState == _RouteLifecycle.replace); assert(currentState == _RouteLifecycle.push || currentState == _RouteLifecycle.pushReplace || currentState == _RouteLifecycle.replace);
assert(navigator != null); assert(navigator != null);
assert(navigator._debugLocked); 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; final _RouteLifecycle previousState = currentState;
route._navigator = navigator; route._navigator = navigator;
route.install(); route.install();
......
...@@ -1051,12 +1051,13 @@ class ListView extends BoxScrollView { ...@@ -1051,12 +1051,13 @@ class ListView extends BoxScrollView {
/// The `itemBuilder` callback will be called only with indices greater than /// The `itemBuilder` callback will be called only with indices greater than
/// or equal to zero and less than `itemCount`. /// or equal to zero and less than `itemCount`.
/// ///
/// The `itemBuilder` should actually create the widget instances when called. /// The `itemBuilder` should always return a non-null widget, and actually
/// Avoid using a builder that returns a previously-constructed widget; if the /// create the widget instances when called. Avoid using a builder that
/// list view's children are created in advance, or all at once when the /// returns a previously-constructed widget; if the list view's children are
/// [ListView] itself is created, it is more efficient to use the [ListView] /// created in advance, or all at once when the [ListView] itself is created,
/// constructor. Even more efficient, however, is to create the instances on /// it is more efficient to use the [ListView] constructor. Even more
/// demand using this constructor's `itemBuilder` callback. /// efficient, however, is to create the instances on demand using this
/// constructor's `itemBuilder` callback.
/// ///
/// The `addAutomaticKeepAlives` argument corresponds to the /// The `addAutomaticKeepAlives` argument corresponds to the
/// [SliverChildBuilderDelegate.addAutomaticKeepAlives] property. The /// [SliverChildBuilderDelegate.addAutomaticKeepAlives] property. The
...@@ -1128,11 +1129,11 @@ class ListView extends BoxScrollView { ...@@ -1128,11 +1129,11 @@ class ListView extends BoxScrollView {
/// The `separatorBuilder` callback will be called with indices greater than /// The `separatorBuilder` callback will be called with indices greater than
/// or equal to zero and less than `itemCount - 1`. /// or equal to zero and less than `itemCount - 1`.
/// ///
/// The `itemBuilder` and `separatorBuilder` callbacks should actually create /// The `itemBuilder` and `separatorBuilder` callbacks should always return a
/// widget instances when called. Avoid using a builder that returns a /// non-null widget, and actually create widget instances when called. Avoid
/// previously-constructed widget; if the list view's children are created in /// using a builder that returns a previously-constructed widget; if the list
/// advance, or all at once when the [ListView] itself is created, it is more /// view's children are created in advance, or all at once when the [ListView]
/// efficient to use the [ListView] constructor. /// itself is created, it is more efficient to use the [ListView] constructor.
/// ///
/// {@tool snippet} /// {@tool snippet}
/// ///
...@@ -1439,6 +1440,24 @@ class ListView extends BoxScrollView { ...@@ -1439,6 +1440,24 @@ class ListView extends BoxScrollView {
/// extremities to avoid partial obstructions indicated by [MediaQuery]'s /// extremities to avoid partial obstructions indicated by [MediaQuery]'s
/// padding. To avoid this behavior, override with a zero [padding] property. /// 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 /// Once code has been ported to use [CustomScrollView], other slivers, such as
/// [SliverList] or [SliverAppBar], can be put in the [CustomScrollView.slivers] /// [SliverList] or [SliverAppBar], can be put in the [CustomScrollView.slivers]
/// list. /// list.
......
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