diff --git a/packages/flutter/lib/src/material/bottom_app_bar.dart b/packages/flutter/lib/src/material/bottom_app_bar.dart index 682dc04ac0..6a05e59516 100644 --- a/packages/flutter/lib/src/material/bottom_app_bar.dart +++ b/packages/flutter/lib/src/material/bottom_app_bar.dart @@ -42,7 +42,7 @@ import 'theme.dart'; class BottomAppBar extends StatefulWidget { /// Creates a bottom application bar. /// - /// The [clipBehavior] argument must not be null. + /// The [clipBehavior] argument defaults to [Clip.none] and must not be null. /// Additionally, [elevation] must be non-negative. /// /// If [color], [elevation], or [shape] are null, their [BottomAppBarTheme] values will be used. @@ -56,9 +56,9 @@ class BottomAppBar extends StatefulWidget { this.clipBehavior = Clip.none, this.notchMargin = 4.0, this.child, - }) : assert(clipBehavior != null), - assert(elevation == null || elevation >= 0.0), + }) : assert(elevation == null || elevation >= 0.0), assert(notchMargin != null), + assert(clipBehavior != null), super(key: key); /// The widget below this widget in the tree. @@ -92,6 +92,8 @@ class BottomAppBar extends StatefulWidget { final NotchedShape shape; /// {@macro flutter.widgets.Clip} + /// + /// Defaults to [Clip.none], and must not be null. final Clip clipBehavior; /// The margin between the [FloatingActionButton] and the [BottomAppBar]'s diff --git a/packages/flutter/lib/src/material/button.dart b/packages/flutter/lib/src/material/button.dart index 95e03c5466..0fad0969ea 100644 --- a/packages/flutter/lib/src/material/button.dart +++ b/packages/flutter/lib/src/material/button.dart @@ -241,6 +241,8 @@ class RawMaterialButton extends StatefulWidget { final bool autofocus; /// {@macro flutter.widgets.Clip} + /// + /// Defaults to [Clip.none], and must not be null. final Clip clipBehavior; @override diff --git a/packages/flutter/lib/src/material/card.dart b/packages/flutter/lib/src/material/card.dart index 1ff6aa04ea..0dcc45558c 100644 --- a/packages/flutter/lib/src/material/card.dart +++ b/packages/flutter/lib/src/material/card.dart @@ -145,6 +145,7 @@ class Card extends StatelessWidget { final bool borderOnForeground; /// {@macro flutter.widgets.Clip} + /// /// If this property is null then [ThemeData.cardTheme.clipBehavior] is used. /// If that's null then the behavior will be [Clip.none]. final Clip clipBehavior; @@ -177,7 +178,6 @@ class Card extends StatelessWidget { final Widget child; static const double _defaultElevation = 1.0; - static const Clip _defaultClipBehavior = Clip.none; @override Widget build(BuildContext context) { @@ -195,7 +195,7 @@ class Card extends StatelessWidget { borderRadius: BorderRadius.all(Radius.circular(4.0)), ), borderOnForeground: borderOnForeground, - clipBehavior: clipBehavior ?? cardTheme.clipBehavior ?? _defaultClipBehavior, + clipBehavior: clipBehavior ?? cardTheme.clipBehavior ?? Clip.none, child: Semantics( explicitChildNodes: !semanticContainer, child: child, diff --git a/packages/flutter/lib/src/material/chip.dart b/packages/flutter/lib/src/material/chip.dart index 4cefe3ae35..6755cb95de 100644 --- a/packages/flutter/lib/src/material/chip.dart +++ b/packages/flutter/lib/src/material/chip.dart @@ -96,6 +96,8 @@ abstract class ChipAttributes { ShapeBorder get shape; /// {@macro flutter.widgets.Clip} + /// + /// Defaults to [Clip.none], and must not be null. Clip get clipBehavior; /// {@macro flutter.widgets.Focus.focusNode} @@ -1227,6 +1229,7 @@ class ActionChip extends StatelessWidget implements ChipAttributes, TappableChip this.elevation, this.shadowColor, }) : assert(label != null), + assert(clipBehavior != null), assert(autofocus != null), assert( onPressed != null, diff --git a/packages/flutter/lib/src/material/flat_button.dart b/packages/flutter/lib/src/material/flat_button.dart index 9dec828774..bd84a66ea0 100644 --- a/packages/flutter/lib/src/material/flat_button.dart +++ b/packages/flutter/lib/src/material/flat_button.dart @@ -115,12 +115,13 @@ class FlatButton extends MaterialButton { Brightness colorBrightness, EdgeInsetsGeometry padding, ShapeBorder shape, - Clip clipBehavior, + Clip clipBehavior = Clip.none, FocusNode focusNode, bool autofocus = false, MaterialTapTargetSize materialTapTargetSize, @required Widget child, - }) : assert(autofocus != null), + }) : assert(clipBehavior != null), + assert(autofocus != null), super( key: key, onPressed: onPressed, @@ -196,7 +197,7 @@ class FlatButton extends MaterialButton { padding: buttonTheme.getPadding(this), constraints: buttonTheme.getConstraints(this), shape: buttonTheme.getShape(this), - clipBehavior: clipBehavior ?? Clip.none, + clipBehavior: clipBehavior, focusNode: focusNode, autofocus: autofocus, materialTapTargetSize: buttonTheme.getMaterialTapTargetSize(this), @@ -227,7 +228,7 @@ class _FlatButtonWithIcon extends FlatButton with MaterialButtonWithIconMixin { Brightness colorBrightness, EdgeInsetsGeometry padding, ShapeBorder shape, - Clip clipBehavior, + Clip clipBehavior = Clip.none, FocusNode focusNode, bool autofocus = false, MaterialTapTargetSize materialTapTargetSize, @@ -235,6 +236,7 @@ class _FlatButtonWithIcon extends FlatButton with MaterialButtonWithIconMixin { @required Widget label, }) : assert(icon != null), assert(label != null), + assert(clipBehavior != null), assert(autofocus != null), super( key: key, diff --git a/packages/flutter/lib/src/material/floating_action_button.dart b/packages/flutter/lib/src/material/floating_action_button.dart index 31f32ede96..4910f95235 100644 --- a/packages/flutter/lib/src/material/floating_action_button.dart +++ b/packages/flutter/lib/src/material/floating_action_button.dart @@ -122,7 +122,7 @@ class _DefaultHeroTag { class FloatingActionButton extends StatelessWidget { /// Creates a circular floating action button. /// - /// The [mini] and [clipBehavior] arguments must be non-null. Additionally, + /// The [mini] and [clipBehavior] arguments must not be null. Additionally, /// [elevation], [highlightElevation], and [disabledElevation] (if specified) /// must be non-negative. const FloatingActionButton({ @@ -154,6 +154,7 @@ class FloatingActionButton extends StatelessWidget { assert(highlightElevation == null || highlightElevation >= 0.0), assert(disabledElevation == null || disabledElevation >= 0.0), assert(mini != null), + assert(clipBehavior != null), assert(isExtended != null), assert(autofocus != null), _sizeConstraints = mini ? _kMiniSizeConstraints : _kSizeConstraints, @@ -162,7 +163,7 @@ class FloatingActionButton extends StatelessWidget { /// Creates a wider [StadiumBorder]-shaped floating action button with /// an optional [icon] and a [label]. /// - /// The [label], [autofocus], and [clipBehavior] arguments must non-null. + /// The [label], [autofocus], and [clipBehavior] arguments must not be null. /// Additionally, [elevation], [highlightElevation], and [disabledElevation] /// (if specified) must be non-negative. FloatingActionButton.extended({ @@ -194,6 +195,7 @@ class FloatingActionButton extends StatelessWidget { assert(highlightElevation == null || highlightElevation >= 0.0), assert(disabledElevation == null || disabledElevation >= 0.0), assert(isExtended != null), + assert(clipBehavior != null), assert(autofocus != null), _sizeConstraints = _kExtendedSizeConstraints, mini = false, @@ -363,6 +365,8 @@ class FloatingActionButton extends StatelessWidget { final ShapeBorder shape; /// {@macro flutter.widgets.Clip} + /// + /// Defaults to [Clip.none], and must not be null. final Clip clipBehavior; /// True if this is an "extended" floating action button. @@ -463,7 +467,7 @@ class FloatingActionButton extends StatelessWidget { splashColor: splashColor, textStyle: textStyle, shape: shape, - clipBehavior: clipBehavior ?? Clip.none, + clipBehavior: clipBehavior, focusNode: focusNode, autofocus: autofocus, child: child, diff --git a/packages/flutter/lib/src/material/material.dart b/packages/flutter/lib/src/material/material.dart index 293d1fc52b..3ef5c75391 100644 --- a/packages/flutter/lib/src/material/material.dart +++ b/packages/flutter/lib/src/material/material.dart @@ -157,9 +157,9 @@ abstract class MaterialInkController { class Material extends StatefulWidget { /// Creates a piece of material. /// - /// The [type], [elevation], [shadowColor], [borderOnForeground] and - /// [animationDuration] arguments must not be null. Additionally, [elevation] - /// must be non-negative. + /// The [type], [elevation], [shadowColor], [borderOnForeground], + /// [clipBehavior], and [animationDuration] arguments must not be null. + /// Additionally, [elevation] must be non-negative. /// /// If a [shape] is specified, then the [borderRadius] property must be /// null and the [type] property must not be [MaterialType.circle]. If the @@ -185,8 +185,8 @@ class Material extends StatefulWidget { assert(!(shape != null && borderRadius != null)), assert(animationDuration != null), assert(!(identical(type, MaterialType.circle) && (borderRadius != null || shape != null))), - assert(clipBehavior != null), assert(borderOnForeground != null), + assert(clipBehavior != null), super(key: key); /// The widget below this widget in the tree. @@ -264,6 +264,8 @@ class Material extends StatefulWidget { /// See the enum [Clip] for details of all possible options and their common /// use cases. /// {@endtemplate} + /// + /// Defaults to [Clip.none], and must not be null. final Clip clipBehavior; /// Defines the duration of animated changes for [shape], [elevation], @@ -670,6 +672,11 @@ class ShapeBorderTween extends Tween { /// /// Animates [elevation], [shadowColor], and [shape]. class _MaterialInterior extends ImplicitlyAnimatedWidget { + /// Creates a const instance of [_MaterialInterior]. + /// + /// The [child], [shape], [clipBehavior], [color], and [shadowColor] arguments + /// must not be null. The [elevation] must be specified and greater than or + /// equal to zero. const _MaterialInterior({ Key key, @required this.child, @@ -707,6 +714,8 @@ class _MaterialInterior extends ImplicitlyAnimatedWidget { final bool borderOnForeground; /// {@macro flutter.widgets.Clip} + /// + /// Defaults to [Clip.none], and must not be null. final Clip clipBehavior; /// The target z-coordinate at which to place this physical object relative diff --git a/packages/flutter/lib/src/material/material_button.dart b/packages/flutter/lib/src/material/material_button.dart index 600050a070..461b20dbec 100644 --- a/packages/flutter/lib/src/material/material_button.dart +++ b/packages/flutter/lib/src/material/material_button.dart @@ -77,7 +77,8 @@ class MaterialButton extends StatelessWidget { this.minWidth, this.height, this.child, - }) : assert(autofocus != null), + }) : assert(clipBehavior != null), + assert(autofocus != null), assert(elevation == null || elevation >= 0.0), assert(focusElevation == null || focusElevation >= 0.0), assert(hoverElevation == null || hoverElevation >= 0.0), @@ -306,6 +307,8 @@ class MaterialButton extends StatelessWidget { final ShapeBorder shape; /// {@macro flutter.widgets.Clip} + /// + /// Defaults to [Clip.none], and must not be null. final Clip clipBehavior; /// {@macro flutter.widgets.Focus.focusNode} @@ -362,7 +365,7 @@ class MaterialButton extends StatelessWidget { minHeight: height, ), shape: buttonTheme.getShape(this), - clipBehavior: clipBehavior ?? Clip.none, + clipBehavior: clipBehavior, focusNode: focusNode, animationDuration: buttonTheme.getAnimationDuration(this), child: child, diff --git a/packages/flutter/lib/src/material/outline_button.dart b/packages/flutter/lib/src/material/outline_button.dart index fda1ab961b..4e672d12da 100644 --- a/packages/flutter/lib/src/material/outline_button.dart +++ b/packages/flutter/lib/src/material/outline_button.dart @@ -75,11 +75,12 @@ class OutlineButton extends MaterialButton { this.highlightedBorderColor, EdgeInsetsGeometry padding, ShapeBorder shape, - Clip clipBehavior, + Clip clipBehavior = Clip.none, FocusNode focusNode, bool autofocus = false, Widget child, }) : assert(highlightElevation == null || highlightElevation >= 0.0), + assert(clipBehavior != null), assert(autofocus != null), super( key: key, @@ -220,12 +221,13 @@ class _OutlineButtonWithIcon extends OutlineButton with MaterialButtonWithIconMi BorderSide borderSide, EdgeInsetsGeometry padding, ShapeBorder shape, - Clip clipBehavior, + Clip clipBehavior = Clip.none, FocusNode focusNode, bool autofocus = false, @required Widget icon, @required Widget label, }) : assert(highlightElevation == null || highlightElevation >= 0.0), + assert(clipBehavior != null), assert(autofocus != null), assert(icon != null), assert(label != null), @@ -279,12 +281,13 @@ class _OutlineButton extends StatefulWidget { @required this.highlightedBorderColor, this.padding, this.shape, - this.clipBehavior, + this.clipBehavior = Clip.none, this.focusNode, this.autofocus = false, this.child, }) : assert(highlightElevation != null && highlightElevation >= 0.0), assert(highlightedBorderColor != null), + assert(clipBehavior != null), assert(autofocus != null), super(key: key); diff --git a/packages/flutter/lib/src/material/raised_button.dart b/packages/flutter/lib/src/material/raised_button.dart index dfb4cc5c4b..17cd6f60ab 100644 --- a/packages/flutter/lib/src/material/raised_button.dart +++ b/packages/flutter/lib/src/material/raised_button.dart @@ -126,7 +126,7 @@ class RaisedButton extends MaterialButton { double disabledElevation, EdgeInsetsGeometry padding, ShapeBorder shape, - Clip clipBehavior, + Clip clipBehavior = Clip.none, FocusNode focusNode, bool autofocus = false, MaterialTapTargetSize materialTapTargetSize, @@ -138,6 +138,7 @@ class RaisedButton extends MaterialButton { assert(hoverElevation == null || hoverElevation >= 0.0), assert(highlightElevation == null || highlightElevation >= 0.0), assert(disabledElevation == null || disabledElevation >= 0.0), + assert(clipBehavior != null), super( key: key, onPressed: onPressed, @@ -209,7 +210,7 @@ class RaisedButton extends MaterialButton { return RawMaterialButton( onPressed: onPressed, onHighlightChanged: onHighlightChanged, - clipBehavior: clipBehavior ?? Clip.none, + clipBehavior: clipBehavior, fillColor: buttonTheme.getFillColor(this), textStyle: theme.textTheme.button.copyWith(color: buttonTheme.getTextColor(this)), focusColor: buttonTheme.getFocusColor(this), @@ -276,6 +277,7 @@ class _RaisedButtonWithIcon extends RaisedButton with MaterialButtonWithIconMixi }) : assert(elevation == null || elevation >= 0.0), assert(highlightElevation == null || highlightElevation >= 0.0), assert(disabledElevation == null || disabledElevation >= 0.0), + assert(clipBehavior != null), assert(icon != null), assert(label != null), assert(autofocus != null), diff --git a/packages/flutter/lib/src/rendering/layer.dart b/packages/flutter/lib/src/rendering/layer.dart index 32c324d0db..8321b0f927 100644 --- a/packages/flutter/lib/src/rendering/layer.dart +++ b/packages/flutter/lib/src/rendering/layer.dart @@ -1058,8 +1058,10 @@ class OffsetLayer extends ContainerLayer { class ClipRectLayer extends ContainerLayer { /// Creates a layer with a rectangular clip. /// - /// The [clipRect] and [clipBehavior] properties must be non-null before the - /// compositing phase of the pipeline. + /// The [clipRect] argument must not be null before the compositing phase of + /// the pipeline. + /// + /// The [clipBehavior] argument must not be null, and must not be [Clip.none]. ClipRectLayer({ Rect clipRect, Clip clipBehavior = Clip.hardEdge, @@ -1082,10 +1084,12 @@ class ClipRectLayer extends ContainerLayer { } /// {@template flutter.clipper.clipBehavior} - /// Controls how to clip (defaults to [Clip.hardEdge]). + /// Controls how to clip. /// - /// [Clip.none] is not allowed here. + /// Must not be set to null or [Clip.none]. /// {@endtemplate} + /// + /// Defaults to [Clip.hardEdge]. Clip get clipBehavior => _clipBehavior; Clip _clipBehavior; set clipBehavior(Clip value) { @@ -1170,6 +1174,8 @@ class ClipRRectLayer extends ContainerLayer { } /// {@macro flutter.clipper.clipBehavior} + /// + /// Defaults to [Clip.antiAlias]. Clip get clipBehavior => _clipBehavior; Clip _clipBehavior; set clipBehavior(Clip value) { @@ -1254,6 +1260,8 @@ class ClipPathLayer extends ContainerLayer { } /// {@macro flutter.clipper.clipBehavior} + /// + /// Defaults to [Clip.antiAlias]. Clip get clipBehavior => _clipBehavior; Clip _clipBehavior; set clipBehavior(Clip value) { diff --git a/packages/flutter/lib/src/rendering/proxy_box.dart b/packages/flutter/lib/src/rendering/proxy_box.dart index 308ec1f3a4..a54c7d94f4 100644 --- a/packages/flutter/lib/src/rendering/proxy_box.dart +++ b/packages/flutter/lib/src/rendering/proxy_box.dart @@ -1285,12 +1285,14 @@ class RenderClipRect extends _RenderCustomClip { /// If [clipper] is null, the clip will match the layout size and position of /// the child. /// - /// The [clipBehavior] cannot be [Clip.none]. + /// The [clipBehavior] must not be null or [Clip.none]. RenderClipRect({ RenderBox child, CustomClipper clipper, Clip clipBehavior = Clip.antiAlias, - }) : super(child: child, clipper: clipper, clipBehavior: clipBehavior); + }) : assert(clipBehavior != null), + assert(clipBehavior != Clip.none), + super(child: child, clipper: clipper, clipBehavior: clipBehavior); @override Rect get _defaultClip => Offset.zero & size; @@ -1342,13 +1344,14 @@ class RenderClipRRect extends _RenderCustomClip { /// /// If [clipper] is non-null, then [borderRadius] is ignored. /// - /// The [clipBehavior] cannot be [Clip.none]. + /// The [clipBehavior] argument must not be null or [Clip.none]. RenderClipRRect({ RenderBox child, BorderRadius borderRadius = BorderRadius.zero, CustomClipper clipper, Clip clipBehavior = Clip.antiAlias, - }) : assert(clipBehavior != Clip.none), + }) : assert(clipBehavior != null), + assert(clipBehavior != Clip.none), _borderRadius = borderRadius, super(child: child, clipper: clipper, clipBehavior: clipBehavior) { assert(_borderRadius != null || clipper != null); @@ -1418,12 +1421,13 @@ class RenderClipOval extends _RenderCustomClip { /// If [clipper] is null, the oval will be inscribed into the layout size and /// position of the child. /// - /// The [clipBehavior] cannot be [Clip.none]. + /// The [clipBehavior] argument must not be null or [Clip.none]. RenderClipOval({ RenderBox child, CustomClipper clipper, Clip clipBehavior = Clip.antiAlias, - }) : assert(clipBehavior != Clip.none), + }) : assert(clipBehavior != null), + assert(clipBehavior != Clip.none), super(child: child, clipper: clipper, clipBehavior: clipBehavior); Rect _cachedRect; @@ -1496,12 +1500,13 @@ class RenderClipPath extends _RenderCustomClip { /// consider using a [RenderClipRect], which can achieve the same effect more /// efficiently. /// - /// The [clipBehavior] cannot be [Clip.none]. + /// The [clipBehavior] argument must not be null or [Clip.none]. RenderClipPath({ RenderBox child, CustomClipper clipper, Clip clipBehavior = Clip.antiAlias, - }) : assert(clipBehavior != Clip.none), + }) : assert(clipBehavior != null), + assert(clipBehavior != Clip.none), super(child: child, clipper: clipper, clipBehavior: clipBehavior); @override @@ -1632,8 +1637,9 @@ class RenderPhysicalModel extends _RenderPhysicalModelBase { /// /// The [color] is required. /// - /// The [shape], [elevation], [color], and [shadowColor] must not be null. - /// Additionally, the [elevation] must be non-negative. + /// The [shape], [elevation], [color], [clipBehavior], and [shadowColor] + /// arguments must not be null. Additionally, the [elevation] must be + /// non-negative. RenderPhysicalModel({ RenderBox child, BoxShape shape = BoxShape.rectangle, diff --git a/packages/flutter/lib/src/widgets/basic.dart b/packages/flutter/lib/src/widgets/basic.dart index c06e93cb06..d606c958a8 100644 --- a/packages/flutter/lib/src/widgets/basic.dart +++ b/packages/flutter/lib/src/widgets/basic.dart @@ -582,19 +582,29 @@ class ClipRect extends SingleChildRenderObjectWidget { /// /// If [clipper] is null, the clip will match the layout size and position of /// the child. - const ClipRect({ Key key, this.clipper, this.clipBehavior = Clip.hardEdge, Widget child }) : super(key: key, child: child); + /// + /// The [clipBehavior] argument must not be null or [Clip.none]. + const ClipRect({ Key key, this.clipper, this.clipBehavior = Clip.hardEdge, Widget child }) + : assert(clipBehavior != null), + super(key: key, child: child); /// If non-null, determines which clip to use. final CustomClipper clipper; /// {@macro flutter.clipper.clipBehavior} + /// + /// Defaults to [Clip.hardEdge]. final Clip clipBehavior; @override - RenderClipRect createRenderObject(BuildContext context) => RenderClipRect(clipper: clipper, clipBehavior: clipBehavior); + RenderClipRect createRenderObject(BuildContext context) { + assert(clipBehavior != Clip.none); + return RenderClipRect(clipper: clipper, clipBehavior: clipBehavior); + } @override void updateRenderObject(BuildContext context, RenderClipRect renderObject) { + assert(clipBehavior != Clip.none); renderObject ..clipper = clipper ..clipBehavior = clipBehavior; @@ -633,6 +643,8 @@ class ClipRRect extends SingleChildRenderObjectWidget { /// right-angled corners. /// /// If [clipper] is non-null, then [borderRadius] is ignored. + /// + /// The [clipBehavior] argument must not be null or [Clip.none]. const ClipRRect({ Key key, this.borderRadius, @@ -655,13 +667,19 @@ class ClipRRect extends SingleChildRenderObjectWidget { final CustomClipper clipper; /// {@macro flutter.clipper.clipBehavior} + /// + /// Defaults to [Clip.antiAlias]. final Clip clipBehavior; @override - RenderClipRRect createRenderObject(BuildContext context) => RenderClipRRect(borderRadius: borderRadius, clipper: clipper, clipBehavior: clipBehavior); + RenderClipRRect createRenderObject(BuildContext context) { + assert(clipBehavior != Clip.none); + return RenderClipRRect(borderRadius: borderRadius, clipper: clipper, clipBehavior: clipBehavior); + } @override void updateRenderObject(BuildContext context, RenderClipRRect renderObject) { + assert(clipBehavior != Clip.none); renderObject ..borderRadius = borderRadius ..clipBehavior = clipBehavior @@ -693,7 +711,11 @@ class ClipOval extends SingleChildRenderObjectWidget { /// /// If [clipper] is null, the oval will be inscribed into the layout size and /// position of the child. - const ClipOval({ Key key, this.clipper, this.clipBehavior = Clip.antiAlias, Widget child }) : super(key: key, child: child); + /// + /// The [clipBehavior] argument must not be null or [Clip.none]. + const ClipOval({Key key, this.clipper, this.clipBehavior = Clip.antiAlias, Widget child}) + : assert(clipBehavior != null), + super(key: key, child: child); /// If non-null, determines which clip to use. /// @@ -707,13 +729,19 @@ class ClipOval extends SingleChildRenderObjectWidget { final CustomClipper clipper; /// {@macro flutter.clipper.clipBehavior} + /// + /// Defaults to [Clip.antiAlias]. final Clip clipBehavior; @override - RenderClipOval createRenderObject(BuildContext context) => RenderClipOval(clipper: clipper, clipBehavior: clipBehavior); + RenderClipOval createRenderObject(BuildContext context) { + assert(clipBehavior != Clip.none); + return RenderClipOval(clipper: clipper, clipBehavior: clipBehavior); + } @override void updateRenderObject(BuildContext context, RenderClipOval renderObject) { + assert(clipBehavior != Clip.none); renderObject ..clipper = clipper ..clipBehavior = clipBehavior; @@ -754,12 +782,15 @@ class ClipPath extends SingleChildRenderObjectWidget { /// size and location of the child. However, rather than use this default, /// consider using a [ClipRect], which can achieve the same effect more /// efficiently. + /// + /// The [clipBehavior] argument must not be null or [Clip.none]. const ClipPath({ Key key, this.clipper, this.clipBehavior = Clip.antiAlias, Widget child, - }) : super(key: key, child: child); + }) : assert(clipBehavior != null), + super(key: key, child: child); /// Creates a shape clip. /// @@ -771,6 +802,8 @@ class ClipPath extends SingleChildRenderObjectWidget { Clip clipBehavior = Clip.antiAlias, Widget child, }) { + assert(clipBehavior != null); + assert(clipBehavior != Clip.none); assert(shape != null); return Builder( key: key, @@ -795,13 +828,19 @@ class ClipPath extends SingleChildRenderObjectWidget { final CustomClipper clipper; /// {@macro flutter.clipper.clipBehavior} + /// + /// Defaults to [Clip.antiAlias]. final Clip clipBehavior; @override - RenderClipPath createRenderObject(BuildContext context) => RenderClipPath(clipper: clipper, clipBehavior: clipBehavior); + RenderClipPath createRenderObject(BuildContext context) { + assert(clipBehavior != Clip.none); + return RenderClipPath(clipper: clipper, clipBehavior: clipBehavior); + } @override void updateRenderObject(BuildContext context, RenderClipPath renderObject) { + assert(clipBehavior != Clip.none); renderObject ..clipper = clipper ..clipBehavior = clipBehavior; @@ -838,8 +877,8 @@ class PhysicalModel extends SingleChildRenderObjectWidget { /// /// The [color] is required; physical things have a color. /// - /// The [shape], [elevation], [color], and [shadowColor] must not be null. - /// Additionally, the [elevation] must be non-negative. + /// The [shape], [elevation], [color], [clipBehavior], and [shadowColor] must + /// not be null. Additionally, the [elevation] must be non-negative. const PhysicalModel({ Key key, this.shape = BoxShape.rectangle, @@ -853,12 +892,15 @@ class PhysicalModel extends SingleChildRenderObjectWidget { assert(elevation != null && elevation >= 0.0), assert(color != null), assert(shadowColor != null), + assert(clipBehavior != null), super(key: key, child: child); /// The type of shape. final BoxShape shape; /// {@macro flutter.widgets.Clip} + /// + /// Defaults to [Clip.none]. final Clip clipBehavior; /// The border radius of the rounded corners. @@ -931,8 +973,8 @@ class PhysicalShape extends SingleChildRenderObjectWidget { /// /// The [color] is required; physical things have a color. /// - /// The [clipper], [elevation], [color], and [shadowColor] must not be null. - /// Additionally, the [elevation] must be non-negative. + /// The [clipper], [elevation], [color], [clipBehavior], and [shadowColor] + /// must not be null. Additionally, the [elevation] must be non-negative. const PhysicalShape({ Key key, @required this.clipper, @@ -956,6 +998,8 @@ class PhysicalShape extends SingleChildRenderObjectWidget { final CustomClipper clipper; /// {@macro flutter.widgets.Clip} + /// + /// Defaults to [Clip.none]. final Clip clipBehavior; /// The z-coordinate relative to the parent at which to place this physical diff --git a/packages/flutter/lib/src/widgets/implicit_animations.dart b/packages/flutter/lib/src/widgets/implicit_animations.dart index 0667368604..4631ce4718 100644 --- a/packages/flutter/lib/src/widgets/implicit_animations.dart +++ b/packages/flutter/lib/src/widgets/implicit_animations.dart @@ -1450,9 +1450,9 @@ class _AnimatedDefaultTextStyleState extends AnimatedWidgetBaseState(find.byType(Material)).clipBehavior, Clip.antiAlias); }); + + testWidgets('Card clipBehavior property defers to theme when null', (WidgetTester tester) async { + await tester.pumpWidget(Builder(builder: (BuildContext context) { + final ThemeData themeData = Theme.of(context); + return Theme( + data: themeData.copyWith( + cardTheme: themeData.cardTheme.copyWith( + clipBehavior: Clip.antiAliasWithSaveLayer, + ), + ), + child: const Card(clipBehavior: null), + ); + })); + expect(tester.widget(find.byType(Material)).clipBehavior, Clip.antiAliasWithSaveLayer); + }); } diff --git a/packages/flutter/test/material/material_test.dart b/packages/flutter/test/material/material_test.dart index d3afca7086..2cc7f826e1 100644 --- a/packages/flutter/test/material/material_test.dart +++ b/packages/flutter/test/material/material_test.dart @@ -300,6 +300,22 @@ void main() { expect(find.byKey(materialKey), hasNoImmediateClip); }); + testWidgets('Null clipBehavior asserts', (WidgetTester tester) async { + final GlobalKey materialKey = GlobalKey(); + Future doPump() async { + await tester.pumpWidget( + Material( + key: materialKey, + type: MaterialType.transparency, + child: const SizedBox(width: 100.0, height: 100.0), + clipBehavior: null, + ) + ); + } + + expect(() async => doPump(), throwsAssertionError); + }); + testWidgets('clips to bounding rect by default given Clip.antiAlias', (WidgetTester tester) async { final GlobalKey materialKey = GlobalKey(); await tester.pumpWidget(