Skip to content

Commit ee3557a

Browse files
Refactor Material build method (#147430)
Only a code quality change, improves readability using `switch`.
1 parent df95cb2 commit ee3557a

File tree

1 file changed

+37
-92
lines changed

1 file changed

+37
-92
lines changed

packages/flutter/lib/src/material/material.dart

Lines changed: 37 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -431,38 +431,24 @@ class Material extends StatefulWidget {
431431
class _MaterialState extends State<Material> with TickerProviderStateMixin {
432432
final GlobalKey _inkFeatureRenderer = GlobalKey(debugLabel: 'ink renderer');
433433

434-
Color? _getBackgroundColor(BuildContext context) {
435-
final ThemeData theme = Theme.of(context);
436-
Color? color = widget.color;
437-
if (color == null) {
438-
switch (widget.type) {
439-
case MaterialType.canvas:
440-
color = theme.canvasColor;
441-
case MaterialType.card:
442-
color = theme.cardColor;
443-
case MaterialType.button:
444-
case MaterialType.circle:
445-
case MaterialType.transparency:
446-
break;
447-
}
448-
}
449-
return color;
450-
}
451-
452434
@override
453435
Widget build(BuildContext context) {
454436
final ThemeData theme = Theme.of(context);
455-
final Color? backgroundColor = _getBackgroundColor(context);
456-
final Color modelShadowColor = widget.shadowColor ?? (theme.useMaterial3 ? theme.colorScheme.shadow : theme.shadowColor);
457-
// If no shadow color is specified, use 0 for elevation in the model so a drop shadow won't be painted.
458-
final double modelElevation = widget.elevation;
437+
final Color? backgroundColor = widget.color ?? switch (widget.type) {
438+
MaterialType.canvas => theme.canvasColor,
439+
MaterialType.card => theme.cardColor,
440+
MaterialType.button || MaterialType.circle || MaterialType.transparency => null,
441+
};
442+
final Color modelShadowColor = widget.shadowColor
443+
?? (theme.useMaterial3 ? theme.colorScheme.shadow : theme.shadowColor);
459444
assert(
460445
backgroundColor != null || widget.type == MaterialType.transparency,
461446
'If Material type is not MaterialType.transparency, a color must '
462447
'either be passed in through the `color` property, or be defined '
463448
'in the theme (ex. canvasColor != null if type is set to '
464449
'MaterialType.canvas)',
465450
);
451+
466452
Widget? contents = widget.child;
467453
if (contents != null) {
468454
contents = AnimatedDefaultTextStyle(
@@ -486,6 +472,10 @@ class _MaterialState extends State<Material> with TickerProviderStateMixin {
486472
),
487473
);
488474

475+
ShapeBorder? shape = widget.borderRadius != null
476+
? RoundedRectangleBorder(borderRadius: widget.borderRadius!)
477+
: widget.shape;
478+
489479
// PhysicalModel has a temporary workaround for a performance issue that
490480
// speeds up rectangular non transparent material (the workaround is to
491481
// skip the call to ui.Canvas.saveLayer if the border radius is 0).
@@ -495,31 +485,39 @@ class _MaterialState extends State<Material> with TickerProviderStateMixin {
495485
// specified rectangles (e.g shape RoundedRectangleBorder with radius 0, but
496486
// we choose not to as we want the change from the fast-path to the
497487
// slow-path to be noticeable in the construction site of Material.
498-
if (widget.type == MaterialType.canvas && widget.shape == null && widget.borderRadius == null) {
499-
final Color color = Theme.of(context).useMaterial3
488+
if (widget.type == MaterialType.canvas && shape == null) {
489+
final Color color = theme.useMaterial3
500490
? ElevationOverlay.applySurfaceTint(backgroundColor!, widget.surfaceTintColor, widget.elevation)
501491
: ElevationOverlay.applyOverlay(context, backgroundColor!, widget.elevation);
502492

503493
return AnimatedPhysicalModel(
504494
curve: Curves.fastOutSlowIn,
505495
duration: widget.animationDuration,
506496
clipBehavior: widget.clipBehavior,
507-
elevation: modelElevation,
497+
elevation: widget.elevation,
508498
color: color,
509499
shadowColor: modelShadowColor,
510500
animateColor: false,
511501
child: contents,
512502
);
513503
}
514504

515-
final ShapeBorder shape = _getShape();
505+
shape ??= switch (widget.type) {
506+
MaterialType.circle => const CircleBorder(),
507+
MaterialType.canvas || MaterialType.transparency => const RoundedRectangleBorder(),
508+
MaterialType.card || MaterialType.button => const RoundedRectangleBorder(
509+
borderRadius: BorderRadius.all(Radius.circular(2.0)),
510+
),
511+
};
516512

517513
if (widget.type == MaterialType.transparency) {
518-
return _transparentInterior(
519-
context: context,
520-
shape: shape,
514+
return ClipPath(
515+
clipper: ShapeBorderClipper(
516+
shape: shape,
517+
textDirection: Directionality.maybeOf(context),
518+
),
521519
clipBehavior: widget.clipBehavior,
522-
contents: contents,
520+
child: _ShapeBorderPaint(shape: shape, child: contents),
523521
);
524522
}
525523

@@ -536,56 +534,6 @@ class _MaterialState extends State<Material> with TickerProviderStateMixin {
536534
child: contents,
537535
);
538536
}
539-
540-
static Widget _transparentInterior({
541-
required BuildContext context,
542-
required ShapeBorder shape,
543-
required Clip clipBehavior,
544-
required Widget contents,
545-
}) {
546-
final _ShapeBorderPaint child = _ShapeBorderPaint(
547-
shape: shape,
548-
child: contents,
549-
);
550-
return ClipPath(
551-
clipper: ShapeBorderClipper(
552-
shape: shape,
553-
textDirection: Directionality.maybeOf(context),
554-
),
555-
clipBehavior: clipBehavior,
556-
child: child,
557-
);
558-
}
559-
560-
// Determines the shape for this Material.
561-
//
562-
// If a shape was specified, it will determine the shape.
563-
// If a borderRadius was specified, the shape is a rounded
564-
// rectangle.
565-
// Otherwise, the shape is determined by the widget type as described in the
566-
// Material class documentation.
567-
ShapeBorder _getShape() {
568-
if (widget.shape != null) {
569-
return widget.shape!;
570-
}
571-
if (widget.borderRadius != null) {
572-
return RoundedRectangleBorder(borderRadius: widget.borderRadius!);
573-
}
574-
switch (widget.type) {
575-
case MaterialType.canvas:
576-
case MaterialType.transparency:
577-
return const RoundedRectangleBorder();
578-
579-
case MaterialType.card:
580-
case MaterialType.button:
581-
return RoundedRectangleBorder(
582-
borderRadius: widget.borderRadius ?? kMaterialEdges[widget.type]!,
583-
);
584-
585-
case MaterialType.circle:
586-
return const CircleBorder();
587-
}
588-
}
589537
}
590538

591539
class _RenderInkFeatures extends RenderProxyBox implements MaterialInkController {
@@ -899,7 +847,7 @@ class _MaterialInterior extends ImplicitlyAnimatedWidget {
899847
final Color color;
900848

901849
/// The target shadow color.
902-
final Color? shadowColor;
850+
final Color shadowColor;
903851

904852
/// The target surface tint color.
905853
final Color? surfaceTintColor;
@@ -930,13 +878,11 @@ class _MaterialInteriorState extends AnimatedWidgetBaseState<_MaterialInterior>
930878
widget.elevation,
931879
(dynamic value) => Tween<double>(begin: value as double),
932880
) as Tween<double>?;
933-
_shadowColor = widget.shadowColor != null
934-
? visitor(
935-
_shadowColor,
936-
widget.shadowColor,
937-
(dynamic value) => ColorTween(begin: value as Color),
938-
) as ColorTween?
939-
: null;
881+
_shadowColor = visitor(
882+
_shadowColor,
883+
widget.shadowColor,
884+
(dynamic value) => ColorTween(begin: value as Color),
885+
) as ColorTween?;
940886
_surfaceTintColor = widget.surfaceTintColor != null
941887
? visitor(
942888
_surfaceTintColor,
@@ -958,16 +904,15 @@ class _MaterialInteriorState extends AnimatedWidgetBaseState<_MaterialInterior>
958904
final Color color = Theme.of(context).useMaterial3
959905
? ElevationOverlay.applySurfaceTint(widget.color, _surfaceTintColor?.evaluate(animation), elevation)
960906
: ElevationOverlay.applyOverlay(context, widget.color, elevation);
961-
// If no shadow color is specified, use 0 for elevation in the model so a drop shadow won't be painted.
962-
final double modelElevation = widget.shadowColor != null ? elevation : 0;
963-
final Color shadowColor = _shadowColor?.evaluate(animation) ?? const Color(0x00000000);
907+
final Color shadowColor = _shadowColor!.evaluate(animation)!;
908+
964909
return PhysicalShape(
965910
clipper: ShapeBorderClipper(
966911
shape: shape,
967912
textDirection: Directionality.maybeOf(context),
968913
),
969914
clipBehavior: widget.clipBehavior,
970-
elevation: modelElevation,
915+
elevation: elevation,
971916
color: color,
972917
shadowColor: shadowColor,
973918
child: _ShapeBorderPaint(

0 commit comments

Comments
 (0)