Refactor Material build method (#147430)

Only a code quality change, improves readability using `switch`.
This commit is contained in:
Nate 2024-05-30 11:54:17 -06:00 committed by GitHub
parent df95cb2984
commit ee3557afe0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -431,31 +431,16 @@ class Material extends StatefulWidget {
class _MaterialState extends State<Material> with TickerProviderStateMixin {
final GlobalKey _inkFeatureRenderer = GlobalKey(debugLabel: 'ink renderer');
Color? _getBackgroundColor(BuildContext context) {
final ThemeData theme = Theme.of(context);
Color? color = widget.color;
if (color == null) {
switch (widget.type) {
case MaterialType.canvas:
color = theme.canvasColor;
case MaterialType.card:
color = theme.cardColor;
case MaterialType.button:
case MaterialType.circle:
case MaterialType.transparency:
break;
}
}
return color;
}
@override
Widget build(BuildContext context) {
final ThemeData theme = Theme.of(context);
final Color? backgroundColor = _getBackgroundColor(context);
final Color modelShadowColor = widget.shadowColor ?? (theme.useMaterial3 ? theme.colorScheme.shadow : theme.shadowColor);
// If no shadow color is specified, use 0 for elevation in the model so a drop shadow won't be painted.
final double modelElevation = widget.elevation;
final Color? backgroundColor = widget.color ?? switch (widget.type) {
MaterialType.canvas => theme.canvasColor,
MaterialType.card => theme.cardColor,
MaterialType.button || MaterialType.circle || MaterialType.transparency => null,
};
final Color modelShadowColor = widget.shadowColor
?? (theme.useMaterial3 ? theme.colorScheme.shadow : theme.shadowColor);
assert(
backgroundColor != null || widget.type == MaterialType.transparency,
'If Material type is not MaterialType.transparency, a color must '
@ -463,6 +448,7 @@ class _MaterialState extends State<Material> with TickerProviderStateMixin {
'in the theme (ex. canvasColor != null if type is set to '
'MaterialType.canvas)',
);
Widget? contents = widget.child;
if (contents != null) {
contents = AnimatedDefaultTextStyle(
@ -486,6 +472,10 @@ class _MaterialState extends State<Material> with TickerProviderStateMixin {
),
);
ShapeBorder? shape = widget.borderRadius != null
? RoundedRectangleBorder(borderRadius: widget.borderRadius!)
: widget.shape;
// PhysicalModel has a temporary workaround for a performance issue that
// speeds up rectangular non transparent material (the workaround is to
// skip the call to ui.Canvas.saveLayer if the border radius is 0).
@ -495,8 +485,8 @@ class _MaterialState extends State<Material> with TickerProviderStateMixin {
// specified rectangles (e.g shape RoundedRectangleBorder with radius 0, but
// we choose not to as we want the change from the fast-path to the
// slow-path to be noticeable in the construction site of Material.
if (widget.type == MaterialType.canvas && widget.shape == null && widget.borderRadius == null) {
final Color color = Theme.of(context).useMaterial3
if (widget.type == MaterialType.canvas && shape == null) {
final Color color = theme.useMaterial3
? ElevationOverlay.applySurfaceTint(backgroundColor!, widget.surfaceTintColor, widget.elevation)
: ElevationOverlay.applyOverlay(context, backgroundColor!, widget.elevation);
@ -504,7 +494,7 @@ class _MaterialState extends State<Material> with TickerProviderStateMixin {
curve: Curves.fastOutSlowIn,
duration: widget.animationDuration,
clipBehavior: widget.clipBehavior,
elevation: modelElevation,
elevation: widget.elevation,
color: color,
shadowColor: modelShadowColor,
animateColor: false,
@ -512,14 +502,22 @@ class _MaterialState extends State<Material> with TickerProviderStateMixin {
);
}
final ShapeBorder shape = _getShape();
shape ??= switch (widget.type) {
MaterialType.circle => const CircleBorder(),
MaterialType.canvas || MaterialType.transparency => const RoundedRectangleBorder(),
MaterialType.card || MaterialType.button => const RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(2.0)),
),
};
if (widget.type == MaterialType.transparency) {
return _transparentInterior(
context: context,
shape: shape,
return ClipPath(
clipper: ShapeBorderClipper(
shape: shape,
textDirection: Directionality.maybeOf(context),
),
clipBehavior: widget.clipBehavior,
contents: contents,
child: _ShapeBorderPaint(shape: shape, child: contents),
);
}
@ -536,56 +534,6 @@ class _MaterialState extends State<Material> with TickerProviderStateMixin {
child: contents,
);
}
static Widget _transparentInterior({
required BuildContext context,
required ShapeBorder shape,
required Clip clipBehavior,
required Widget contents,
}) {
final _ShapeBorderPaint child = _ShapeBorderPaint(
shape: shape,
child: contents,
);
return ClipPath(
clipper: ShapeBorderClipper(
shape: shape,
textDirection: Directionality.maybeOf(context),
),
clipBehavior: clipBehavior,
child: child,
);
}
// Determines the shape for this Material.
//
// If a shape was specified, it will determine the shape.
// If a borderRadius was specified, the shape is a rounded
// rectangle.
// Otherwise, the shape is determined by the widget type as described in the
// Material class documentation.
ShapeBorder _getShape() {
if (widget.shape != null) {
return widget.shape!;
}
if (widget.borderRadius != null) {
return RoundedRectangleBorder(borderRadius: widget.borderRadius!);
}
switch (widget.type) {
case MaterialType.canvas:
case MaterialType.transparency:
return const RoundedRectangleBorder();
case MaterialType.card:
case MaterialType.button:
return RoundedRectangleBorder(
borderRadius: widget.borderRadius ?? kMaterialEdges[widget.type]!,
);
case MaterialType.circle:
return const CircleBorder();
}
}
}
class _RenderInkFeatures extends RenderProxyBox implements MaterialInkController {
@ -899,7 +847,7 @@ class _MaterialInterior extends ImplicitlyAnimatedWidget {
final Color color;
/// The target shadow color.
final Color? shadowColor;
final Color shadowColor;
/// The target surface tint color.
final Color? surfaceTintColor;
@ -930,13 +878,11 @@ class _MaterialInteriorState extends AnimatedWidgetBaseState<_MaterialInterior>
widget.elevation,
(dynamic value) => Tween<double>(begin: value as double),
) as Tween<double>?;
_shadowColor = widget.shadowColor != null
? visitor(
_shadowColor,
widget.shadowColor,
(dynamic value) => ColorTween(begin: value as Color),
) as ColorTween?
: null;
_shadowColor = visitor(
_shadowColor,
widget.shadowColor,
(dynamic value) => ColorTween(begin: value as Color),
) as ColorTween?;
_surfaceTintColor = widget.surfaceTintColor != null
? visitor(
_surfaceTintColor,
@ -958,16 +904,15 @@ class _MaterialInteriorState extends AnimatedWidgetBaseState<_MaterialInterior>
final Color color = Theme.of(context).useMaterial3
? ElevationOverlay.applySurfaceTint(widget.color, _surfaceTintColor?.evaluate(animation), elevation)
: ElevationOverlay.applyOverlay(context, widget.color, elevation);
// If no shadow color is specified, use 0 for elevation in the model so a drop shadow won't be painted.
final double modelElevation = widget.shadowColor != null ? elevation : 0;
final Color shadowColor = _shadowColor?.evaluate(animation) ?? const Color(0x00000000);
final Color shadowColor = _shadowColor!.evaluate(animation)!;
return PhysicalShape(
clipper: ShapeBorderClipper(
shape: shape,
textDirection: Directionality.maybeOf(context),
),
clipBehavior: widget.clipBehavior,
elevation: modelElevation,
elevation: elevation,
color: color,
shadowColor: shadowColor,
child: _ShapeBorderPaint(