Add Card.filled
and Card.outlined
factory methods (#136229)
Fixes #119401 This PR is to: * add `Card.filled` and `Card.outlined` factory methods so that we can use tokens for these two types of cards to generate default theme instead of providing hard-corded values in example. * update card.2.dart example. * add test file for card.2.dart example. * fix some mismatch caused by editing the auto-generated defaults by hand in navigation_bar.dart and navigation_drawer.dart.
This commit is contained in:
parent
b47e4c4acb
commit
4a0f261b4e
@ -261,7 +261,7 @@ class SampleChecker {
|
||||
}
|
||||
}
|
||||
|
||||
// These tests are known to be missing. They should all eventually be
|
||||
// These tests are known to be missing. They should all eventually be
|
||||
// implemented, but until they are we allow them, so that we can catch any new
|
||||
// examples that are added without tests.
|
||||
//
|
||||
@ -282,7 +282,6 @@ final Set<String> _knownMissingTests = <String>{
|
||||
'examples/api/test/material/text_field/text_field.1_test.dart',
|
||||
'examples/api/test/material/button_style/button_style.0_test.dart',
|
||||
'examples/api/test/material/range_slider/range_slider.0_test.dart',
|
||||
'examples/api/test/material/card/card.2_test.dart',
|
||||
'examples/api/test/material/card/card.0_test.dart',
|
||||
'examples/api/test/material/selection_container/selection_container_disabled.0_test.dart',
|
||||
'examples/api/test/material/selection_container/selection_container.0_test.dart',
|
||||
|
@ -112,7 +112,9 @@ Future<void> main(List<String> args) async {
|
||||
ButtonTemplate('md.comp.filled-tonal-button', 'FilledTonalButton', '$materialLib/filled_button.dart', tokens).updateFile();
|
||||
ButtonTemplate('md.comp.outlined-button', 'OutlinedButton', '$materialLib/outlined_button.dart', tokens).updateFile();
|
||||
ButtonTemplate('md.comp.text-button', 'TextButton', '$materialLib/text_button.dart', tokens).updateFile();
|
||||
CardTemplate('Card', '$materialLib/card.dart', tokens).updateFile();
|
||||
CardTemplate('md.comp.elevated-card', 'Card', '$materialLib/card.dart', tokens).updateFile();
|
||||
CardTemplate('md.comp.filled-card', 'FilledCard', '$materialLib/card.dart', tokens).updateFile();
|
||||
CardTemplate('md.comp.outlined-card', 'OutlinedCard', '$materialLib/card.dart', tokens).updateFile();
|
||||
CheckboxTemplate('Checkbox', '$materialLib/checkbox.dart', tokens).updateFile();
|
||||
ColorSchemeTemplate(colorLightTokens, colorDarkTokens, 'ColorScheme', '$materialLib/theme_data.dart', tokens).updateFile();
|
||||
DatePickerTemplate('DatePicker', '$materialLib/date_picker_theme.dart', tokens).updateFile();
|
||||
|
@ -203,6 +203,10 @@ md.comp.filled-button.label-text.text-style,
|
||||
md.comp.filled-button.pressed.container.elevation,
|
||||
md.comp.filled-button.pressed.state-layer.color,
|
||||
md.comp.filled-button.pressed.state-layer.opacity,
|
||||
md.comp.filled-card.container.color,
|
||||
md.comp.filled-card.container.elevation,
|
||||
md.comp.filled-card.container.shadow-color,
|
||||
md.comp.filled-card.container.shape,
|
||||
md.comp.filled-icon-button.container.color,
|
||||
md.comp.filled-icon-button.container.shape,
|
||||
md.comp.filled-icon-button.container.size,
|
||||
@ -459,6 +463,13 @@ md.comp.outlined-button.outline.color,
|
||||
md.comp.outlined-button.outline.width,
|
||||
md.comp.outlined-button.pressed.state-layer.color,
|
||||
md.comp.outlined-button.pressed.state-layer.opacity,
|
||||
md.comp.outlined-card.container.color,
|
||||
md.comp.outlined-card.container.elevation,
|
||||
md.comp.outlined-card.container.shadow-color,
|
||||
md.comp.outlined-card.container.shape,
|
||||
md.comp.outlined-card.container.surface-tint-layer.color,
|
||||
md.comp.outlined-card.outline.color,
|
||||
md.comp.outlined-card.outline.width,
|
||||
md.comp.outlined-icon-button.container.shape,
|
||||
md.comp.outlined-icon-button.container.size,
|
||||
md.comp.outlined-icon-button.disabled.icon.color,
|
||||
|
|
@ -5,32 +5,49 @@
|
||||
import 'template.dart';
|
||||
|
||||
class CardTemplate extends TokenTemplate {
|
||||
const CardTemplate(super.blockName, super.fileName, super.tokens, {
|
||||
const CardTemplate(this.tokenGroup, super.blockName, super.fileName, super.tokens, {
|
||||
super.colorSchemePrefix = '_colors.',
|
||||
});
|
||||
|
||||
final String tokenGroup;
|
||||
|
||||
String _shape() {
|
||||
final String cardShape = shape('$tokenGroup.container');
|
||||
if (tokenAvailable('$tokenGroup.outline.color')) {
|
||||
return '''
|
||||
|
||||
$cardShape.copyWith(
|
||||
side: ${border('$tokenGroup.outline')}
|
||||
)''';
|
||||
} else {
|
||||
return cardShape;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
String generate() => '''
|
||||
class _${blockName}DefaultsM3 extends CardTheme {
|
||||
_${blockName}DefaultsM3(this.context)
|
||||
: super(
|
||||
clipBehavior: Clip.none,
|
||||
elevation: ${elevation("md.comp.elevated-card.container")},
|
||||
elevation: ${elevation('$tokenGroup.container')},
|
||||
margin: const EdgeInsets.all(4.0),
|
||||
shape: ${shape("md.comp.elevated-card.container")},
|
||||
);
|
||||
|
||||
final BuildContext context;
|
||||
late final ColorScheme _colors = Theme.of(context).colorScheme;
|
||||
|
||||
@override
|
||||
Color? get color => ${componentColor("md.comp.elevated-card.container")};
|
||||
Color? get color => ${componentColor('$tokenGroup.container')};
|
||||
|
||||
@override
|
||||
Color? get shadowColor => ${colorOrTransparent("md.comp.elevated-card.container.shadow-color")};
|
||||
Color? get shadowColor => ${colorOrTransparent('$tokenGroup.container.shadow-color')};
|
||||
|
||||
@override
|
||||
Color? get surfaceTintColor => ${colorOrTransparent("md.comp.elevated-card.container.surface-tint-layer.color")};
|
||||
Color? get surfaceTintColor => ${colorOrTransparent('$tokenGroup.container.surface-tint-layer.color')};
|
||||
|
||||
@override
|
||||
ShapeBorder? get shape =>${_shape()};
|
||||
}
|
||||
''';
|
||||
}
|
||||
|
@ -34,9 +34,11 @@ class _${blockName}DefaultsM3 extends NavigationBarThemeData {
|
||||
return MaterialStateProperty.resolveWith((Set<MaterialState> states) {
|
||||
return IconThemeData(
|
||||
size: ${getToken("md.comp.navigation-bar.icon.size")},
|
||||
color: states.contains(MaterialState.selected)
|
||||
? ${componentColor("md.comp.navigation-bar.active.icon")}
|
||||
: ${componentColor("md.comp.navigation-bar.inactive.icon")},
|
||||
color: states.contains(MaterialState.disabled)
|
||||
? _colors.onSurfaceVariant.withOpacity(0.38)
|
||||
: states.contains(MaterialState.selected)
|
||||
? ${componentColor("md.comp.navigation-bar.active.icon")}
|
||||
: ${componentColor("md.comp.navigation-bar.inactive.icon")},
|
||||
);
|
||||
});
|
||||
}
|
||||
@ -47,9 +49,12 @@ class _${blockName}DefaultsM3 extends NavigationBarThemeData {
|
||||
@override MaterialStateProperty<TextStyle?>? get labelTextStyle {
|
||||
return MaterialStateProperty.resolveWith((Set<MaterialState> states) {
|
||||
final TextStyle style = ${textStyle("md.comp.navigation-bar.label-text")}!;
|
||||
return style.apply(color: states.contains(MaterialState.selected)
|
||||
? ${componentColor("md.comp.navigation-bar.active.label-text")}
|
||||
: ${componentColor("md.comp.navigation-bar.inactive.label-text")}
|
||||
return style.apply(
|
||||
color: states.contains(MaterialState.disabled)
|
||||
? _colors.onSurfaceVariant.withOpacity(0.38)
|
||||
: states.contains(MaterialState.selected)
|
||||
? ${componentColor("md.comp.navigation-bar.active.label-text")}
|
||||
: ${componentColor("md.comp.navigation-bar.inactive.label-text")}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
@ -42,7 +42,9 @@ class _${blockName}DefaultsM3 extends NavigationDrawerThemeData {
|
||||
return MaterialStateProperty.resolveWith((Set<MaterialState> states) {
|
||||
return IconThemeData(
|
||||
size: ${getToken("md.comp.navigation-drawer.icon.size")},
|
||||
color: states.contains(MaterialState.selected)
|
||||
color: states.contains(MaterialState.disabled)
|
||||
? _colors.onSurfaceVariant.withOpacity(0.38)
|
||||
: states.contains(MaterialState.selected)
|
||||
? ${componentColor("md.comp.navigation-drawer.active.icon")}
|
||||
: ${componentColor("md.comp.navigation-drawer.inactive.icon")},
|
||||
);
|
||||
@ -54,7 +56,9 @@ class _${blockName}DefaultsM3 extends NavigationDrawerThemeData {
|
||||
return MaterialStateProperty.resolveWith((Set<MaterialState> states) {
|
||||
final TextStyle style = ${textStyle("md.comp.navigation-drawer.label-text")}!;
|
||||
return style.apply(
|
||||
color: states.contains(MaterialState.selected)
|
||||
color: states.contains(MaterialState.disabled)
|
||||
? _colors.onSurfaceVariant.withOpacity(0.38)
|
||||
: states.contains(MaterialState.selected)
|
||||
? ${componentColor("md.comp.navigation-drawer.active.label-text")}
|
||||
: ${componentColor("md.comp.navigation-drawer.inactive.label-text")},
|
||||
);
|
||||
|
@ -16,97 +16,33 @@ class CardExamplesApp extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MaterialApp(
|
||||
theme: ThemeData(colorSchemeSeed: const Color(0xff6750a4), useMaterial3: true),
|
||||
home: Scaffold(
|
||||
appBar: AppBar(title: const Text('Card Examples')),
|
||||
body: const Column(
|
||||
children: <Widget>[
|
||||
Spacer(),
|
||||
ElevatedCardExample(),
|
||||
FilledCardExample(),
|
||||
OutlinedCardExample(),
|
||||
Spacer(),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// An example of the elevated card type.
|
||||
///
|
||||
/// The default settings for [Card] will provide an elevated
|
||||
/// card matching the spec:
|
||||
///
|
||||
/// https://m3.material.io/components/cards/specs#a012d40d-7a5c-4b07-8740-491dec79d58b
|
||||
class ElevatedCardExample extends StatelessWidget {
|
||||
const ElevatedCardExample({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return const Center(
|
||||
child: Card(
|
||||
child: SizedBox(
|
||||
width: 300,
|
||||
height: 100,
|
||||
child: Center(child: Text('Elevated Card')),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// An example of the filled card type.
|
||||
///
|
||||
/// To make a [Card] match the filled type, the default elevation and color
|
||||
/// need to be changed to the values from the spec:
|
||||
///
|
||||
/// https://m3.material.io/components/cards/specs#0f55bf62-edf2-4619-b00d-b9ed462f2c5a
|
||||
class FilledCardExample extends StatelessWidget {
|
||||
const FilledCardExample({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Center(
|
||||
child: Card(
|
||||
elevation: 0,
|
||||
color: Theme.of(context).colorScheme.surfaceVariant,
|
||||
child: const SizedBox(
|
||||
width: 300,
|
||||
height: 100,
|
||||
child: Center(child: Text('Filled Card')),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// An example of the outlined card type.
|
||||
///
|
||||
/// To make a [Card] match the outlined type, the default elevation and shape
|
||||
/// need to be changed to the values from the spec:
|
||||
///
|
||||
/// https://m3.material.io/components/cards/specs#0f55bf62-edf2-4619-b00d-b9ed462f2c5a
|
||||
class OutlinedCardExample extends StatelessWidget {
|
||||
const OutlinedCardExample({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Center(
|
||||
child: Card(
|
||||
elevation: 0,
|
||||
shape: RoundedRectangleBorder(
|
||||
side: BorderSide(
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
body: const Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
Card(child: _SampleCard(cardName: 'Elevated Card')),
|
||||
Card.filled(child: _SampleCard(cardName: 'Filled Card')),
|
||||
Card.outlined(child: _SampleCard(cardName: 'Outlined Card')),
|
||||
],
|
||||
),
|
||||
borderRadius: const BorderRadius.all(Radius.circular(12)),
|
||||
),
|
||||
child: const SizedBox(
|
||||
width: 300,
|
||||
height: 100,
|
||||
child: Center(child: Text('Outlined Card')),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _SampleCard extends StatelessWidget {
|
||||
const _SampleCard({required this.cardName});
|
||||
final String cardName;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SizedBox(
|
||||
width: 300,
|
||||
height: 100,
|
||||
child: Center(child: Text(cardName)),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
59
examples/api/test/material/card/card.2_test.dart
Normal file
59
examples/api/test/material/card/card.2_test.dart
Normal file
@ -0,0 +1,59 @@
|
||||
// Copyright 2014 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_api_samples/material/card/card.2.dart' as example;
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
void main() {
|
||||
testWidgets('Card variants', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(const example.CardExamplesApp());
|
||||
|
||||
expect(find.byType(Card), findsNWidgets(3));
|
||||
|
||||
expect(find.widgetWithText(Card, 'Elevated Card'), findsOneWidget);
|
||||
expect(find.widgetWithText(Card, 'Filled Card'), findsOneWidget);
|
||||
expect(find.widgetWithText(Card, 'Outlined Card'), findsOneWidget);
|
||||
|
||||
Material getCardMaterial(WidgetTester tester, int cardIndex) {
|
||||
return tester.widget<Material>(
|
||||
find.descendant(
|
||||
of: find.byType(Card).at(cardIndex),
|
||||
matching: find.byType(Material),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
final Material defaultCard = getCardMaterial(tester, 0);
|
||||
expect(defaultCard.clipBehavior, Clip.none);
|
||||
expect(defaultCard.elevation, 1.0);
|
||||
expect(defaultCard.shape, const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(Radius.circular(12.0)),
|
||||
));
|
||||
expect(defaultCard.color, const Color(0xfffffbfe));
|
||||
expect(defaultCard.shadowColor, const Color(0xff000000));
|
||||
expect(defaultCard.surfaceTintColor, const Color(0xff6750a4));
|
||||
|
||||
final Material filledCard = getCardMaterial(tester, 1);
|
||||
expect(filledCard.clipBehavior, Clip.none);
|
||||
expect(filledCard.elevation, 0.0);
|
||||
expect(filledCard.shape, const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(Radius.circular(12.0)),
|
||||
));
|
||||
expect(filledCard.color, const Color(0xffe7e0ec));
|
||||
expect(filledCard.shadowColor, const Color(0xff000000));
|
||||
expect(filledCard.surfaceTintColor, const Color(0x00000000));
|
||||
|
||||
final Material outlinedCard = getCardMaterial(tester, 2);
|
||||
expect(outlinedCard.clipBehavior, Clip.none);
|
||||
expect(outlinedCard.elevation, 0.0);
|
||||
expect(outlinedCard.shape, const RoundedRectangleBorder(
|
||||
side: BorderSide(color: Color(0xffcac4d0)),
|
||||
borderRadius: BorderRadius.all(Radius.circular(12.0)),
|
||||
));
|
||||
expect(outlinedCard.color, const Color(0xfffffbfe));
|
||||
expect(outlinedCard.shadowColor, const Color(0xff000000));
|
||||
expect(outlinedCard.surfaceTintColor, const Color(0xff6750a4));
|
||||
});
|
||||
}
|
@ -6,9 +6,12 @@ import 'package:flutter/widgets.dart';
|
||||
|
||||
import 'card_theme.dart';
|
||||
import 'color_scheme.dart';
|
||||
import 'colors.dart';
|
||||
import 'material.dart';
|
||||
import 'theme.dart';
|
||||
|
||||
enum _CardVariant { elevated, filled, outlined }
|
||||
|
||||
/// A Material Design card: a panel with slightly rounded corners and an
|
||||
/// elevation shadow.
|
||||
///
|
||||
@ -39,9 +42,9 @@ import 'theme.dart';
|
||||
/// ** See code in examples/api/lib/material/card/card.1.dart **
|
||||
/// {@end-tool}
|
||||
///
|
||||
/// Material Design 3 introduced new types of cards. These can
|
||||
/// be produced by configuring the [Card] widget's properties.
|
||||
/// [Card] widget.
|
||||
/// Material Design 3 introduced new types of cards. The default [Card] is the
|
||||
/// elevated card. To create a filled card, use [Card.filled]; to create a outlined
|
||||
/// card, use [Card.outlined].
|
||||
/// {@tool dartpad}
|
||||
/// This sample shows creation of [Card] widgets for elevated, filled and
|
||||
/// outlined types, as described in: https://m3.material.io/components/cards/overview
|
||||
@ -71,7 +74,46 @@ class Card extends StatelessWidget {
|
||||
this.clipBehavior,
|
||||
this.child,
|
||||
this.semanticContainer = true,
|
||||
}) : assert(elevation == null || elevation >= 0.0);
|
||||
}) : assert(elevation == null || elevation >= 0.0),
|
||||
_variant = _CardVariant.elevated;
|
||||
|
||||
/// Create a filled variant of Card.
|
||||
///
|
||||
/// Filled cards provide subtle separation from the background. This has less
|
||||
/// emphasis than elevated(default) or outlined cards.
|
||||
const Card.filled({
|
||||
super.key,
|
||||
this.color,
|
||||
this.shadowColor,
|
||||
this.surfaceTintColor,
|
||||
this.elevation,
|
||||
this.shape,
|
||||
this.borderOnForeground = true,
|
||||
this.margin,
|
||||
this.clipBehavior,
|
||||
this.child,
|
||||
this.semanticContainer = true,
|
||||
}) : assert(elevation == null || elevation >= 0.0),
|
||||
_variant = _CardVariant.filled;
|
||||
|
||||
/// Create an outlined variant of Card.
|
||||
///
|
||||
/// Outlined cards have a visual boundary around the container. This can
|
||||
/// provide greater emphasis than the other types.
|
||||
const Card.outlined({
|
||||
super.key,
|
||||
this.color,
|
||||
this.shadowColor,
|
||||
this.surfaceTintColor,
|
||||
this.elevation,
|
||||
this.shape,
|
||||
this.borderOnForeground = true,
|
||||
this.margin,
|
||||
this.clipBehavior,
|
||||
this.child,
|
||||
this.semanticContainer = true,
|
||||
}) : assert(elevation == null || elevation >= 0.0),
|
||||
_variant = _CardVariant.outlined;
|
||||
|
||||
/// The card's background color.
|
||||
///
|
||||
@ -164,10 +206,24 @@ class Card extends StatelessWidget {
|
||||
/// {@macro flutter.widgets.ProxyWidget.child}
|
||||
final Widget? child;
|
||||
|
||||
final _CardVariant _variant;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final CardTheme cardTheme = CardTheme.of(context);
|
||||
final CardTheme defaults = Theme.of(context).useMaterial3 ? _CardDefaultsM3(context) : _CardDefaultsM2(context);
|
||||
final CardTheme defaults;
|
||||
if (Theme.of(context).useMaterial3) {
|
||||
switch (_variant) {
|
||||
case _CardVariant.elevated:
|
||||
defaults = _CardDefaultsM3(context);
|
||||
case _CardVariant.filled:
|
||||
defaults = _FilledCardDefaultsM3(context);
|
||||
case _CardVariant.outlined:
|
||||
defaults = _OutlinedCardDefaultsM3(context);
|
||||
}
|
||||
} else {
|
||||
defaults = _CardDefaultsM2(context);
|
||||
}
|
||||
|
||||
return Semantics(
|
||||
container: semanticContainer,
|
||||
@ -226,7 +282,6 @@ class _CardDefaultsM3 extends CardTheme {
|
||||
clipBehavior: Clip.none,
|
||||
elevation: 1.0,
|
||||
margin: const EdgeInsets.all(4.0),
|
||||
shape: const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(12.0))),
|
||||
);
|
||||
|
||||
final BuildContext context;
|
||||
@ -240,6 +295,78 @@ class _CardDefaultsM3 extends CardTheme {
|
||||
|
||||
@override
|
||||
Color? get surfaceTintColor => _colors.surfaceTint;
|
||||
|
||||
@override
|
||||
ShapeBorder? get shape =>const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(12.0)));
|
||||
}
|
||||
|
||||
// END GENERATED TOKEN PROPERTIES - Card
|
||||
|
||||
// BEGIN GENERATED TOKEN PROPERTIES - FilledCard
|
||||
|
||||
// Do not edit by hand. The code between the "BEGIN GENERATED" and
|
||||
// "END GENERATED" comments are generated from data in the Material
|
||||
// Design token database by the script:
|
||||
// dev/tools/gen_defaults/bin/gen_defaults.dart.
|
||||
|
||||
class _FilledCardDefaultsM3 extends CardTheme {
|
||||
_FilledCardDefaultsM3(this.context)
|
||||
: super(
|
||||
clipBehavior: Clip.none,
|
||||
elevation: 0.0,
|
||||
margin: const EdgeInsets.all(4.0),
|
||||
);
|
||||
|
||||
final BuildContext context;
|
||||
late final ColorScheme _colors = Theme.of(context).colorScheme;
|
||||
|
||||
@override
|
||||
Color? get color => _colors.surfaceVariant;
|
||||
|
||||
@override
|
||||
Color? get shadowColor => _colors.shadow;
|
||||
|
||||
@override
|
||||
Color? get surfaceTintColor => Colors.transparent;
|
||||
|
||||
@override
|
||||
ShapeBorder? get shape =>const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(12.0)));
|
||||
}
|
||||
|
||||
// END GENERATED TOKEN PROPERTIES - FilledCard
|
||||
|
||||
// BEGIN GENERATED TOKEN PROPERTIES - OutlinedCard
|
||||
|
||||
// Do not edit by hand. The code between the "BEGIN GENERATED" and
|
||||
// "END GENERATED" comments are generated from data in the Material
|
||||
// Design token database by the script:
|
||||
// dev/tools/gen_defaults/bin/gen_defaults.dart.
|
||||
|
||||
class _OutlinedCardDefaultsM3 extends CardTheme {
|
||||
_OutlinedCardDefaultsM3(this.context)
|
||||
: super(
|
||||
clipBehavior: Clip.none,
|
||||
elevation: 0.0,
|
||||
margin: const EdgeInsets.all(4.0),
|
||||
);
|
||||
|
||||
final BuildContext context;
|
||||
late final ColorScheme _colors = Theme.of(context).colorScheme;
|
||||
|
||||
@override
|
||||
Color? get color => _colors.surface;
|
||||
|
||||
@override
|
||||
Color? get shadowColor => _colors.shadow;
|
||||
|
||||
@override
|
||||
Color? get surfaceTintColor => _colors.surfaceTint;
|
||||
|
||||
@override
|
||||
ShapeBorder? get shape =>
|
||||
const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(12.0))).copyWith(
|
||||
side: BorderSide(color: _colors.outlineVariant)
|
||||
);
|
||||
}
|
||||
|
||||
// END GENERATED TOKEN PROPERTIES - OutlinedCard
|
||||
|
@ -1364,9 +1364,10 @@ class _NavigationBarDefaultsM3 extends NavigationBarThemeData {
|
||||
@override MaterialStateProperty<TextStyle?>? get labelTextStyle {
|
||||
return MaterialStateProperty.resolveWith((Set<MaterialState> states) {
|
||||
final TextStyle style = _textTheme.labelMedium!;
|
||||
return style.apply(color: states.contains(MaterialState.disabled)
|
||||
? _colors.onSurfaceVariant.withOpacity(0.38)
|
||||
: states.contains(MaterialState.selected)
|
||||
return style.apply(
|
||||
color: states.contains(MaterialState.disabled)
|
||||
? _colors.onSurfaceVariant.withOpacity(0.38)
|
||||
: states.contains(MaterialState.selected)
|
||||
? _colors.onSurface
|
||||
: _colors.onSurfaceVariant
|
||||
);
|
||||
|
@ -9,6 +9,79 @@ import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
|
||||
import '../widgets/semantics_tester.dart';
|
||||
|
||||
void main() {
|
||||
testWidgetsWithLeakTracking('Material3 - Card defaults (Elevated card)', (WidgetTester tester) async {
|
||||
final ThemeData theme = ThemeData();
|
||||
final ColorScheme colors = theme.colorScheme;
|
||||
await tester.pumpWidget(MaterialApp(
|
||||
theme: theme,
|
||||
home: const Scaffold(
|
||||
body: Card(),
|
||||
),
|
||||
));
|
||||
|
||||
final Container container = _getCardContainer(tester);
|
||||
final Material material = _getCardMaterial(tester);
|
||||
|
||||
expect(material.clipBehavior, Clip.none);
|
||||
expect(material.elevation, 1.0);
|
||||
expect(container.margin, const EdgeInsets.all(4.0));
|
||||
expect(material.color, colors.surface);
|
||||
expect(material.shadowColor, colors.shadow);
|
||||
expect(material.surfaceTintColor, colors.surfaceTint); // Default primary color
|
||||
expect(material.shape, const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(Radius.circular(12.0)),
|
||||
));
|
||||
});
|
||||
|
||||
testWidgetsWithLeakTracking('Material3 - Card.filled defaults', (WidgetTester tester) async {
|
||||
final ThemeData theme = ThemeData();
|
||||
final ColorScheme colors = theme.colorScheme;
|
||||
await tester.pumpWidget(MaterialApp(
|
||||
theme: theme,
|
||||
home: const Scaffold(
|
||||
body: Card.filled(),
|
||||
),
|
||||
));
|
||||
|
||||
final Container container = _getCardContainer(tester);
|
||||
final Material material = _getCardMaterial(tester);
|
||||
|
||||
expect(material.clipBehavior, Clip.none);
|
||||
expect(material.elevation, 0.0);
|
||||
expect(container.margin, const EdgeInsets.all(4.0));
|
||||
expect(material.color, colors.surfaceVariant);
|
||||
expect(material.shadowColor, colors.shadow);
|
||||
expect(material.surfaceTintColor, Colors.transparent);
|
||||
expect(material.shape, const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(Radius.circular(12.0)),
|
||||
));
|
||||
});
|
||||
|
||||
testWidgetsWithLeakTracking('Material3 - Card.outlined defaults', (WidgetTester tester) async {
|
||||
final ThemeData theme = ThemeData();
|
||||
final ColorScheme colors = theme.colorScheme;
|
||||
await tester.pumpWidget(MaterialApp(
|
||||
theme: theme,
|
||||
home: const Scaffold(
|
||||
body: Card.outlined(),
|
||||
),
|
||||
));
|
||||
|
||||
final Container container = _getCardContainer(tester);
|
||||
final Material material = _getCardMaterial(tester);
|
||||
|
||||
expect(material.clipBehavior, Clip.none);
|
||||
expect(material.elevation, 0.0);
|
||||
expect(container.margin, const EdgeInsets.all(4.0));
|
||||
expect(material.color, colors.surface);
|
||||
expect(material.shadowColor, colors.shadow);
|
||||
expect(material.surfaceTintColor, colors.surfaceTint);
|
||||
expect(material.shape, RoundedRectangleBorder(
|
||||
side: BorderSide(color: colors.outlineVariant),
|
||||
borderRadius: const BorderRadius.all(Radius.circular(12.0)),
|
||||
));
|
||||
});
|
||||
|
||||
testWidgetsWithLeakTracking('Card can take semantic text from multiple children', (WidgetTester tester) async {
|
||||
final SemanticsTester semantics = SemanticsTester(tester);
|
||||
await tester.pumpWidget(
|
||||
@ -219,3 +292,21 @@ void main() {
|
||||
expect(getCardMaterial(tester).shadowColor, Colors.red);
|
||||
});
|
||||
}
|
||||
|
||||
Material _getCardMaterial(WidgetTester tester) {
|
||||
return tester.widget<Material>(
|
||||
find.descendant(
|
||||
of: find.byType(Card),
|
||||
matching: find.byType(Material),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Container _getCardContainer(WidgetTester tester) {
|
||||
return tester.widget<Container>(
|
||||
find.descendant(
|
||||
of: find.byType(Card),
|
||||
matching: find.byType(Container),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user