Add FilterChip.elevated
, ChoiceChip.elevated
, & ActionChip.elevated
variants (#128049)
This commit is contained in:
parent
14136ae319
commit
513ff44bce
@ -26,6 +26,7 @@ import 'package:gen_defaults/bottom_sheet_template.dart';
|
||||
import 'package:gen_defaults/button_template.dart';
|
||||
import 'package:gen_defaults/card_template.dart';
|
||||
import 'package:gen_defaults/checkbox_template.dart';
|
||||
import 'package:gen_defaults/chip_template.dart';
|
||||
import 'package:gen_defaults/color_scheme_template.dart';
|
||||
import 'package:gen_defaults/date_picker_template.dart';
|
||||
import 'package:gen_defaults/dialog_template.dart';
|
||||
@ -138,7 +139,7 @@ Future<void> main(List<String> args) async {
|
||||
tokens['colorsLight'] = _readTokenFile('color_light.json');
|
||||
tokens['colorsDark'] = _readTokenFile('color_dark.json');
|
||||
|
||||
ActionChipTemplate('Chip', '$materialLib/chip.dart', tokens).updateFile();
|
||||
ChipTemplate('Chip', '$materialLib/chip.dart', tokens).updateFile();
|
||||
ActionChipTemplate('ActionChip', '$materialLib/action_chip.dart', tokens).updateFile();
|
||||
AppBarTemplate('AppBar', '$materialLib/app_bar.dart', tokens).updateFile();
|
||||
BottomAppBarTemplate('BottomAppBar', '$materialLib/bottom_app_bar.dart', tokens).updateFile();
|
||||
|
@ -11,51 +11,66 @@ class ActionChipTemplate extends TokenTemplate {
|
||||
});
|
||||
|
||||
static const String tokenGroup = 'md.comp.assist-chip';
|
||||
static const String variant = '.flat';
|
||||
static const String flatVariant = '.flat';
|
||||
static const String elevatedVariant = '.elevated';
|
||||
|
||||
@override
|
||||
String generate() => '''
|
||||
class _${blockName}DefaultsM3 extends ChipThemeData {
|
||||
_${blockName}DefaultsM3(this.context, this.isEnabled)
|
||||
_${blockName}DefaultsM3(this.context, this.isEnabled, this._chipVariant)
|
||||
: super(
|
||||
elevation: ${elevation("$tokenGroup$variant.container")},
|
||||
shape: ${shape("$tokenGroup.container")},
|
||||
showCheckmark: true,
|
||||
);
|
||||
|
||||
final BuildContext context;
|
||||
final bool isEnabled;
|
||||
final _ChipVariant _chipVariant;
|
||||
late final ColorScheme _colors = Theme.of(context).colorScheme;
|
||||
late final TextTheme _textTheme = Theme.of(context).textTheme;
|
||||
|
||||
@override
|
||||
double? get elevation => _chipVariant == _ChipVariant.flat
|
||||
? ${elevation("$tokenGroup$flatVariant.container")}
|
||||
: isEnabled ? ${elevation("$tokenGroup$elevatedVariant.container")} : ${elevation("$tokenGroup$elevatedVariant.disabled.container")};
|
||||
|
||||
@override
|
||||
double? get pressElevation => ${elevation("$tokenGroup$elevatedVariant.pressed.container")};
|
||||
|
||||
@override
|
||||
TextStyle? get labelStyle => ${textStyle("$tokenGroup.label-text")};
|
||||
|
||||
@override
|
||||
Color? get backgroundColor => ${componentColor("$tokenGroup$variant.container")};
|
||||
Color? get backgroundColor => ${componentColor("$tokenGroup$flatVariant.container")};
|
||||
|
||||
@override
|
||||
Color? get shadowColor => ${colorOrTransparent("$tokenGroup.container.shadow-color")};
|
||||
Color? get shadowColor => _chipVariant == _ChipVariant.flat
|
||||
? ${colorOrTransparent("$tokenGroup$flatVariant.container.shadow-color")}
|
||||
: ${colorOrTransparent("$tokenGroup$elevatedVariant.container.shadow-color")};
|
||||
|
||||
@override
|
||||
Color? get surfaceTintColor => ${colorOrTransparent("$tokenGroup.container.surface-tint-layer.color")};
|
||||
|
||||
@override
|
||||
Color? get selectedColor => ${componentColor("$tokenGroup$variant.selected.container")};
|
||||
Color? get selectedColor => ${componentColor("$tokenGroup$flatVariant.selected.container")};
|
||||
|
||||
@override
|
||||
Color? get checkmarkColor => ${color("$tokenGroup.with-icon.selected.icon.color")};
|
||||
|
||||
@override
|
||||
Color? get disabledColor => ${componentColor("$tokenGroup$variant.disabled.container")};
|
||||
Color? get disabledColor => _chipVariant == _ChipVariant.flat
|
||||
? ${componentColor("$tokenGroup$flatVariant.disabled.container")}
|
||||
: ${componentColor("$tokenGroup$elevatedVariant.disabled.container")};
|
||||
|
||||
@override
|
||||
Color? get deleteIconColor => ${color("$tokenGroup.with-icon.selected.icon.color")};
|
||||
|
||||
@override
|
||||
BorderSide? get side => isEnabled
|
||||
? ${border('$tokenGroup$variant.outline')}
|
||||
: ${border('$tokenGroup$variant.disabled.outline')};
|
||||
BorderSide? get side => _chipVariant == _ChipVariant.flat
|
||||
? isEnabled
|
||||
? ${border('$tokenGroup$flatVariant.outline')}
|
||||
: ${border('$tokenGroup$flatVariant.disabled.outline')}
|
||||
: const BorderSide(color: Colors.transparent);
|
||||
|
||||
@override
|
||||
IconThemeData? get iconTheme => IconThemeData(
|
||||
|
83
dev/tools/gen_defaults/lib/chip_template.dart
Normal file
83
dev/tools/gen_defaults/lib/chip_template.dart
Normal file
@ -0,0 +1,83 @@
|
||||
// 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 'template.dart';
|
||||
|
||||
class ChipTemplate extends TokenTemplate {
|
||||
const ChipTemplate(super.blockName, super.fileName, super.tokens, {
|
||||
super.colorSchemePrefix = '_colors.',
|
||||
super.textThemePrefix = '_textTheme.'
|
||||
});
|
||||
|
||||
static const String tokenGroup = 'md.comp.assist-chip';
|
||||
static const String variant = '.flat';
|
||||
|
||||
@override
|
||||
String generate() => '''
|
||||
class _${blockName}DefaultsM3 extends ChipThemeData {
|
||||
_${blockName}DefaultsM3(this.context, this.isEnabled)
|
||||
: super(
|
||||
elevation: ${elevation("$tokenGroup$variant.container")},
|
||||
shape: ${shape("$tokenGroup.container")},
|
||||
showCheckmark: true,
|
||||
);
|
||||
|
||||
final BuildContext context;
|
||||
final bool isEnabled;
|
||||
late final ColorScheme _colors = Theme.of(context).colorScheme;
|
||||
late final TextTheme _textTheme = Theme.of(context).textTheme;
|
||||
|
||||
@override
|
||||
TextStyle? get labelStyle => ${textStyle("$tokenGroup.label-text")};
|
||||
|
||||
@override
|
||||
Color? get backgroundColor => ${componentColor("$tokenGroup$variant.container")};
|
||||
|
||||
@override
|
||||
Color? get shadowColor => ${colorOrTransparent("$tokenGroup.container.shadow-color")};
|
||||
|
||||
@override
|
||||
Color? get surfaceTintColor => ${colorOrTransparent("$tokenGroup.container.surface-tint-layer.color")};
|
||||
|
||||
@override
|
||||
Color? get selectedColor => ${componentColor("$tokenGroup$variant.selected.container")};
|
||||
|
||||
@override
|
||||
Color? get checkmarkColor => ${color("$tokenGroup.with-icon.selected.icon.color")};
|
||||
|
||||
@override
|
||||
Color? get disabledColor => ${componentColor("$tokenGroup$variant.disabled.container")};
|
||||
|
||||
@override
|
||||
Color? get deleteIconColor => ${color("$tokenGroup.with-icon.selected.icon.color")};
|
||||
|
||||
@override
|
||||
BorderSide? get side => isEnabled
|
||||
? ${border('$tokenGroup$variant.outline')}
|
||||
: ${border('$tokenGroup$variant.disabled.outline')};
|
||||
|
||||
@override
|
||||
IconThemeData? get iconTheme => IconThemeData(
|
||||
color: isEnabled
|
||||
? ${color("$tokenGroup.with-icon.icon.color")}
|
||||
: ${color("$tokenGroup.with-icon.disabled.icon.color")},
|
||||
size: ${tokens["$tokenGroup.with-icon.icon.size"]},
|
||||
);
|
||||
|
||||
@override
|
||||
EdgeInsetsGeometry? get padding => const EdgeInsets.all(8.0);
|
||||
|
||||
/// The chip at text scale 1 starts with 8px on each side and as text scaling
|
||||
/// gets closer to 2, the label padding is linearly interpolated from 8px to 4px.
|
||||
/// Once the widget has a text scaling of 2 or higher than the label padding
|
||||
/// remains 4px.
|
||||
@override
|
||||
EdgeInsetsGeometry? get labelPadding => EdgeInsets.lerp(
|
||||
const EdgeInsets.symmetric(horizontal: 8.0),
|
||||
const EdgeInsets.symmetric(horizontal: 4.0),
|
||||
clampDouble(MediaQuery.textScaleFactorOf(context) - 1.0, 0.0, 1.0),
|
||||
)!;
|
||||
}
|
||||
''';
|
||||
}
|
@ -11,14 +11,18 @@ class FilterChipTemplate extends TokenTemplate {
|
||||
});
|
||||
|
||||
static const String tokenGroup = 'md.comp.filter-chip';
|
||||
static const String variant = '.flat';
|
||||
static const String flatVariant = '.flat';
|
||||
static const String elevatedVariant = '.elevated';
|
||||
|
||||
@override
|
||||
String generate() => '''
|
||||
class _${blockName}DefaultsM3 extends ChipThemeData {
|
||||
_${blockName}DefaultsM3(this.context, this.isEnabled, this.isSelected)
|
||||
: super(
|
||||
elevation: ${elevation("$tokenGroup$variant.container")},
|
||||
_${blockName}DefaultsM3(
|
||||
this.context,
|
||||
this.isEnabled,
|
||||
this.isSelected,
|
||||
this._chipVariant,
|
||||
) : super(
|
||||
shape: ${shape("$tokenGroup.container")},
|
||||
showCheckmark: true,
|
||||
);
|
||||
@ -26,42 +30,59 @@ class _${blockName}DefaultsM3 extends ChipThemeData {
|
||||
final BuildContext context;
|
||||
final bool isEnabled;
|
||||
final bool isSelected;
|
||||
final _ChipVariant _chipVariant;
|
||||
late final ColorScheme _colors = Theme.of(context).colorScheme;
|
||||
late final TextTheme _textTheme = Theme.of(context).textTheme;
|
||||
|
||||
@override
|
||||
double? get elevation => _chipVariant == _ChipVariant.flat
|
||||
? ${elevation("$tokenGroup$flatVariant.container")}
|
||||
: isEnabled ? ${elevation("$tokenGroup$elevatedVariant.container")} : ${elevation("$tokenGroup$elevatedVariant.disabled.container")};
|
||||
|
||||
@override
|
||||
double? get pressElevation => ${elevation("$tokenGroup$elevatedVariant.pressed.container")};
|
||||
|
||||
@override
|
||||
TextStyle? get labelStyle => ${textStyle("$tokenGroup.label-text")};
|
||||
|
||||
@override
|
||||
Color? get backgroundColor => ${componentColor("$tokenGroup$variant.container")};
|
||||
Color? get backgroundColor => ${componentColor("$tokenGroup$flatVariant.container")};
|
||||
|
||||
@override
|
||||
Color? get shadowColor => ${colorOrTransparent("$tokenGroup.container.shadow-color")};
|
||||
Color? get shadowColor => _chipVariant == _ChipVariant.flat
|
||||
? ${colorOrTransparent("$tokenGroup$flatVariant.container.shadow-color")}
|
||||
: ${colorOrTransparent("$tokenGroup$elevatedVariant.container.shadow-color")};
|
||||
|
||||
@override
|
||||
Color? get surfaceTintColor => ${colorOrTransparent("$tokenGroup.container.surface-tint-layer.color")};
|
||||
|
||||
@override
|
||||
Color? get selectedColor => isEnabled
|
||||
? ${componentColor("$tokenGroup$variant.selected.container")}
|
||||
: ${componentColor("$tokenGroup$variant.disabled.selected.container")};
|
||||
Color? get selectedColor => _chipVariant == _ChipVariant.flat
|
||||
? isEnabled
|
||||
? ${componentColor("$tokenGroup$flatVariant.selected.container")}
|
||||
: ${componentColor("$tokenGroup$flatVariant.disabled.selected.container")}
|
||||
: isEnabled
|
||||
? ${componentColor("$tokenGroup$elevatedVariant.selected.container")}
|
||||
: ${componentColor("$tokenGroup$elevatedVariant.disabled.container")};
|
||||
|
||||
@override
|
||||
Color? get checkmarkColor => ${color("$tokenGroup.with-leading-icon.selected.leading-icon.color")};
|
||||
|
||||
@override
|
||||
Color? get disabledColor => isSelected
|
||||
? ${componentColor("$tokenGroup$variant.disabled.selected.container")}
|
||||
: ${componentColor("$tokenGroup$variant.disabled.unselected.container")};
|
||||
Color? get disabledColor => _chipVariant == _ChipVariant.flat
|
||||
? isSelected
|
||||
? ${componentColor("$tokenGroup$flatVariant.disabled.selected.container")}
|
||||
: ${componentColor("$tokenGroup$flatVariant.disabled.unselected.container")}
|
||||
: ${componentColor("$tokenGroup$elevatedVariant.disabled.container")};
|
||||
|
||||
@override
|
||||
Color? get deleteIconColor => ${color("$tokenGroup.with-trailing-icon.selected.trailing-icon.color")};
|
||||
|
||||
@override
|
||||
BorderSide? get side => !isSelected
|
||||
BorderSide? get side => _chipVariant == _ChipVariant.flat && !isSelected
|
||||
? isEnabled
|
||||
? ${border('$tokenGroup$variant.unselected.outline')}
|
||||
: ${border('$tokenGroup$variant.disabled.unselected.outline')}
|
||||
? ${border('$tokenGroup$flatVariant.unselected.outline')}
|
||||
: ${border('$tokenGroup$flatVariant.disabled.unselected.outline')}
|
||||
: const BorderSide(color: Colors.transparent);
|
||||
|
||||
@override
|
||||
|
@ -14,6 +14,8 @@ import 'text_theme.dart';
|
||||
import 'theme.dart';
|
||||
import 'theme_data.dart';
|
||||
|
||||
enum _ChipVariant { flat, elevated }
|
||||
|
||||
/// A Material Design action chip.
|
||||
///
|
||||
/// Action chips are a set of options which trigger an action related to primary
|
||||
@ -89,7 +91,40 @@ class ActionChip extends StatelessWidget implements ChipAttributes, TappableChip
|
||||
this.surfaceTintColor,
|
||||
this.iconTheme,
|
||||
}) : assert(pressElevation == null || pressElevation >= 0.0),
|
||||
assert(elevation == null || elevation >= 0.0);
|
||||
assert(elevation == null || elevation >= 0.0),
|
||||
_chipVariant = _ChipVariant.flat;
|
||||
|
||||
/// Create an elevated chip that acts like a button.
|
||||
///
|
||||
/// The [label], [onPressed], [autofocus], and [clipBehavior] arguments must
|
||||
/// not be null. The [pressElevation] and [elevation] must be null or
|
||||
/// non-negative. Typically, [pressElevation] is greater than [elevation].
|
||||
const ActionChip.elevated({
|
||||
super.key,
|
||||
this.avatar,
|
||||
required this.label,
|
||||
this.labelStyle,
|
||||
this.labelPadding,
|
||||
this.onPressed,
|
||||
this.pressElevation,
|
||||
this.tooltip,
|
||||
this.side,
|
||||
this.shape,
|
||||
this.clipBehavior = Clip.none,
|
||||
this.focusNode,
|
||||
this.autofocus = false,
|
||||
this.backgroundColor,
|
||||
this.disabledColor,
|
||||
this.padding,
|
||||
this.visualDensity,
|
||||
this.materialTapTargetSize,
|
||||
this.elevation,
|
||||
this.shadowColor,
|
||||
this.surfaceTintColor,
|
||||
this.iconTheme,
|
||||
}) : assert(pressElevation == null || pressElevation >= 0.0),
|
||||
assert(elevation == null || elevation >= 0.0),
|
||||
_chipVariant = _ChipVariant.elevated;
|
||||
|
||||
@override
|
||||
final Widget? avatar;
|
||||
@ -137,11 +172,13 @@ class ActionChip extends StatelessWidget implements ChipAttributes, TappableChip
|
||||
@override
|
||||
bool get isEnabled => onPressed != null;
|
||||
|
||||
final _ChipVariant _chipVariant;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
assert(debugCheckHasMaterial(context));
|
||||
final ChipThemeData? defaults = Theme.of(context).useMaterial3
|
||||
? _ActionChipDefaultsM3(context, isEnabled)
|
||||
? _ActionChipDefaultsM3(context, isEnabled, _chipVariant)
|
||||
: null;
|
||||
return RawChip(
|
||||
defaultProperties: defaults,
|
||||
@ -180,18 +217,26 @@ class ActionChip extends StatelessWidget implements ChipAttributes, TappableChip
|
||||
// Token database version: v0_162
|
||||
|
||||
class _ActionChipDefaultsM3 extends ChipThemeData {
|
||||
_ActionChipDefaultsM3(this.context, this.isEnabled)
|
||||
_ActionChipDefaultsM3(this.context, this.isEnabled, this._chipVariant)
|
||||
: super(
|
||||
elevation: 0.0,
|
||||
shape: const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(8.0))),
|
||||
showCheckmark: true,
|
||||
);
|
||||
|
||||
final BuildContext context;
|
||||
final bool isEnabled;
|
||||
final _ChipVariant _chipVariant;
|
||||
late final ColorScheme _colors = Theme.of(context).colorScheme;
|
||||
late final TextTheme _textTheme = Theme.of(context).textTheme;
|
||||
|
||||
@override
|
||||
double? get elevation => _chipVariant == _ChipVariant.flat
|
||||
? 0.0
|
||||
: isEnabled ? 1.0 : 0.0;
|
||||
|
||||
@override
|
||||
double? get pressElevation => 1.0;
|
||||
|
||||
@override
|
||||
TextStyle? get labelStyle => _textTheme.labelLarge;
|
||||
|
||||
@ -199,7 +244,9 @@ class _ActionChipDefaultsM3 extends ChipThemeData {
|
||||
Color? get backgroundColor => null;
|
||||
|
||||
@override
|
||||
Color? get shadowColor => Colors.transparent;
|
||||
Color? get shadowColor => _chipVariant == _ChipVariant.flat
|
||||
? Colors.transparent
|
||||
: _colors.shadow;
|
||||
|
||||
@override
|
||||
Color? get surfaceTintColor => _colors.surfaceTint;
|
||||
@ -211,15 +258,19 @@ class _ActionChipDefaultsM3 extends ChipThemeData {
|
||||
Color? get checkmarkColor => null;
|
||||
|
||||
@override
|
||||
Color? get disabledColor => null;
|
||||
Color? get disabledColor => _chipVariant == _ChipVariant.flat
|
||||
? null
|
||||
: _colors.onSurface.withOpacity(0.12);
|
||||
|
||||
@override
|
||||
Color? get deleteIconColor => null;
|
||||
|
||||
@override
|
||||
BorderSide? get side => isEnabled
|
||||
? BorderSide(color: _colors.outline)
|
||||
: BorderSide(color: _colors.onSurface.withOpacity(0.12));
|
||||
BorderSide? get side => _chipVariant == _ChipVariant.flat
|
||||
? isEnabled
|
||||
? BorderSide(color: _colors.outline)
|
||||
: BorderSide(color: _colors.onSurface.withOpacity(0.12))
|
||||
: const BorderSide(color: Colors.transparent);
|
||||
|
||||
@override
|
||||
IconThemeData? get iconTheme => IconThemeData(
|
||||
|
@ -14,6 +14,8 @@ import 'text_theme.dart';
|
||||
import 'theme.dart';
|
||||
import 'theme_data.dart';
|
||||
|
||||
enum _ChipVariant { flat, elevated }
|
||||
|
||||
/// A Material Design choice chip.
|
||||
///
|
||||
/// [ChoiceChip]s represent a single choice from a set. Choice chips contain
|
||||
@ -89,7 +91,46 @@ class ChoiceChip extends StatelessWidget
|
||||
this.checkmarkColor,
|
||||
this.avatarBorder = const CircleBorder(),
|
||||
}) : assert(pressElevation == null || pressElevation >= 0.0),
|
||||
assert(elevation == null || elevation >= 0.0);
|
||||
assert(elevation == null || elevation >= 0.0),
|
||||
_chipVariant = _ChipVariant.flat;
|
||||
|
||||
/// Create an elevated chip that acts like a radio button.
|
||||
///
|
||||
/// The [label], [selected], [autofocus], and [clipBehavior] arguments must
|
||||
/// not be null. The [pressElevation] and [elevation] must be null or
|
||||
/// non-negative. Typically, [pressElevation] is greater than [elevation].
|
||||
const ChoiceChip.elevated({
|
||||
super.key,
|
||||
this.avatar,
|
||||
required this.label,
|
||||
this.labelStyle,
|
||||
this.labelPadding,
|
||||
this.onSelected,
|
||||
this.pressElevation,
|
||||
required this.selected,
|
||||
this.selectedColor,
|
||||
this.disabledColor,
|
||||
this.tooltip,
|
||||
this.side,
|
||||
this.shape,
|
||||
this.clipBehavior = Clip.none,
|
||||
this.focusNode,
|
||||
this.autofocus = false,
|
||||
this.backgroundColor,
|
||||
this.padding,
|
||||
this.visualDensity,
|
||||
this.materialTapTargetSize,
|
||||
this.elevation,
|
||||
this.shadowColor,
|
||||
this.surfaceTintColor,
|
||||
this.iconTheme,
|
||||
this.selectedShadowColor,
|
||||
this.showCheckmark,
|
||||
this.checkmarkColor,
|
||||
this.avatarBorder = const CircleBorder(),
|
||||
}) : assert(pressElevation == null || pressElevation >= 0.0),
|
||||
assert(elevation == null || elevation >= 0.0),
|
||||
_chipVariant = _ChipVariant.elevated;
|
||||
|
||||
@override
|
||||
final Widget? avatar;
|
||||
@ -149,12 +190,14 @@ class ChoiceChip extends StatelessWidget
|
||||
@override
|
||||
bool get isEnabled => onSelected != null;
|
||||
|
||||
final _ChipVariant _chipVariant;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
assert(debugCheckHasMaterial(context));
|
||||
final ChipThemeData chipTheme = ChipTheme.of(context);
|
||||
final ChipThemeData? defaults = Theme.of(context).useMaterial3
|
||||
? _ChoiceChipDefaultsM3(context, isEnabled, selected)
|
||||
? _ChoiceChipDefaultsM3(context, isEnabled, selected, _chipVariant)
|
||||
: null;
|
||||
return RawChip(
|
||||
defaultProperties: defaults,
|
||||
@ -200,9 +243,12 @@ class ChoiceChip extends StatelessWidget
|
||||
// Token database version: v0_162
|
||||
|
||||
class _ChoiceChipDefaultsM3 extends ChipThemeData {
|
||||
_ChoiceChipDefaultsM3(this.context, this.isEnabled, this.isSelected)
|
||||
: super(
|
||||
elevation: 0.0,
|
||||
_ChoiceChipDefaultsM3(
|
||||
this.context,
|
||||
this.isEnabled,
|
||||
this.isSelected,
|
||||
this._chipVariant,
|
||||
) : super(
|
||||
shape: const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(8.0))),
|
||||
showCheckmark: true,
|
||||
);
|
||||
@ -210,9 +256,18 @@ class _ChoiceChipDefaultsM3 extends ChipThemeData {
|
||||
final BuildContext context;
|
||||
final bool isEnabled;
|
||||
final bool isSelected;
|
||||
final _ChipVariant _chipVariant;
|
||||
late final ColorScheme _colors = Theme.of(context).colorScheme;
|
||||
late final TextTheme _textTheme = Theme.of(context).textTheme;
|
||||
|
||||
@override
|
||||
double? get elevation => _chipVariant == _ChipVariant.flat
|
||||
? 0.0
|
||||
: isEnabled ? 1.0 : 0.0;
|
||||
|
||||
@override
|
||||
double? get pressElevation => 1.0;
|
||||
|
||||
@override
|
||||
TextStyle? get labelStyle => _textTheme.labelLarge;
|
||||
|
||||
@ -220,29 +275,37 @@ class _ChoiceChipDefaultsM3 extends ChipThemeData {
|
||||
Color? get backgroundColor => null;
|
||||
|
||||
@override
|
||||
Color? get shadowColor => Colors.transparent;
|
||||
Color? get shadowColor => _chipVariant == _ChipVariant.flat
|
||||
? Colors.transparent
|
||||
: _colors.shadow;
|
||||
|
||||
@override
|
||||
Color? get surfaceTintColor => _colors.surfaceTint;
|
||||
|
||||
@override
|
||||
Color? get selectedColor => isEnabled
|
||||
? _colors.secondaryContainer
|
||||
: _colors.onSurface.withOpacity(0.12);
|
||||
Color? get selectedColor => _chipVariant == _ChipVariant.flat
|
||||
? isEnabled
|
||||
? _colors.secondaryContainer
|
||||
: _colors.onSurface.withOpacity(0.12)
|
||||
: isEnabled
|
||||
? _colors.secondaryContainer
|
||||
: _colors.onSurface.withOpacity(0.12);
|
||||
|
||||
@override
|
||||
Color? get checkmarkColor => _colors.onSecondaryContainer;
|
||||
|
||||
@override
|
||||
Color? get disabledColor => isSelected
|
||||
? _colors.onSurface.withOpacity(0.12)
|
||||
: null;
|
||||
Color? get disabledColor => _chipVariant == _ChipVariant.flat
|
||||
? isSelected
|
||||
? _colors.onSurface.withOpacity(0.12)
|
||||
: null
|
||||
: _colors.onSurface.withOpacity(0.12);
|
||||
|
||||
@override
|
||||
Color? get deleteIconColor => _colors.onSecondaryContainer;
|
||||
|
||||
@override
|
||||
BorderSide? get side => !isSelected
|
||||
BorderSide? get side => _chipVariant == _ChipVariant.flat && !isSelected
|
||||
? isEnabled
|
||||
? BorderSide(color: _colors.outline)
|
||||
: BorderSide(color: _colors.onSurface.withOpacity(0.12))
|
||||
|
@ -14,6 +14,8 @@ import 'text_theme.dart';
|
||||
import 'theme.dart';
|
||||
import 'theme_data.dart';
|
||||
|
||||
enum _ChipVariant { flat, elevated }
|
||||
|
||||
/// A Material Design filter chip.
|
||||
///
|
||||
/// Filter chips use tags or descriptive words as a way to filter content.
|
||||
@ -91,7 +93,46 @@ class FilterChip extends StatelessWidget
|
||||
this.checkmarkColor,
|
||||
this.avatarBorder = const CircleBorder(),
|
||||
}) : assert(pressElevation == null || pressElevation >= 0.0),
|
||||
assert(elevation == null || elevation >= 0.0);
|
||||
assert(elevation == null || elevation >= 0.0),
|
||||
_chipVariant = _ChipVariant.flat;
|
||||
|
||||
/// Create an elevated chip that acts like a checkbox.
|
||||
///
|
||||
/// The [selected], [label], [autofocus], and [clipBehavior] arguments must
|
||||
/// not be null. The [pressElevation] and [elevation] must be null or
|
||||
/// non-negative. Typically, [pressElevation] is greater than [elevation].
|
||||
const FilterChip.elevated({
|
||||
super.key,
|
||||
this.avatar,
|
||||
required this.label,
|
||||
this.labelStyle,
|
||||
this.labelPadding,
|
||||
this.selected = false,
|
||||
required this.onSelected,
|
||||
this.pressElevation,
|
||||
this.disabledColor,
|
||||
this.selectedColor,
|
||||
this.tooltip,
|
||||
this.side,
|
||||
this.shape,
|
||||
this.clipBehavior = Clip.none,
|
||||
this.focusNode,
|
||||
this.autofocus = false,
|
||||
this.backgroundColor,
|
||||
this.padding,
|
||||
this.visualDensity,
|
||||
this.materialTapTargetSize,
|
||||
this.elevation,
|
||||
this.shadowColor,
|
||||
this.surfaceTintColor,
|
||||
this.iconTheme,
|
||||
this.selectedShadowColor,
|
||||
this.showCheckmark,
|
||||
this.checkmarkColor,
|
||||
this.avatarBorder = const CircleBorder(),
|
||||
}) : assert(pressElevation == null || pressElevation >= 0.0),
|
||||
assert(elevation == null || elevation >= 0.0),
|
||||
_chipVariant = _ChipVariant.elevated;
|
||||
|
||||
@override
|
||||
final Widget? avatar;
|
||||
@ -151,11 +192,13 @@ class FilterChip extends StatelessWidget
|
||||
@override
|
||||
bool get isEnabled => onSelected != null;
|
||||
|
||||
final _ChipVariant _chipVariant;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
assert(debugCheckHasMaterial(context));
|
||||
final ChipThemeData? defaults = Theme.of(context).useMaterial3
|
||||
? _FilterChipDefaultsM3(context, isEnabled, selected)
|
||||
? _FilterChipDefaultsM3(context, isEnabled, selected, _chipVariant)
|
||||
: null;
|
||||
return RawChip(
|
||||
defaultProperties: defaults,
|
||||
@ -200,9 +243,12 @@ class FilterChip extends StatelessWidget
|
||||
// Token database version: v0_162
|
||||
|
||||
class _FilterChipDefaultsM3 extends ChipThemeData {
|
||||
_FilterChipDefaultsM3(this.context, this.isEnabled, this.isSelected)
|
||||
: super(
|
||||
elevation: 0.0,
|
||||
_FilterChipDefaultsM3(
|
||||
this.context,
|
||||
this.isEnabled,
|
||||
this.isSelected,
|
||||
this._chipVariant,
|
||||
) : super(
|
||||
shape: const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(8.0))),
|
||||
showCheckmark: true,
|
||||
);
|
||||
@ -210,9 +256,18 @@ class _FilterChipDefaultsM3 extends ChipThemeData {
|
||||
final BuildContext context;
|
||||
final bool isEnabled;
|
||||
final bool isSelected;
|
||||
final _ChipVariant _chipVariant;
|
||||
late final ColorScheme _colors = Theme.of(context).colorScheme;
|
||||
late final TextTheme _textTheme = Theme.of(context).textTheme;
|
||||
|
||||
@override
|
||||
double? get elevation => _chipVariant == _ChipVariant.flat
|
||||
? 0.0
|
||||
: isEnabled ? 1.0 : 0.0;
|
||||
|
||||
@override
|
||||
double? get pressElevation => 1.0;
|
||||
|
||||
@override
|
||||
TextStyle? get labelStyle => _textTheme.labelLarge;
|
||||
|
||||
@ -220,29 +275,37 @@ class _FilterChipDefaultsM3 extends ChipThemeData {
|
||||
Color? get backgroundColor => null;
|
||||
|
||||
@override
|
||||
Color? get shadowColor => Colors.transparent;
|
||||
Color? get shadowColor => _chipVariant == _ChipVariant.flat
|
||||
? Colors.transparent
|
||||
: _colors.shadow;
|
||||
|
||||
@override
|
||||
Color? get surfaceTintColor => _colors.surfaceTint;
|
||||
|
||||
@override
|
||||
Color? get selectedColor => isEnabled
|
||||
? _colors.secondaryContainer
|
||||
: _colors.onSurface.withOpacity(0.12);
|
||||
Color? get selectedColor => _chipVariant == _ChipVariant.flat
|
||||
? isEnabled
|
||||
? _colors.secondaryContainer
|
||||
: _colors.onSurface.withOpacity(0.12)
|
||||
: isEnabled
|
||||
? _colors.secondaryContainer
|
||||
: _colors.onSurface.withOpacity(0.12);
|
||||
|
||||
@override
|
||||
Color? get checkmarkColor => _colors.onSecondaryContainer;
|
||||
|
||||
@override
|
||||
Color? get disabledColor => isSelected
|
||||
? _colors.onSurface.withOpacity(0.12)
|
||||
: null;
|
||||
Color? get disabledColor => _chipVariant == _ChipVariant.flat
|
||||
? isSelected
|
||||
? _colors.onSurface.withOpacity(0.12)
|
||||
: null
|
||||
: _colors.onSurface.withOpacity(0.12);
|
||||
|
||||
@override
|
||||
Color? get deleteIconColor => _colors.onSecondaryContainer;
|
||||
|
||||
@override
|
||||
BorderSide? get side => !isSelected
|
||||
BorderSide? get side => _chipVariant == _ChipVariant.flat && !isSelected
|
||||
? isEnabled
|
||||
? BorderSide(color: _colors.outline)
|
||||
: BorderSide(color: _colors.onSurface.withOpacity(0.12))
|
||||
|
@ -26,6 +26,24 @@ Widget wrapForChip({
|
||||
);
|
||||
}
|
||||
|
||||
Material getMaterial(WidgetTester tester) {
|
||||
return tester.widget<Material>(
|
||||
find.descendant(
|
||||
of: find.byType(ActionChip),
|
||||
matching: find.byType(Material),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
DefaultTextStyle getLabelStyle(WidgetTester tester, String labelText) {
|
||||
return tester.widget(
|
||||
find.ancestor(
|
||||
of: find.text(labelText),
|
||||
matching: find.byType(DefaultTextStyle),
|
||||
).first,
|
||||
);
|
||||
}
|
||||
|
||||
void checkChipMaterialClipBehavior(WidgetTester tester, Clip clipBehavior) {
|
||||
final Iterable<Material> materials = tester.widgetList<Material>(find.byType(Material));
|
||||
// There should be two Material widgets, first Material is from the "_wrapForChip" and
|
||||
@ -36,6 +54,148 @@ void checkChipMaterialClipBehavior(WidgetTester tester, Clip clipBehavior) {
|
||||
}
|
||||
|
||||
void main() {
|
||||
testWidgets('ActionChip defaults', (WidgetTester tester) async {
|
||||
final ThemeData theme = ThemeData(useMaterial3: true);
|
||||
const String label = 'action chip';
|
||||
|
||||
// Test enabled ActionChip defaults.
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
theme: theme,
|
||||
home: Material(
|
||||
child: Center(
|
||||
child: ActionChip(
|
||||
onPressed: () {},
|
||||
label: const Text(label),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
// Test default chip size.
|
||||
expect(tester.getSize(find.byType(ActionChip)), const Size(190.0, 48.0));
|
||||
// Test default label style.
|
||||
expect(
|
||||
getLabelStyle(tester, label).style.color!.value,
|
||||
theme.textTheme.labelLarge!.color!.value,
|
||||
);
|
||||
|
||||
Material chipMaterial = getMaterial(tester);
|
||||
expect(chipMaterial.elevation, 0);
|
||||
expect(chipMaterial.shadowColor, Colors.transparent);
|
||||
expect(chipMaterial.surfaceTintColor, theme.colorScheme.surfaceTint);
|
||||
expect(
|
||||
chipMaterial.shape,
|
||||
RoundedRectangleBorder(
|
||||
borderRadius: const BorderRadius.all(Radius.circular(8.0)),
|
||||
side: BorderSide(color: theme.colorScheme.outline),
|
||||
),
|
||||
);
|
||||
|
||||
ShapeDecoration decoration = tester.widget<Ink>(find.byType(Ink)).decoration! as ShapeDecoration;
|
||||
expect(decoration.color, null);
|
||||
|
||||
// Test disabled ActionChip defaults.
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
theme: theme,
|
||||
home: const Material(
|
||||
child: ActionChip(
|
||||
label: Text(label),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
chipMaterial = getMaterial(tester);
|
||||
expect(chipMaterial.elevation, 0);
|
||||
expect(chipMaterial.shadowColor, Colors.transparent);
|
||||
expect(chipMaterial.surfaceTintColor, theme.colorScheme.surfaceTint);
|
||||
expect(
|
||||
chipMaterial.shape,
|
||||
RoundedRectangleBorder(
|
||||
borderRadius: const BorderRadius.all(Radius.circular(8.0)),
|
||||
side: BorderSide(color: theme.colorScheme.onSurface.withOpacity(0.12)),
|
||||
),
|
||||
);
|
||||
|
||||
decoration = tester.widget<Ink>(find.byType(Ink)).decoration! as ShapeDecoration;
|
||||
expect(decoration.color, null);
|
||||
});
|
||||
|
||||
testWidgets('ActionChip.elevated defaults', (WidgetTester tester) async {
|
||||
final ThemeData theme = ThemeData(useMaterial3: true);
|
||||
const String label = 'action chip';
|
||||
|
||||
// Test enabled ActionChip defaults.
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
theme: theme,
|
||||
home: Material(
|
||||
child: Center(
|
||||
child: ActionChip.elevated(
|
||||
onPressed: () {},
|
||||
label: const Text(label),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
// Test default chip size.
|
||||
expect(tester.getSize(find.byType(ActionChip)), const Size(190.0, 48.0));
|
||||
// Test default label style.
|
||||
expect(
|
||||
getLabelStyle(tester, label).style.color!.value,
|
||||
theme.textTheme.labelLarge!.color!.value,
|
||||
);
|
||||
|
||||
Material chipMaterial = getMaterial(tester);
|
||||
expect(chipMaterial.elevation, 1);
|
||||
expect(chipMaterial.shadowColor, theme.colorScheme.shadow);
|
||||
expect(chipMaterial.surfaceTintColor, theme.colorScheme.surfaceTint);
|
||||
expect(
|
||||
chipMaterial.shape,
|
||||
const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(Radius.circular(8.0)),
|
||||
side: BorderSide(color: Colors.transparent),
|
||||
),
|
||||
);
|
||||
|
||||
ShapeDecoration decoration = tester.widget<Ink>(find.byType(Ink)).decoration! as ShapeDecoration;
|
||||
expect(decoration.color, null);
|
||||
|
||||
// Test disabled ActionChip.elevated defaults.
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
theme: theme,
|
||||
home: const Material(
|
||||
child: ActionChip.elevated(
|
||||
label: Text(label),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
chipMaterial = getMaterial(tester);
|
||||
expect(chipMaterial.elevation, 0);
|
||||
expect(chipMaterial.shadowColor, theme.colorScheme.shadow);
|
||||
expect(chipMaterial.surfaceTintColor, theme.colorScheme.surfaceTint);
|
||||
expect(
|
||||
chipMaterial.shape,
|
||||
const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(Radius.circular(8.0)),
|
||||
side: BorderSide(color: Colors.transparent),
|
||||
),
|
||||
);
|
||||
|
||||
decoration = tester.widget<Ink>(find.byType(Ink)).decoration! as ShapeDecoration;
|
||||
expect(decoration.color, theme.colorScheme.onSurface.withOpacity(0.12));
|
||||
});
|
||||
|
||||
testWidgetsWithLeakTracking('ActionChip can be tapped', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
|
@ -64,36 +64,267 @@ void checkChipMaterialClipBehavior(WidgetTester tester, Clip clipBehavior) {
|
||||
|
||||
void main() {
|
||||
testWidgets('ChoiceChip defaults', (WidgetTester tester) async {
|
||||
Widget buildFrame(Brightness brightness) {
|
||||
return MaterialApp(
|
||||
theme: ThemeData(brightness: brightness),
|
||||
home: const Scaffold(
|
||||
body: Center(
|
||||
final ThemeData theme = ThemeData(useMaterial3: true);
|
||||
const String label = 'choice chip';
|
||||
|
||||
// Test enabled ChoiceChip defaults.
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
theme: theme,
|
||||
home: Material(
|
||||
child: Center(
|
||||
child: ChoiceChip(
|
||||
label: Text('Chip A'),
|
||||
selected: true,
|
||||
selected: false,
|
||||
onSelected: (bool valueChanged) { },
|
||||
label: const Text(label),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
),
|
||||
);
|
||||
|
||||
await tester.pumpWidget(buildFrame(Brightness.light));
|
||||
expect(getMaterialBox(tester), paints..rrect(color: const Color(0x3d000000)));
|
||||
expect(tester.getSize(find.byType(ChoiceChip)), const Size(108.0, 48.0));
|
||||
expect(getMaterial(tester).color, null);
|
||||
expect(getMaterial(tester).elevation, 0);
|
||||
expect(getMaterial(tester).shape, const StadiumBorder());
|
||||
expect(getLabelStyle(tester, 'Chip A').style.color?.value, 0xde000000);
|
||||
// Test default chip size.
|
||||
expect(tester.getSize(find.byType(ChoiceChip)), const Size(190.0, 48.0));
|
||||
// Test default label style.
|
||||
expect(
|
||||
getLabelStyle(tester, label).style.color!.value,
|
||||
theme.textTheme.labelLarge!.color!.value,
|
||||
);
|
||||
|
||||
await tester.pumpWidget(buildFrame(Brightness.dark));
|
||||
await tester.pumpAndSettle(); // Theme transition animation
|
||||
expect(getMaterialBox(tester), paints..rrect(color: const Color(0x3dffffff)));
|
||||
expect(tester.getSize(find.byType(ChoiceChip)), const Size(108.0, 48.0));
|
||||
expect(getMaterial(tester).color, null);
|
||||
expect(getMaterial(tester).elevation, 0);
|
||||
expect(getMaterial(tester).shape, const StadiumBorder());
|
||||
expect(getLabelStyle(tester, 'Chip A').style.color?.value, 0xdeffffff);
|
||||
Material chipMaterial = getMaterial(tester);
|
||||
expect(chipMaterial.elevation, 0);
|
||||
expect(chipMaterial.shadowColor, Colors.transparent);
|
||||
expect(chipMaterial.surfaceTintColor, theme.colorScheme.surfaceTint);
|
||||
expect(
|
||||
chipMaterial.shape,
|
||||
RoundedRectangleBorder(
|
||||
borderRadius: const BorderRadius.all(Radius.circular(8.0)),
|
||||
side: BorderSide(color: theme.colorScheme.outline),
|
||||
),
|
||||
);
|
||||
|
||||
ShapeDecoration decoration = tester.widget<Ink>(find.byType(Ink)).decoration! as ShapeDecoration;
|
||||
expect(decoration.color, null);
|
||||
|
||||
// Test disabled ChoiceChip defaults.
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
theme: theme,
|
||||
home: const Material(
|
||||
child: ChoiceChip(
|
||||
selected: false,
|
||||
label: Text(label),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
chipMaterial = getMaterial(tester);
|
||||
expect(chipMaterial.elevation, 0);
|
||||
expect(chipMaterial.shadowColor, Colors.transparent);
|
||||
expect(chipMaterial.surfaceTintColor, theme.colorScheme.surfaceTint);
|
||||
expect(
|
||||
chipMaterial.shape,
|
||||
RoundedRectangleBorder(
|
||||
borderRadius: const BorderRadius.all(Radius.circular(8.0)),
|
||||
side: BorderSide(color: theme.colorScheme.onSurface.withOpacity(0.12)),
|
||||
),
|
||||
);
|
||||
|
||||
decoration = tester.widget<Ink>(find.byType(Ink)).decoration! as ShapeDecoration;
|
||||
expect(decoration.color, null);
|
||||
|
||||
// Test selected enabled ChoiceChip defaults.
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
theme: theme,
|
||||
home: Material(
|
||||
child: ChoiceChip(
|
||||
selected: true,
|
||||
onSelected: (bool valueChanged) { },
|
||||
label: const Text(label),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
chipMaterial = getMaterial(tester);
|
||||
expect(chipMaterial.elevation, 0);
|
||||
expect(chipMaterial.shadowColor, null);
|
||||
expect(chipMaterial.surfaceTintColor, theme.colorScheme.surfaceTint);
|
||||
expect(
|
||||
chipMaterial.shape,
|
||||
const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(Radius.circular(8.0)),
|
||||
side: BorderSide(color: Colors.transparent),
|
||||
),
|
||||
);
|
||||
|
||||
decoration = tester.widget<Ink>(find.byType(Ink)).decoration! as ShapeDecoration;
|
||||
expect(decoration.color, theme.colorScheme.secondaryContainer);
|
||||
|
||||
// Test selected disabled ChoiceChip defaults.
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
theme: theme,
|
||||
home: const Material(
|
||||
child: ChoiceChip(
|
||||
selected: true,
|
||||
label: Text(label),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
chipMaterial = getMaterial(tester);
|
||||
expect(chipMaterial.elevation, 0);
|
||||
expect(chipMaterial.shadowColor, null);
|
||||
expect(chipMaterial.surfaceTintColor, theme.colorScheme.surfaceTint);
|
||||
expect(
|
||||
chipMaterial.shape,
|
||||
const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(Radius.circular(8.0)),
|
||||
side: BorderSide(color: Colors.transparent),
|
||||
),
|
||||
);
|
||||
|
||||
decoration = tester.widget<Ink>(find.byType(Ink)).decoration! as ShapeDecoration;
|
||||
expect(decoration.color, theme.colorScheme.onSurface.withOpacity(0.12));
|
||||
});
|
||||
|
||||
testWidgets('ChoiceChip.elevated defaults', (WidgetTester tester) async {
|
||||
final ThemeData theme = ThemeData(useMaterial3: true);
|
||||
const String label = 'choice chip';
|
||||
|
||||
// Test enabled ChoiceChip.elevated defaults.
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
theme: theme,
|
||||
home: Material(
|
||||
child: Center(
|
||||
child: ChoiceChip.elevated(
|
||||
selected: false,
|
||||
onSelected: (bool valueChanged) { },
|
||||
label: const Text(label),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
// Test default chip size.
|
||||
expect(tester.getSize(find.byType(ChoiceChip)), const Size(190.0, 48.0));
|
||||
// Test default label style.
|
||||
expect(
|
||||
getLabelStyle(tester, label).style.color!.value,
|
||||
theme.textTheme.labelLarge!.color!.value,
|
||||
);
|
||||
|
||||
Material chipMaterial = getMaterial(tester);
|
||||
expect(chipMaterial.elevation, 1);
|
||||
expect(chipMaterial.shadowColor, theme.colorScheme.shadow);
|
||||
expect(chipMaterial.surfaceTintColor, theme.colorScheme.surfaceTint);
|
||||
expect(
|
||||
chipMaterial.shape,
|
||||
const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(Radius.circular(8.0)),
|
||||
side: BorderSide(color: Colors.transparent),
|
||||
),
|
||||
);
|
||||
|
||||
ShapeDecoration decoration = tester.widget<Ink>(find.byType(Ink)).decoration! as ShapeDecoration;
|
||||
expect(decoration.color, null);
|
||||
|
||||
// Test disabled ChoiceChip.elevated defaults.
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
theme: theme,
|
||||
home: const Material(
|
||||
child: ChoiceChip.elevated(
|
||||
selected: false,
|
||||
label: Text(label),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
chipMaterial = getMaterial(tester);
|
||||
expect(chipMaterial.elevation, 0);
|
||||
expect(chipMaterial.shadowColor, theme.colorScheme.shadow);
|
||||
expect(chipMaterial.surfaceTintColor, theme.colorScheme.surfaceTint);
|
||||
expect(
|
||||
chipMaterial.shape,
|
||||
const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(Radius.circular(8.0)),
|
||||
side: BorderSide(color: Colors.transparent),
|
||||
),
|
||||
);
|
||||
|
||||
decoration = tester.widget<Ink>(find.byType(Ink)).decoration! as ShapeDecoration;
|
||||
expect(decoration.color, theme.colorScheme.onSurface.withOpacity(0.12));
|
||||
|
||||
// Test selected enabled ChoiceChip.elevated defaults.
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
theme: theme,
|
||||
home: Material(
|
||||
child: ChoiceChip.elevated(
|
||||
selected: true,
|
||||
onSelected: (bool valueChanged) { },
|
||||
label: const Text(label),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
chipMaterial = getMaterial(tester);
|
||||
expect(chipMaterial.elevation, 1);
|
||||
expect(chipMaterial.shadowColor, null);
|
||||
expect(chipMaterial.surfaceTintColor, theme.colorScheme.surfaceTint);
|
||||
expect(
|
||||
chipMaterial.shape,
|
||||
const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(Radius.circular(8.0)),
|
||||
side: BorderSide(color: Colors.transparent),
|
||||
),
|
||||
);
|
||||
|
||||
decoration = tester.widget<Ink>(find.byType(Ink)).decoration! as ShapeDecoration;
|
||||
expect(decoration.color, theme.colorScheme.secondaryContainer);
|
||||
|
||||
// Test selected disabled ChoiceChip.elevated defaults.
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
theme: theme,
|
||||
home: const Material(
|
||||
child: ChoiceChip.elevated(
|
||||
selected: false,
|
||||
label: Text(label),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
chipMaterial = getMaterial(tester);
|
||||
expect(chipMaterial.elevation, 0);
|
||||
expect(chipMaterial.shadowColor, theme.colorScheme.shadow);
|
||||
expect(chipMaterial.surfaceTintColor, theme.colorScheme.surfaceTint);
|
||||
expect(
|
||||
chipMaterial.shape,
|
||||
const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(Radius.circular(8.0)),
|
||||
side: BorderSide(color: Colors.transparent),
|
||||
),
|
||||
);
|
||||
|
||||
decoration = tester.widget<Ink>(find.byType(Ink)).decoration! as ShapeDecoration;
|
||||
expect(decoration.color, theme.colorScheme.onSurface.withOpacity(0.12));
|
||||
});
|
||||
|
||||
testWidgets('ChoiceChip can be tapped', (WidgetTester tester) async {
|
||||
@ -163,4 +394,43 @@ void main() {
|
||||
expect(rawChip.showCheckmark, showCheckmark);
|
||||
expect(rawChip.checkmarkColor, checkmarkColor);
|
||||
});
|
||||
|
||||
group('Material 2', () {
|
||||
// These tests are only relevant for Material 2. Once Material 2
|
||||
// support is deprecated and the APIs are removed, these tests
|
||||
// can be deleted.
|
||||
|
||||
testWidgets('ChoiceChip defaults', (WidgetTester tester) async {
|
||||
Widget buildFrame(Brightness brightness) {
|
||||
return MaterialApp(
|
||||
theme: ThemeData(brightness: brightness),
|
||||
home: const Scaffold(
|
||||
body: Center(
|
||||
child: ChoiceChip(
|
||||
label: Text('Chip A'),
|
||||
selected: true,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
await tester.pumpWidget(buildFrame(Brightness.light));
|
||||
expect(getMaterialBox(tester), paints..rrect(color: const Color(0x3d000000)));
|
||||
expect(tester.getSize(find.byType(ChoiceChip)), const Size(108.0, 48.0));
|
||||
expect(getMaterial(tester).color, null);
|
||||
expect(getMaterial(tester).elevation, 0);
|
||||
expect(getMaterial(tester).shape, const StadiumBorder());
|
||||
expect(getLabelStyle(tester, 'Chip A').style.color?.value, 0xde000000);
|
||||
|
||||
await tester.pumpWidget(buildFrame(Brightness.dark));
|
||||
await tester.pumpAndSettle(); // Theme transition animation
|
||||
expect(getMaterialBox(tester), paints..rrect(color: const Color(0x3dffffff)));
|
||||
expect(tester.getSize(find.byType(ChoiceChip)), const Size(108.0, 48.0));
|
||||
expect(getMaterial(tester).color, null);
|
||||
expect(getMaterial(tester).elevation, 0);
|
||||
expect(getMaterial(tester).shape, const StadiumBorder());
|
||||
expect(getLabelStyle(tester, 'Chip A').style.color?.value, 0xdeffffff);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -84,7 +84,289 @@ void checkChipMaterialClipBehavior(WidgetTester tester, Clip clipBehavior) {
|
||||
expect(materials.last.clipBehavior, clipBehavior);
|
||||
}
|
||||
|
||||
Material getMaterial(WidgetTester tester) {
|
||||
return tester.widget<Material>(
|
||||
find.descendant(
|
||||
of: find.byType(FilterChip),
|
||||
matching: find.byType(Material),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
DefaultTextStyle getLabelStyle(WidgetTester tester, String labelText) {
|
||||
return tester.widget(
|
||||
find.ancestor(
|
||||
of: find.text(labelText),
|
||||
matching: find.byType(DefaultTextStyle),
|
||||
).first,
|
||||
);
|
||||
}
|
||||
|
||||
void main() {
|
||||
testWidgets('FilterChip defaults', (WidgetTester tester) async {
|
||||
final ThemeData theme = ThemeData(useMaterial3: true);
|
||||
const String label = 'filter chip';
|
||||
|
||||
// Test enabled FilterChip defaults.
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
theme: theme,
|
||||
home: Material(
|
||||
child: Center(
|
||||
child: FilterChip(
|
||||
onSelected: (bool valueChanged) { },
|
||||
label: const Text(label),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
// Test default chip size.
|
||||
expect(tester.getSize(find.byType(FilterChip)), const Size(190.0, 48.0));
|
||||
// Test default label style.
|
||||
expect(
|
||||
getLabelStyle(tester, label).style.color!.value,
|
||||
theme.textTheme.labelLarge!.color!.value,
|
||||
);
|
||||
|
||||
Material chipMaterial = getMaterial(tester);
|
||||
expect(chipMaterial.elevation, 0);
|
||||
expect(chipMaterial.shadowColor, Colors.transparent);
|
||||
expect(chipMaterial.surfaceTintColor, theme.colorScheme.surfaceTint);
|
||||
expect(
|
||||
chipMaterial.shape,
|
||||
RoundedRectangleBorder(
|
||||
borderRadius: const BorderRadius.all(Radius.circular(8.0)),
|
||||
side: BorderSide(color: theme.colorScheme.outline),
|
||||
),
|
||||
);
|
||||
|
||||
ShapeDecoration decoration = tester.widget<Ink>(find.byType(Ink)).decoration! as ShapeDecoration;
|
||||
expect(decoration.color, null);
|
||||
|
||||
// Test disabled FilterChip defaults.
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
theme: theme,
|
||||
home: const Material(
|
||||
child: FilterChip(
|
||||
onSelected: null,
|
||||
label: Text(label),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
chipMaterial = getMaterial(tester);
|
||||
expect(chipMaterial.elevation, 0);
|
||||
expect(chipMaterial.shadowColor, Colors.transparent);
|
||||
expect(chipMaterial.surfaceTintColor, theme.colorScheme.surfaceTint);
|
||||
expect(
|
||||
chipMaterial.shape,
|
||||
RoundedRectangleBorder(
|
||||
borderRadius: const BorderRadius.all(Radius.circular(8.0)),
|
||||
side: BorderSide(color: theme.colorScheme.onSurface.withOpacity(0.12)),
|
||||
),
|
||||
);
|
||||
|
||||
decoration = tester.widget<Ink>(find.byType(Ink)).decoration! as ShapeDecoration;
|
||||
expect(decoration.color, null);
|
||||
|
||||
// Test selected enabled FilterChip defaults.
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
theme: theme,
|
||||
home: Material(
|
||||
child: FilterChip(
|
||||
selected: true,
|
||||
onSelected: (bool valueChanged) { },
|
||||
label: const Text(label),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
chipMaterial = getMaterial(tester);
|
||||
expect(chipMaterial.elevation, 0);
|
||||
expect(chipMaterial.shadowColor, null);
|
||||
expect(chipMaterial.surfaceTintColor, theme.colorScheme.surfaceTint);
|
||||
expect(
|
||||
chipMaterial.shape,
|
||||
const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(Radius.circular(8.0)),
|
||||
side: BorderSide(color: Colors.transparent),
|
||||
),
|
||||
);
|
||||
|
||||
decoration = tester.widget<Ink>(find.byType(Ink)).decoration! as ShapeDecoration;
|
||||
expect(decoration.color, theme.colorScheme.secondaryContainer);
|
||||
|
||||
// Test selected disabled FilterChip defaults.
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
theme: theme,
|
||||
home: const Material(
|
||||
child: FilterChip(
|
||||
selected: true,
|
||||
onSelected: null,
|
||||
label: Text(label),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
chipMaterial = getMaterial(tester);
|
||||
expect(chipMaterial.elevation, 0);
|
||||
expect(chipMaterial.shadowColor, null);
|
||||
expect(chipMaterial.surfaceTintColor, theme.colorScheme.surfaceTint);
|
||||
expect(
|
||||
chipMaterial.shape,
|
||||
const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(Radius.circular(8.0)),
|
||||
side: BorderSide(color: Colors.transparent),
|
||||
),
|
||||
);
|
||||
|
||||
decoration = tester.widget<Ink>(find.byType(Ink)).decoration! as ShapeDecoration;
|
||||
expect(decoration.color, theme.colorScheme.onSurface.withOpacity(0.12));
|
||||
});
|
||||
|
||||
testWidgets('FilterChip.elevated defaults', (WidgetTester tester) async {
|
||||
final ThemeData theme = ThemeData(useMaterial3: true);
|
||||
const String label = 'filter chip';
|
||||
|
||||
// Test enabled FilterChip.elevated defaults.
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
theme: theme,
|
||||
home: Material(
|
||||
child: Center(
|
||||
child: FilterChip.elevated(
|
||||
onSelected: (bool valueChanged) { },
|
||||
label: const Text(label),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
// Test default chip size.
|
||||
expect(tester.getSize(find.byType(FilterChip)), const Size(190.0, 48.0));
|
||||
// Test default label style.
|
||||
expect(
|
||||
getLabelStyle(tester, 'filter chip').style.color!.value,
|
||||
theme.textTheme.labelLarge!.color!.value,
|
||||
);
|
||||
|
||||
Material chipMaterial = getMaterial(tester);
|
||||
expect(chipMaterial.elevation, 1);
|
||||
expect(chipMaterial.shadowColor, theme.colorScheme.shadow);
|
||||
expect(chipMaterial.surfaceTintColor, theme.colorScheme.surfaceTint);
|
||||
expect(
|
||||
chipMaterial.shape,
|
||||
const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(Radius.circular(8.0)),
|
||||
side: BorderSide(color: Colors.transparent),
|
||||
),
|
||||
);
|
||||
|
||||
ShapeDecoration decoration = tester.widget<Ink>(find.byType(Ink)).decoration! as ShapeDecoration;
|
||||
expect(decoration.color, null);
|
||||
|
||||
// Test disabled FilterChip.elevated defaults.
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
theme: theme,
|
||||
home: const Material(
|
||||
child: FilterChip.elevated(
|
||||
onSelected: null,
|
||||
label: Text(label),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
chipMaterial = getMaterial(tester);
|
||||
expect(chipMaterial.elevation, 0);
|
||||
expect(chipMaterial.shadowColor, theme.colorScheme.shadow);
|
||||
expect(chipMaterial.surfaceTintColor, theme.colorScheme.surfaceTint);
|
||||
expect(
|
||||
chipMaterial.shape,
|
||||
const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(Radius.circular(8.0)),
|
||||
side: BorderSide(color: Colors.transparent),
|
||||
),
|
||||
);
|
||||
|
||||
decoration = tester.widget<Ink>(find.byType(Ink)).decoration! as ShapeDecoration;
|
||||
expect(decoration.color, theme.colorScheme.onSurface.withOpacity(0.12));
|
||||
|
||||
// Test selected enabled FilterChip.elevated defaults.
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
theme: theme,
|
||||
home: Material(
|
||||
child: FilterChip.elevated(
|
||||
selected: true,
|
||||
onSelected: (bool valueChanged) { },
|
||||
label: const Text(label),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
chipMaterial = getMaterial(tester);
|
||||
expect(chipMaterial.elevation, 1);
|
||||
expect(chipMaterial.shadowColor, null);
|
||||
expect(chipMaterial.surfaceTintColor, theme.colorScheme.surfaceTint);
|
||||
expect(
|
||||
chipMaterial.shape,
|
||||
const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(Radius.circular(8.0)),
|
||||
side: BorderSide(color: Colors.transparent),
|
||||
),
|
||||
);
|
||||
|
||||
decoration = tester.widget<Ink>(find.byType(Ink)).decoration! as ShapeDecoration;
|
||||
expect(decoration.color, theme.colorScheme.secondaryContainer);
|
||||
|
||||
// Test selected disabled FilterChip.elevated defaults.
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
theme: theme,
|
||||
home: const Material(
|
||||
child: FilterChip.elevated(
|
||||
selected: true,
|
||||
onSelected: null,
|
||||
label: Text(label),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
chipMaterial = getMaterial(tester);
|
||||
expect(chipMaterial.elevation, 0);
|
||||
expect(chipMaterial.shadowColor, null);
|
||||
expect(chipMaterial.surfaceTintColor, theme.colorScheme.surfaceTint);
|
||||
expect(
|
||||
chipMaterial.shape,
|
||||
const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(Radius.circular(8.0)),
|
||||
side: BorderSide(color: Colors.transparent),
|
||||
),
|
||||
);
|
||||
|
||||
decoration = tester.widget<Ink>(find.byType(Ink)).decoration! as ShapeDecoration;
|
||||
expect(decoration.color, theme.colorScheme.onSurface.withOpacity(0.12));
|
||||
});
|
||||
|
||||
testWidgets('FilterChip can be tapped', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
|
Loading…
x
Reference in New Issue
Block a user