Refactor chip class and move independent chips into separate classes (#101507)
This commit is contained in:
parent
0675471207
commit
0f2b1a3baf
@ -45,6 +45,10 @@ export 'src/material/checkbox.dart';
|
|||||||
export 'src/material/checkbox_list_tile.dart';
|
export 'src/material/checkbox_list_tile.dart';
|
||||||
export 'src/material/checkbox_theme.dart';
|
export 'src/material/checkbox_theme.dart';
|
||||||
export 'src/material/chip.dart';
|
export 'src/material/chip.dart';
|
||||||
|
export 'src/material/chip_action.dart';
|
||||||
|
export 'src/material/chip_choice.dart';
|
||||||
|
export 'src/material/chip_filter.dart';
|
||||||
|
export 'src/material/chip_input.dart';
|
||||||
export 'src/material/chip_theme.dart';
|
export 'src/material/chip_theme.dart';
|
||||||
export 'src/material/circle_avatar.dart';
|
export 'src/material/circle_avatar.dart';
|
||||||
export 'src/material/color_scheme.dart';
|
export 'src/material/color_scheme.dart';
|
||||||
|
@ -659,777 +659,6 @@ class Chip extends StatelessWidget implements ChipAttributes, DeletableChipAttri
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A material design input chip.
|
|
||||||
///
|
|
||||||
/// Input chips represent a complex piece of information, such as an entity
|
|
||||||
/// (person, place, or thing) or conversational text, in a compact form.
|
|
||||||
///
|
|
||||||
/// Input chips can be made selectable by setting [onSelected], deletable by
|
|
||||||
/// setting [onDeleted], and pressable like a button with [onPressed]. They have
|
|
||||||
/// a [label], and they can have a leading icon (see [avatar]) and a trailing
|
|
||||||
/// icon ([deleteIcon]). Colors and padding can be customized.
|
|
||||||
///
|
|
||||||
/// Requires one of its ancestors to be a [Material] widget.
|
|
||||||
///
|
|
||||||
/// Input chips work together with other UI elements. They can appear:
|
|
||||||
///
|
|
||||||
/// * In a [Wrap] widget.
|
|
||||||
/// * In a horizontally scrollable list, like a [ListView] whose
|
|
||||||
/// scrollDirection is [Axis.horizontal].
|
|
||||||
///
|
|
||||||
/// {@tool snippet}
|
|
||||||
///
|
|
||||||
/// ```dart
|
|
||||||
/// InputChip(
|
|
||||||
/// avatar: CircleAvatar(
|
|
||||||
/// backgroundColor: Colors.grey.shade800,
|
|
||||||
/// child: const Text('AB'),
|
|
||||||
/// ),
|
|
||||||
/// label: const Text('Aaron Burr'),
|
|
||||||
/// onPressed: () {
|
|
||||||
/// print('I am the one thing in life.');
|
|
||||||
/// }
|
|
||||||
/// )
|
|
||||||
/// ```
|
|
||||||
/// {@end-tool}
|
|
||||||
///
|
|
||||||
/// See also:
|
|
||||||
///
|
|
||||||
/// * [Chip], a chip that displays information and can be deleted.
|
|
||||||
/// * [ChoiceChip], allows a single selection from a set of options. Choice
|
|
||||||
/// chips contain related descriptive text or categories.
|
|
||||||
/// * [FilterChip], uses tags or descriptive words as a way to filter content.
|
|
||||||
/// * [ActionChip], represents an action related to primary content.
|
|
||||||
/// * [CircleAvatar], which shows images or initials of people.
|
|
||||||
/// * [Wrap], A widget that displays its children in multiple horizontal or
|
|
||||||
/// vertical runs.
|
|
||||||
/// * <https://material.io/design/components/chips.html>
|
|
||||||
class InputChip extends StatelessWidget
|
|
||||||
implements
|
|
||||||
ChipAttributes,
|
|
||||||
DeletableChipAttributes,
|
|
||||||
SelectableChipAttributes,
|
|
||||||
CheckmarkableChipAttributes,
|
|
||||||
DisabledChipAttributes,
|
|
||||||
TappableChipAttributes {
|
|
||||||
/// Creates an [InputChip].
|
|
||||||
///
|
|
||||||
/// The [onPressed] and [onSelected] callbacks must not both be specified at
|
|
||||||
/// the same time.
|
|
||||||
///
|
|
||||||
/// The [label], [isEnabled], [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 InputChip({
|
|
||||||
Key? key,
|
|
||||||
this.avatar,
|
|
||||||
required this.label,
|
|
||||||
this.labelStyle,
|
|
||||||
this.labelPadding,
|
|
||||||
this.selected = false,
|
|
||||||
this.isEnabled = true,
|
|
||||||
this.onSelected,
|
|
||||||
this.deleteIcon,
|
|
||||||
this.onDeleted,
|
|
||||||
this.deleteIconColor,
|
|
||||||
this.deleteButtonTooltipMessage,
|
|
||||||
this.onPressed,
|
|
||||||
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.selectedShadowColor,
|
|
||||||
this.showCheckmark,
|
|
||||||
this.checkmarkColor,
|
|
||||||
this.avatarBorder = const CircleBorder(),
|
|
||||||
@Deprecated(
|
|
||||||
'Migrate to deleteButtonTooltipMessage. '
|
|
||||||
'This feature was deprecated after v2.10.0-0.3.pre.'
|
|
||||||
)
|
|
||||||
this.useDeleteButtonTooltip = true,
|
|
||||||
}) : assert(selected != null),
|
|
||||||
assert(isEnabled != null),
|
|
||||||
assert(label != null),
|
|
||||||
assert(clipBehavior != null),
|
|
||||||
assert(autofocus != null),
|
|
||||||
assert(pressElevation == null || pressElevation >= 0.0),
|
|
||||||
assert(elevation == null || elevation >= 0.0),
|
|
||||||
super(key: key);
|
|
||||||
|
|
||||||
@override
|
|
||||||
final Widget? avatar;
|
|
||||||
@override
|
|
||||||
final Widget label;
|
|
||||||
@override
|
|
||||||
final TextStyle? labelStyle;
|
|
||||||
@override
|
|
||||||
final EdgeInsetsGeometry? labelPadding;
|
|
||||||
@override
|
|
||||||
final bool selected;
|
|
||||||
@override
|
|
||||||
final bool isEnabled;
|
|
||||||
@override
|
|
||||||
final ValueChanged<bool>? onSelected;
|
|
||||||
@override
|
|
||||||
final Widget? deleteIcon;
|
|
||||||
@override
|
|
||||||
final VoidCallback? onDeleted;
|
|
||||||
@override
|
|
||||||
final Color? deleteIconColor;
|
|
||||||
@override
|
|
||||||
final String? deleteButtonTooltipMessage;
|
|
||||||
@override
|
|
||||||
final VoidCallback? onPressed;
|
|
||||||
@override
|
|
||||||
final double? pressElevation;
|
|
||||||
@override
|
|
||||||
final Color? disabledColor;
|
|
||||||
@override
|
|
||||||
final Color? selectedColor;
|
|
||||||
@override
|
|
||||||
final String? tooltip;
|
|
||||||
@override
|
|
||||||
final BorderSide? side;
|
|
||||||
@override
|
|
||||||
final OutlinedBorder? shape;
|
|
||||||
@override
|
|
||||||
final Clip clipBehavior;
|
|
||||||
@override
|
|
||||||
final FocusNode? focusNode;
|
|
||||||
@override
|
|
||||||
final bool autofocus;
|
|
||||||
@override
|
|
||||||
final Color? backgroundColor;
|
|
||||||
@override
|
|
||||||
final EdgeInsetsGeometry? padding;
|
|
||||||
@override
|
|
||||||
final VisualDensity? visualDensity;
|
|
||||||
@override
|
|
||||||
final MaterialTapTargetSize? materialTapTargetSize;
|
|
||||||
@override
|
|
||||||
final double? elevation;
|
|
||||||
@override
|
|
||||||
final Color? shadowColor;
|
|
||||||
@override
|
|
||||||
final Color? selectedShadowColor;
|
|
||||||
@override
|
|
||||||
final bool? showCheckmark;
|
|
||||||
@override
|
|
||||||
final Color? checkmarkColor;
|
|
||||||
@override
|
|
||||||
final ShapeBorder avatarBorder;
|
|
||||||
@override
|
|
||||||
@Deprecated(
|
|
||||||
'Migrate to deleteButtonTooltipMessage. '
|
|
||||||
'This feature was deprecated after v2.10.0-0.3.pre.'
|
|
||||||
)
|
|
||||||
final bool useDeleteButtonTooltip;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
assert(debugCheckHasMaterial(context));
|
|
||||||
return RawChip(
|
|
||||||
avatar: avatar,
|
|
||||||
label: label,
|
|
||||||
labelStyle: labelStyle,
|
|
||||||
labelPadding: labelPadding,
|
|
||||||
deleteIcon: deleteIcon,
|
|
||||||
onDeleted: onDeleted,
|
|
||||||
deleteIconColor: deleteIconColor,
|
|
||||||
useDeleteButtonTooltip: useDeleteButtonTooltip,
|
|
||||||
deleteButtonTooltipMessage: deleteButtonTooltipMessage,
|
|
||||||
onSelected: onSelected,
|
|
||||||
onPressed: onPressed,
|
|
||||||
pressElevation: pressElevation,
|
|
||||||
selected: selected,
|
|
||||||
disabledColor: disabledColor,
|
|
||||||
selectedColor: selectedColor,
|
|
||||||
tooltip: tooltip,
|
|
||||||
side: side,
|
|
||||||
shape: shape,
|
|
||||||
clipBehavior: clipBehavior,
|
|
||||||
focusNode: focusNode,
|
|
||||||
autofocus: autofocus,
|
|
||||||
backgroundColor: backgroundColor,
|
|
||||||
padding: padding,
|
|
||||||
visualDensity: visualDensity,
|
|
||||||
materialTapTargetSize: materialTapTargetSize,
|
|
||||||
elevation: elevation,
|
|
||||||
shadowColor: shadowColor,
|
|
||||||
selectedShadowColor: selectedShadowColor,
|
|
||||||
showCheckmark: showCheckmark,
|
|
||||||
checkmarkColor: checkmarkColor,
|
|
||||||
isEnabled: isEnabled && (onSelected != null || onDeleted != null || onPressed != null),
|
|
||||||
avatarBorder: avatarBorder,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A material design choice chip.
|
|
||||||
///
|
|
||||||
/// [ChoiceChip]s represent a single choice from a set. Choice chips contain
|
|
||||||
/// related descriptive text or categories.
|
|
||||||
///
|
|
||||||
/// Requires one of its ancestors to be a [Material] widget. The [selected] and
|
|
||||||
/// [label] arguments must not be null.
|
|
||||||
///
|
|
||||||
/// {@tool snippet}
|
|
||||||
///
|
|
||||||
/// ```dart
|
|
||||||
/// class MyThreeOptions extends StatefulWidget {
|
|
||||||
/// const MyThreeOptions({Key? key}) : super(key: key);
|
|
||||||
///
|
|
||||||
/// @override
|
|
||||||
/// State<MyThreeOptions> createState() => _MyThreeOptionsState();
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// class _MyThreeOptionsState extends State<MyThreeOptions> {
|
|
||||||
/// int? _value = 1;
|
|
||||||
///
|
|
||||||
/// @override
|
|
||||||
/// Widget build(BuildContext context) {
|
|
||||||
/// return Wrap(
|
|
||||||
/// children: List<Widget>.generate(
|
|
||||||
/// 3,
|
|
||||||
/// (int index) {
|
|
||||||
/// return ChoiceChip(
|
|
||||||
/// label: Text('Item $index'),
|
|
||||||
/// selected: _value == index,
|
|
||||||
/// onSelected: (bool selected) {
|
|
||||||
/// setState(() {
|
|
||||||
/// _value = selected ? index : null;
|
|
||||||
/// });
|
|
||||||
/// },
|
|
||||||
/// );
|
|
||||||
/// },
|
|
||||||
/// ).toList(),
|
|
||||||
/// );
|
|
||||||
/// }
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
/// {@end-tool}
|
|
||||||
///
|
|
||||||
/// See also:
|
|
||||||
///
|
|
||||||
/// * [Chip], a chip that displays information and can be deleted.
|
|
||||||
/// * [InputChip], a chip that represents a complex piece of information, such
|
|
||||||
/// as an entity (person, place, or thing) or conversational text, in a
|
|
||||||
/// compact form.
|
|
||||||
/// * [FilterChip], uses tags or descriptive words as a way to filter content.
|
|
||||||
/// * [ActionChip], represents an action related to primary content.
|
|
||||||
/// * [CircleAvatar], which shows images or initials of people.
|
|
||||||
/// * [Wrap], A widget that displays its children in multiple horizontal or
|
|
||||||
/// vertical runs.
|
|
||||||
/// * <https://material.io/design/components/chips.html>
|
|
||||||
class ChoiceChip extends StatelessWidget
|
|
||||||
implements
|
|
||||||
ChipAttributes,
|
|
||||||
SelectableChipAttributes,
|
|
||||||
DisabledChipAttributes {
|
|
||||||
/// Create a 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({
|
|
||||||
Key? 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.selectedShadowColor,
|
|
||||||
this.avatarBorder = const CircleBorder(),
|
|
||||||
}) : assert(selected != null),
|
|
||||||
assert(label != null),
|
|
||||||
assert(clipBehavior != null),
|
|
||||||
assert(autofocus != null),
|
|
||||||
assert(pressElevation == null || pressElevation >= 0.0),
|
|
||||||
assert(elevation == null || elevation >= 0.0),
|
|
||||||
super(key: key);
|
|
||||||
|
|
||||||
@override
|
|
||||||
final Widget? avatar;
|
|
||||||
@override
|
|
||||||
final Widget label;
|
|
||||||
@override
|
|
||||||
final TextStyle? labelStyle;
|
|
||||||
@override
|
|
||||||
final EdgeInsetsGeometry? labelPadding;
|
|
||||||
@override
|
|
||||||
final ValueChanged<bool>? onSelected;
|
|
||||||
@override
|
|
||||||
final double? pressElevation;
|
|
||||||
@override
|
|
||||||
final bool selected;
|
|
||||||
@override
|
|
||||||
final Color? disabledColor;
|
|
||||||
@override
|
|
||||||
final Color? selectedColor;
|
|
||||||
@override
|
|
||||||
final String? tooltip;
|
|
||||||
@override
|
|
||||||
final BorderSide? side;
|
|
||||||
@override
|
|
||||||
final OutlinedBorder? shape;
|
|
||||||
@override
|
|
||||||
final Clip clipBehavior;
|
|
||||||
@override
|
|
||||||
final FocusNode? focusNode;
|
|
||||||
@override
|
|
||||||
final bool autofocus;
|
|
||||||
@override
|
|
||||||
final Color? backgroundColor;
|
|
||||||
@override
|
|
||||||
final EdgeInsetsGeometry? padding;
|
|
||||||
@override
|
|
||||||
final VisualDensity? visualDensity;
|
|
||||||
@override
|
|
||||||
final MaterialTapTargetSize? materialTapTargetSize;
|
|
||||||
@override
|
|
||||||
final double? elevation;
|
|
||||||
@override
|
|
||||||
final Color? shadowColor;
|
|
||||||
@override
|
|
||||||
final Color? selectedShadowColor;
|
|
||||||
@override
|
|
||||||
final ShapeBorder avatarBorder;
|
|
||||||
|
|
||||||
@override
|
|
||||||
bool get isEnabled => onSelected != null;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
assert(debugCheckHasMaterial(context));
|
|
||||||
final ChipThemeData chipTheme = ChipTheme.of(context);
|
|
||||||
return RawChip(
|
|
||||||
avatar: avatar,
|
|
||||||
label: label,
|
|
||||||
labelStyle: labelStyle ?? (selected ? chipTheme.secondaryLabelStyle : null),
|
|
||||||
labelPadding: labelPadding,
|
|
||||||
onSelected: onSelected,
|
|
||||||
pressElevation: pressElevation,
|
|
||||||
selected: selected,
|
|
||||||
showCheckmark: false,
|
|
||||||
tooltip: tooltip,
|
|
||||||
side: side,
|
|
||||||
shape: shape,
|
|
||||||
clipBehavior: clipBehavior,
|
|
||||||
focusNode: focusNode,
|
|
||||||
autofocus: autofocus,
|
|
||||||
disabledColor: disabledColor,
|
|
||||||
selectedColor: selectedColor ?? chipTheme.secondarySelectedColor,
|
|
||||||
backgroundColor: backgroundColor,
|
|
||||||
padding: padding,
|
|
||||||
visualDensity: visualDensity,
|
|
||||||
isEnabled: isEnabled,
|
|
||||||
materialTapTargetSize: materialTapTargetSize,
|
|
||||||
elevation: elevation,
|
|
||||||
shadowColor: shadowColor,
|
|
||||||
selectedShadowColor: selectedShadowColor,
|
|
||||||
avatarBorder: avatarBorder,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A material design filter chip.
|
|
||||||
///
|
|
||||||
/// Filter chips use tags or descriptive words as a way to filter content.
|
|
||||||
///
|
|
||||||
/// Filter chips are a good alternative to [Checkbox] or [Switch] widgets.
|
|
||||||
/// Unlike these alternatives, filter chips allow for clearly delineated and
|
|
||||||
/// exposed options in a compact area.
|
|
||||||
///
|
|
||||||
/// Requires one of its ancestors to be a [Material] widget.
|
|
||||||
///
|
|
||||||
/// {@tool snippet}
|
|
||||||
///
|
|
||||||
/// ```dart
|
|
||||||
/// class ActorFilterEntry {
|
|
||||||
/// const ActorFilterEntry(this.name, this.initials);
|
|
||||||
/// final String name;
|
|
||||||
/// final String initials;
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// class CastFilter extends StatefulWidget {
|
|
||||||
/// const CastFilter({Key? key}) : super(key: key);
|
|
||||||
///
|
|
||||||
/// @override
|
|
||||||
/// State createState() => CastFilterState();
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// class CastFilterState extends State<CastFilter> {
|
|
||||||
/// final List<ActorFilterEntry> _cast = <ActorFilterEntry>[
|
|
||||||
/// const ActorFilterEntry('Aaron Burr', 'AB'),
|
|
||||||
/// const ActorFilterEntry('Alexander Hamilton', 'AH'),
|
|
||||||
/// const ActorFilterEntry('Eliza Hamilton', 'EH'),
|
|
||||||
/// const ActorFilterEntry('James Madison', 'JM'),
|
|
||||||
/// ];
|
|
||||||
/// final List<String> _filters = <String>[];
|
|
||||||
///
|
|
||||||
/// Iterable<Widget> get actorWidgets {
|
|
||||||
/// return _cast.map((ActorFilterEntry actor) {
|
|
||||||
/// return Padding(
|
|
||||||
/// padding: const EdgeInsets.all(4.0),
|
|
||||||
/// child: FilterChip(
|
|
||||||
/// avatar: CircleAvatar(child: Text(actor.initials)),
|
|
||||||
/// label: Text(actor.name),
|
|
||||||
/// selected: _filters.contains(actor.name),
|
|
||||||
/// onSelected: (bool value) {
|
|
||||||
/// setState(() {
|
|
||||||
/// if (value) {
|
|
||||||
/// _filters.add(actor.name);
|
|
||||||
/// } else {
|
|
||||||
/// _filters.removeWhere((String name) {
|
|
||||||
/// return name == actor.name;
|
|
||||||
/// });
|
|
||||||
/// }
|
|
||||||
/// });
|
|
||||||
/// },
|
|
||||||
/// ),
|
|
||||||
/// );
|
|
||||||
/// });
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// @override
|
|
||||||
/// Widget build(BuildContext context) {
|
|
||||||
/// return Column(
|
|
||||||
/// mainAxisAlignment: MainAxisAlignment.center,
|
|
||||||
/// children: <Widget>[
|
|
||||||
/// Wrap(
|
|
||||||
/// children: actorWidgets.toList(),
|
|
||||||
/// ),
|
|
||||||
/// Text('Look for: ${_filters.join(', ')}'),
|
|
||||||
/// ],
|
|
||||||
/// );
|
|
||||||
/// }
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
/// {@end-tool}
|
|
||||||
///
|
|
||||||
/// See also:
|
|
||||||
///
|
|
||||||
/// * [Chip], a chip that displays information and can be deleted.
|
|
||||||
/// * [InputChip], a chip that represents a complex piece of information, such
|
|
||||||
/// as an entity (person, place, or thing) or conversational text, in a
|
|
||||||
/// compact form.
|
|
||||||
/// * [ChoiceChip], allows a single selection from a set of options. Choice
|
|
||||||
/// chips contain related descriptive text or categories.
|
|
||||||
/// * [ActionChip], represents an action related to primary content.
|
|
||||||
/// * [CircleAvatar], which shows images or initials of people.
|
|
||||||
/// * [Wrap], A widget that displays its children in multiple horizontal or
|
|
||||||
/// vertical runs.
|
|
||||||
/// * <https://material.io/design/components/chips.html>
|
|
||||||
class FilterChip extends StatelessWidget
|
|
||||||
implements
|
|
||||||
ChipAttributes,
|
|
||||||
SelectableChipAttributes,
|
|
||||||
CheckmarkableChipAttributes,
|
|
||||||
DisabledChipAttributes {
|
|
||||||
/// Create a 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({
|
|
||||||
Key? 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.selectedShadowColor,
|
|
||||||
this.showCheckmark,
|
|
||||||
this.checkmarkColor,
|
|
||||||
this.avatarBorder = const CircleBorder(),
|
|
||||||
}) : assert(selected != null),
|
|
||||||
assert(label != null),
|
|
||||||
assert(clipBehavior != null),
|
|
||||||
assert(autofocus != null),
|
|
||||||
assert(pressElevation == null || pressElevation >= 0.0),
|
|
||||||
assert(elevation == null || elevation >= 0.0),
|
|
||||||
super(key: key);
|
|
||||||
|
|
||||||
@override
|
|
||||||
final Widget? avatar;
|
|
||||||
@override
|
|
||||||
final Widget label;
|
|
||||||
@override
|
|
||||||
final TextStyle? labelStyle;
|
|
||||||
@override
|
|
||||||
final EdgeInsetsGeometry? labelPadding;
|
|
||||||
@override
|
|
||||||
final bool selected;
|
|
||||||
@override
|
|
||||||
final ValueChanged<bool>? onSelected;
|
|
||||||
@override
|
|
||||||
final double? pressElevation;
|
|
||||||
@override
|
|
||||||
final Color? disabledColor;
|
|
||||||
@override
|
|
||||||
final Color? selectedColor;
|
|
||||||
@override
|
|
||||||
final String? tooltip;
|
|
||||||
@override
|
|
||||||
final BorderSide? side;
|
|
||||||
@override
|
|
||||||
final OutlinedBorder? shape;
|
|
||||||
@override
|
|
||||||
final Clip clipBehavior;
|
|
||||||
@override
|
|
||||||
final FocusNode? focusNode;
|
|
||||||
@override
|
|
||||||
final bool autofocus;
|
|
||||||
@override
|
|
||||||
final Color? backgroundColor;
|
|
||||||
@override
|
|
||||||
final EdgeInsetsGeometry? padding;
|
|
||||||
@override
|
|
||||||
final VisualDensity? visualDensity;
|
|
||||||
@override
|
|
||||||
final MaterialTapTargetSize? materialTapTargetSize;
|
|
||||||
@override
|
|
||||||
final double? elevation;
|
|
||||||
@override
|
|
||||||
final Color? shadowColor;
|
|
||||||
@override
|
|
||||||
final Color? selectedShadowColor;
|
|
||||||
@override
|
|
||||||
final bool? showCheckmark;
|
|
||||||
@override
|
|
||||||
final Color? checkmarkColor;
|
|
||||||
@override
|
|
||||||
final ShapeBorder avatarBorder;
|
|
||||||
|
|
||||||
@override
|
|
||||||
bool get isEnabled => onSelected != null;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
assert(debugCheckHasMaterial(context));
|
|
||||||
return RawChip(
|
|
||||||
avatar: avatar,
|
|
||||||
label: label,
|
|
||||||
labelStyle: labelStyle,
|
|
||||||
labelPadding: labelPadding,
|
|
||||||
onSelected: onSelected,
|
|
||||||
pressElevation: pressElevation,
|
|
||||||
selected: selected,
|
|
||||||
tooltip: tooltip,
|
|
||||||
side: side,
|
|
||||||
shape: shape,
|
|
||||||
clipBehavior: clipBehavior,
|
|
||||||
focusNode: focusNode,
|
|
||||||
autofocus: autofocus,
|
|
||||||
backgroundColor: backgroundColor,
|
|
||||||
disabledColor: disabledColor,
|
|
||||||
selectedColor: selectedColor,
|
|
||||||
padding: padding,
|
|
||||||
visualDensity: visualDensity,
|
|
||||||
isEnabled: isEnabled,
|
|
||||||
materialTapTargetSize: materialTapTargetSize,
|
|
||||||
elevation: elevation,
|
|
||||||
shadowColor: shadowColor,
|
|
||||||
selectedShadowColor: selectedShadowColor,
|
|
||||||
showCheckmark: showCheckmark,
|
|
||||||
checkmarkColor: checkmarkColor,
|
|
||||||
avatarBorder: avatarBorder,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A material design action chip.
|
|
||||||
///
|
|
||||||
/// Action chips are a set of options which trigger an action related to primary
|
|
||||||
/// content. Action chips should appear dynamically and contextually in a UI.
|
|
||||||
///
|
|
||||||
/// Action chips can be tapped to trigger an action or show progress and
|
|
||||||
/// confirmation. They cannot be disabled; if the action is not applicable, the
|
|
||||||
/// chip should not be included in the interface. (This contrasts with buttons,
|
|
||||||
/// where unavailable choices are usually represented as disabled controls.)
|
|
||||||
///
|
|
||||||
/// Action chips are displayed after primary content, such as below a card or
|
|
||||||
/// persistently at the bottom of a screen.
|
|
||||||
///
|
|
||||||
/// The material button widgets, [ElevatedButton], [TextButton], and
|
|
||||||
/// [OutlinedButton], are an alternative to action chips, which should appear
|
|
||||||
/// statically and consistently in a UI.
|
|
||||||
///
|
|
||||||
/// Requires one of its ancestors to be a [Material] widget.
|
|
||||||
///
|
|
||||||
/// {@tool snippet}
|
|
||||||
///
|
|
||||||
/// ```dart
|
|
||||||
/// ActionChip(
|
|
||||||
/// avatar: CircleAvatar(
|
|
||||||
/// backgroundColor: Colors.grey.shade800,
|
|
||||||
/// child: const Text('AB'),
|
|
||||||
/// ),
|
|
||||||
/// label: const Text('Aaron Burr'),
|
|
||||||
/// onPressed: () {
|
|
||||||
/// print('If you stand for nothing, Burr, what’ll you fall for?');
|
|
||||||
/// }
|
|
||||||
/// )
|
|
||||||
/// ```
|
|
||||||
/// {@end-tool}
|
|
||||||
///
|
|
||||||
/// See also:
|
|
||||||
///
|
|
||||||
/// * [Chip], a chip that displays information and can be deleted.
|
|
||||||
/// * [InputChip], a chip that represents a complex piece of information, such
|
|
||||||
/// as an entity (person, place, or thing) or conversational text, in a
|
|
||||||
/// compact form.
|
|
||||||
/// * [ChoiceChip], allows a single selection from a set of options. Choice
|
|
||||||
/// chips contain related descriptive text or categories.
|
|
||||||
/// * [CircleAvatar], which shows images or initials of people.
|
|
||||||
/// * [Wrap], A widget that displays its children in multiple horizontal or
|
|
||||||
/// vertical runs.
|
|
||||||
/// * <https://material.io/design/components/chips.html>
|
|
||||||
class ActionChip extends StatelessWidget implements ChipAttributes, TappableChipAttributes {
|
|
||||||
/// Create a 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({
|
|
||||||
Key? key,
|
|
||||||
this.avatar,
|
|
||||||
required this.label,
|
|
||||||
this.labelStyle,
|
|
||||||
this.labelPadding,
|
|
||||||
required this.onPressed,
|
|
||||||
this.pressElevation,
|
|
||||||
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,
|
|
||||||
}) : assert(label != null),
|
|
||||||
assert(clipBehavior != null),
|
|
||||||
assert(autofocus != null),
|
|
||||||
assert(
|
|
||||||
onPressed != null,
|
|
||||||
'Rather than disabling an ActionChip by setting onPressed to null, '
|
|
||||||
'remove it from the interface entirely.',
|
|
||||||
),
|
|
||||||
assert(pressElevation == null || pressElevation >= 0.0),
|
|
||||||
assert(elevation == null || elevation >= 0.0),
|
|
||||||
super(key: key);
|
|
||||||
|
|
||||||
@override
|
|
||||||
final Widget? avatar;
|
|
||||||
@override
|
|
||||||
final Widget label;
|
|
||||||
@override
|
|
||||||
final TextStyle? labelStyle;
|
|
||||||
@override
|
|
||||||
final EdgeInsetsGeometry? labelPadding;
|
|
||||||
@override
|
|
||||||
final VoidCallback onPressed;
|
|
||||||
@override
|
|
||||||
final double? pressElevation;
|
|
||||||
@override
|
|
||||||
final String? tooltip;
|
|
||||||
@override
|
|
||||||
final BorderSide? side;
|
|
||||||
@override
|
|
||||||
final OutlinedBorder? shape;
|
|
||||||
@override
|
|
||||||
final Clip clipBehavior;
|
|
||||||
@override
|
|
||||||
final FocusNode? focusNode;
|
|
||||||
@override
|
|
||||||
final bool autofocus;
|
|
||||||
@override
|
|
||||||
final Color? backgroundColor;
|
|
||||||
@override
|
|
||||||
final EdgeInsetsGeometry? padding;
|
|
||||||
@override
|
|
||||||
final VisualDensity? visualDensity;
|
|
||||||
@override
|
|
||||||
final MaterialTapTargetSize? materialTapTargetSize;
|
|
||||||
@override
|
|
||||||
final double? elevation;
|
|
||||||
@override
|
|
||||||
final Color? shadowColor;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
assert(debugCheckHasMaterial(context));
|
|
||||||
return RawChip(
|
|
||||||
avatar: avatar,
|
|
||||||
label: label,
|
|
||||||
onPressed: onPressed,
|
|
||||||
pressElevation: pressElevation,
|
|
||||||
tooltip: tooltip,
|
|
||||||
labelStyle: labelStyle,
|
|
||||||
backgroundColor: backgroundColor,
|
|
||||||
side: side,
|
|
||||||
shape: shape,
|
|
||||||
clipBehavior: clipBehavior,
|
|
||||||
focusNode: focusNode,
|
|
||||||
autofocus: autofocus,
|
|
||||||
padding: padding,
|
|
||||||
visualDensity: visualDensity,
|
|
||||||
labelPadding: labelPadding,
|
|
||||||
materialTapTargetSize: materialTapTargetSize,
|
|
||||||
elevation: elevation,
|
|
||||||
shadowColor: shadowColor,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A raw material design chip.
|
/// A raw material design chip.
|
||||||
///
|
///
|
||||||
/// This serves as the basis for all of the chip widget types to aggregate.
|
/// This serves as the basis for all of the chip widget types to aggregate.
|
||||||
|
157
packages/flutter/lib/src/material/chip_action.dart
Normal file
157
packages/flutter/lib/src/material/chip_action.dart
Normal file
@ -0,0 +1,157 @@
|
|||||||
|
// 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/widgets.dart';
|
||||||
|
|
||||||
|
import 'chip.dart';
|
||||||
|
import 'debug.dart';
|
||||||
|
import 'theme_data.dart';
|
||||||
|
|
||||||
|
/// A material design action chip.
|
||||||
|
///
|
||||||
|
/// Action chips are a set of options which trigger an action related to primary
|
||||||
|
/// content. Action chips should appear dynamically and contextually in a UI.
|
||||||
|
///
|
||||||
|
/// Action chips can be tapped to trigger an action or show progress and
|
||||||
|
/// confirmation. They cannot be disabled; if the action is not applicable, the
|
||||||
|
/// chip should not be included in the interface. (This contrasts with buttons,
|
||||||
|
/// where unavailable choices are usually represented as disabled controls.)
|
||||||
|
///
|
||||||
|
/// Action chips are displayed after primary content, such as below a card or
|
||||||
|
/// persistently at the bottom of a screen.
|
||||||
|
///
|
||||||
|
/// The material button widgets, [ElevatedButton], [TextButton], and
|
||||||
|
/// [OutlinedButton], are an alternative to action chips, which should appear
|
||||||
|
/// statically and consistently in a UI.
|
||||||
|
///
|
||||||
|
/// Requires one of its ancestors to be a [Material] widget.
|
||||||
|
///
|
||||||
|
/// {@tool snippet}
|
||||||
|
///
|
||||||
|
/// ```dart
|
||||||
|
/// ActionChip(
|
||||||
|
/// avatar: CircleAvatar(
|
||||||
|
/// backgroundColor: Colors.grey.shade800,
|
||||||
|
/// child: const Text('AB'),
|
||||||
|
/// ),
|
||||||
|
/// label: const Text('Aaron Burr'),
|
||||||
|
/// onPressed: () {
|
||||||
|
/// print('If you stand for nothing, Burr, what’ll you fall for?');
|
||||||
|
/// }
|
||||||
|
/// )
|
||||||
|
/// ```
|
||||||
|
/// {@end-tool}
|
||||||
|
///
|
||||||
|
/// See also:
|
||||||
|
///
|
||||||
|
/// * [Chip], a chip that displays information and can be deleted.
|
||||||
|
/// * [InputChip], a chip that represents a complex piece of information, such
|
||||||
|
/// as an entity (person, place, or thing) or conversational text, in a
|
||||||
|
/// compact form.
|
||||||
|
/// * [ChoiceChip], allows a single selection from a set of options. Choice
|
||||||
|
/// chips contain related descriptive text or categories.
|
||||||
|
/// * [CircleAvatar], which shows images or initials of people.
|
||||||
|
/// * [Wrap], A widget that displays its children in multiple horizontal or
|
||||||
|
/// vertical runs.
|
||||||
|
/// * <https://material.io/design/components/chips.html>
|
||||||
|
class ActionChip extends StatelessWidget implements ChipAttributes, TappableChipAttributes {
|
||||||
|
/// Create a 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({
|
||||||
|
Key? key,
|
||||||
|
this.avatar,
|
||||||
|
required this.label,
|
||||||
|
this.labelStyle,
|
||||||
|
this.labelPadding,
|
||||||
|
required this.onPressed,
|
||||||
|
this.pressElevation,
|
||||||
|
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,
|
||||||
|
}) : assert(label != null),
|
||||||
|
assert(clipBehavior != null),
|
||||||
|
assert(autofocus != null),
|
||||||
|
assert(
|
||||||
|
onPressed != null,
|
||||||
|
'Rather than disabling an ActionChip by setting onPressed to null, '
|
||||||
|
'remove it from the interface entirely.',
|
||||||
|
),
|
||||||
|
assert(pressElevation == null || pressElevation >= 0.0),
|
||||||
|
assert(elevation == null || elevation >= 0.0),
|
||||||
|
super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
final Widget? avatar;
|
||||||
|
@override
|
||||||
|
final Widget label;
|
||||||
|
@override
|
||||||
|
final TextStyle? labelStyle;
|
||||||
|
@override
|
||||||
|
final EdgeInsetsGeometry? labelPadding;
|
||||||
|
@override
|
||||||
|
final VoidCallback onPressed;
|
||||||
|
@override
|
||||||
|
final double? pressElevation;
|
||||||
|
@override
|
||||||
|
final String? tooltip;
|
||||||
|
@override
|
||||||
|
final BorderSide? side;
|
||||||
|
@override
|
||||||
|
final OutlinedBorder? shape;
|
||||||
|
@override
|
||||||
|
final Clip clipBehavior;
|
||||||
|
@override
|
||||||
|
final FocusNode? focusNode;
|
||||||
|
@override
|
||||||
|
final bool autofocus;
|
||||||
|
@override
|
||||||
|
final Color? backgroundColor;
|
||||||
|
@override
|
||||||
|
final EdgeInsetsGeometry? padding;
|
||||||
|
@override
|
||||||
|
final VisualDensity? visualDensity;
|
||||||
|
@override
|
||||||
|
final MaterialTapTargetSize? materialTapTargetSize;
|
||||||
|
@override
|
||||||
|
final double? elevation;
|
||||||
|
@override
|
||||||
|
final Color? shadowColor;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
assert(debugCheckHasMaterial(context));
|
||||||
|
return RawChip(
|
||||||
|
avatar: avatar,
|
||||||
|
label: label,
|
||||||
|
onPressed: onPressed,
|
||||||
|
pressElevation: pressElevation,
|
||||||
|
tooltip: tooltip,
|
||||||
|
labelStyle: labelStyle,
|
||||||
|
backgroundColor: backgroundColor,
|
||||||
|
side: side,
|
||||||
|
shape: shape,
|
||||||
|
clipBehavior: clipBehavior,
|
||||||
|
focusNode: focusNode,
|
||||||
|
autofocus: autofocus,
|
||||||
|
padding: padding,
|
||||||
|
visualDensity: visualDensity,
|
||||||
|
labelPadding: labelPadding,
|
||||||
|
materialTapTargetSize: materialTapTargetSize,
|
||||||
|
elevation: elevation,
|
||||||
|
shadowColor: shadowColor,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
193
packages/flutter/lib/src/material/chip_choice.dart
Normal file
193
packages/flutter/lib/src/material/chip_choice.dart
Normal file
@ -0,0 +1,193 @@
|
|||||||
|
// 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/widgets.dart';
|
||||||
|
|
||||||
|
import 'chip.dart';
|
||||||
|
import 'chip_theme.dart';
|
||||||
|
import 'debug.dart';
|
||||||
|
import 'theme_data.dart';
|
||||||
|
|
||||||
|
/// A material design choice chip.
|
||||||
|
///
|
||||||
|
/// [ChoiceChip]s represent a single choice from a set. Choice chips contain
|
||||||
|
/// related descriptive text or categories.
|
||||||
|
///
|
||||||
|
/// Requires one of its ancestors to be a [Material] widget. The [selected] and
|
||||||
|
/// [label] arguments must not be null.
|
||||||
|
///
|
||||||
|
/// {@tool snippet}
|
||||||
|
///
|
||||||
|
/// ```dart
|
||||||
|
/// class MyThreeOptions extends StatefulWidget {
|
||||||
|
/// const MyThreeOptions({Key? key}) : super(key: key);
|
||||||
|
///
|
||||||
|
/// @override
|
||||||
|
/// State<MyThreeOptions> createState() => _MyThreeOptionsState();
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// class _MyThreeOptionsState extends State<MyThreeOptions> {
|
||||||
|
/// int? _value = 1;
|
||||||
|
///
|
||||||
|
/// @override
|
||||||
|
/// Widget build(BuildContext context) {
|
||||||
|
/// return Wrap(
|
||||||
|
/// children: List<Widget>.generate(
|
||||||
|
/// 3,
|
||||||
|
/// (int index) {
|
||||||
|
/// return ChoiceChip(
|
||||||
|
/// label: Text('Item $index'),
|
||||||
|
/// selected: _value == index,
|
||||||
|
/// onSelected: (bool selected) {
|
||||||
|
/// setState(() {
|
||||||
|
/// _value = selected ? index : null;
|
||||||
|
/// });
|
||||||
|
/// },
|
||||||
|
/// );
|
||||||
|
/// },
|
||||||
|
/// ).toList(),
|
||||||
|
/// );
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
/// {@end-tool}
|
||||||
|
///
|
||||||
|
/// See also:
|
||||||
|
///
|
||||||
|
/// * [Chip], a chip that displays information and can be deleted.
|
||||||
|
/// * [InputChip], a chip that represents a complex piece of information, such
|
||||||
|
/// as an entity (person, place, or thing) or conversational text, in a
|
||||||
|
/// compact form.
|
||||||
|
/// * [FilterChip], uses tags or descriptive words as a way to filter content.
|
||||||
|
/// * [ActionChip], represents an action related to primary content.
|
||||||
|
/// * [CircleAvatar], which shows images or initials of people.
|
||||||
|
/// * [Wrap], A widget that displays its children in multiple horizontal or
|
||||||
|
/// vertical runs.
|
||||||
|
/// * <https://material.io/design/components/chips.html>
|
||||||
|
class ChoiceChip extends StatelessWidget
|
||||||
|
implements
|
||||||
|
ChipAttributes,
|
||||||
|
SelectableChipAttributes,
|
||||||
|
DisabledChipAttributes {
|
||||||
|
/// Create a 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({
|
||||||
|
Key? 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.selectedShadowColor,
|
||||||
|
this.avatarBorder = const CircleBorder(),
|
||||||
|
}) : assert(selected != null),
|
||||||
|
assert(label != null),
|
||||||
|
assert(clipBehavior != null),
|
||||||
|
assert(autofocus != null),
|
||||||
|
assert(pressElevation == null || pressElevation >= 0.0),
|
||||||
|
assert(elevation == null || elevation >= 0.0),
|
||||||
|
super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
final Widget? avatar;
|
||||||
|
@override
|
||||||
|
final Widget label;
|
||||||
|
@override
|
||||||
|
final TextStyle? labelStyle;
|
||||||
|
@override
|
||||||
|
final EdgeInsetsGeometry? labelPadding;
|
||||||
|
@override
|
||||||
|
final ValueChanged<bool>? onSelected;
|
||||||
|
@override
|
||||||
|
final double? pressElevation;
|
||||||
|
@override
|
||||||
|
final bool selected;
|
||||||
|
@override
|
||||||
|
final Color? disabledColor;
|
||||||
|
@override
|
||||||
|
final Color? selectedColor;
|
||||||
|
@override
|
||||||
|
final String? tooltip;
|
||||||
|
@override
|
||||||
|
final BorderSide? side;
|
||||||
|
@override
|
||||||
|
final OutlinedBorder? shape;
|
||||||
|
@override
|
||||||
|
final Clip clipBehavior;
|
||||||
|
@override
|
||||||
|
final FocusNode? focusNode;
|
||||||
|
@override
|
||||||
|
final bool autofocus;
|
||||||
|
@override
|
||||||
|
final Color? backgroundColor;
|
||||||
|
@override
|
||||||
|
final EdgeInsetsGeometry? padding;
|
||||||
|
@override
|
||||||
|
final VisualDensity? visualDensity;
|
||||||
|
@override
|
||||||
|
final MaterialTapTargetSize? materialTapTargetSize;
|
||||||
|
@override
|
||||||
|
final double? elevation;
|
||||||
|
@override
|
||||||
|
final Color? shadowColor;
|
||||||
|
@override
|
||||||
|
final Color? selectedShadowColor;
|
||||||
|
@override
|
||||||
|
final ShapeBorder avatarBorder;
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool get isEnabled => onSelected != null;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
assert(debugCheckHasMaterial(context));
|
||||||
|
final ChipThemeData chipTheme = ChipTheme.of(context);
|
||||||
|
return RawChip(
|
||||||
|
avatar: avatar,
|
||||||
|
label: label,
|
||||||
|
labelStyle: labelStyle ?? (selected ? chipTheme.secondaryLabelStyle : null),
|
||||||
|
labelPadding: labelPadding,
|
||||||
|
onSelected: onSelected,
|
||||||
|
pressElevation: pressElevation,
|
||||||
|
selected: selected,
|
||||||
|
showCheckmark: false,
|
||||||
|
tooltip: tooltip,
|
||||||
|
side: side,
|
||||||
|
shape: shape,
|
||||||
|
clipBehavior: clipBehavior,
|
||||||
|
focusNode: focusNode,
|
||||||
|
autofocus: autofocus,
|
||||||
|
disabledColor: disabledColor,
|
||||||
|
selectedColor: selectedColor ?? chipTheme.secondarySelectedColor,
|
||||||
|
backgroundColor: backgroundColor,
|
||||||
|
padding: padding,
|
||||||
|
visualDensity: visualDensity,
|
||||||
|
isEnabled: isEnabled,
|
||||||
|
materialTapTargetSize: materialTapTargetSize,
|
||||||
|
elevation: elevation,
|
||||||
|
shadowColor: shadowColor,
|
||||||
|
selectedShadowColor: selectedShadowColor,
|
||||||
|
avatarBorder: avatarBorder,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
231
packages/flutter/lib/src/material/chip_filter.dart
Normal file
231
packages/flutter/lib/src/material/chip_filter.dart
Normal file
@ -0,0 +1,231 @@
|
|||||||
|
// 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/widgets.dart';
|
||||||
|
|
||||||
|
import 'chip.dart';
|
||||||
|
import 'debug.dart';
|
||||||
|
import 'theme_data.dart';
|
||||||
|
|
||||||
|
/// A material design filter chip.
|
||||||
|
///
|
||||||
|
/// Filter chips use tags or descriptive words as a way to filter content.
|
||||||
|
///
|
||||||
|
/// Filter chips are a good alternative to [Checkbox] or [Switch] widgets.
|
||||||
|
/// Unlike these alternatives, filter chips allow for clearly delineated and
|
||||||
|
/// exposed options in a compact area.
|
||||||
|
///
|
||||||
|
/// Requires one of its ancestors to be a [Material] widget.
|
||||||
|
///
|
||||||
|
/// {@tool snippet}
|
||||||
|
///
|
||||||
|
/// ```dart
|
||||||
|
/// class ActorFilterEntry {
|
||||||
|
/// const ActorFilterEntry(this.name, this.initials);
|
||||||
|
/// final String name;
|
||||||
|
/// final String initials;
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// class CastFilter extends StatefulWidget {
|
||||||
|
/// const CastFilter({Key? key}) : super(key: key);
|
||||||
|
///
|
||||||
|
/// @override
|
||||||
|
/// State createState() => CastFilterState();
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// class CastFilterState extends State<CastFilter> {
|
||||||
|
/// final List<ActorFilterEntry> _cast = <ActorFilterEntry>[
|
||||||
|
/// const ActorFilterEntry('Aaron Burr', 'AB'),
|
||||||
|
/// const ActorFilterEntry('Alexander Hamilton', 'AH'),
|
||||||
|
/// const ActorFilterEntry('Eliza Hamilton', 'EH'),
|
||||||
|
/// const ActorFilterEntry('James Madison', 'JM'),
|
||||||
|
/// ];
|
||||||
|
/// final List<String> _filters = <String>[];
|
||||||
|
///
|
||||||
|
/// Iterable<Widget> get actorWidgets {
|
||||||
|
/// return _cast.map((ActorFilterEntry actor) {
|
||||||
|
/// return Padding(
|
||||||
|
/// padding: const EdgeInsets.all(4.0),
|
||||||
|
/// child: FilterChip(
|
||||||
|
/// avatar: CircleAvatar(child: Text(actor.initials)),
|
||||||
|
/// label: Text(actor.name),
|
||||||
|
/// selected: _filters.contains(actor.name),
|
||||||
|
/// onSelected: (bool value) {
|
||||||
|
/// setState(() {
|
||||||
|
/// if (value) {
|
||||||
|
/// _filters.add(actor.name);
|
||||||
|
/// } else {
|
||||||
|
/// _filters.removeWhere((String name) {
|
||||||
|
/// return name == actor.name;
|
||||||
|
/// });
|
||||||
|
/// }
|
||||||
|
/// });
|
||||||
|
/// },
|
||||||
|
/// ),
|
||||||
|
/// );
|
||||||
|
/// });
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// @override
|
||||||
|
/// Widget build(BuildContext context) {
|
||||||
|
/// return Column(
|
||||||
|
/// mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
/// children: <Widget>[
|
||||||
|
/// Wrap(
|
||||||
|
/// children: actorWidgets.toList(),
|
||||||
|
/// ),
|
||||||
|
/// Text('Look for: ${_filters.join(', ')}'),
|
||||||
|
/// ],
|
||||||
|
/// );
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
/// {@end-tool}
|
||||||
|
///
|
||||||
|
/// See also:
|
||||||
|
///
|
||||||
|
/// * [Chip], a chip that displays information and can be deleted.
|
||||||
|
/// * [InputChip], a chip that represents a complex piece of information, such
|
||||||
|
/// as an entity (person, place, or thing) or conversational text, in a
|
||||||
|
/// compact form.
|
||||||
|
/// * [ChoiceChip], allows a single selection from a set of options. Choice
|
||||||
|
/// chips contain related descriptive text or categories.
|
||||||
|
/// * [ActionChip], represents an action related to primary content.
|
||||||
|
/// * [CircleAvatar], which shows images or initials of people.
|
||||||
|
/// * [Wrap], A widget that displays its children in multiple horizontal or
|
||||||
|
/// vertical runs.
|
||||||
|
/// * <https://material.io/design/components/chips.html>
|
||||||
|
class FilterChip extends StatelessWidget
|
||||||
|
implements
|
||||||
|
ChipAttributes,
|
||||||
|
SelectableChipAttributes,
|
||||||
|
CheckmarkableChipAttributes,
|
||||||
|
DisabledChipAttributes {
|
||||||
|
/// Create a 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({
|
||||||
|
Key? 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.selectedShadowColor,
|
||||||
|
this.showCheckmark,
|
||||||
|
this.checkmarkColor,
|
||||||
|
this.avatarBorder = const CircleBorder(),
|
||||||
|
}) : assert(selected != null),
|
||||||
|
assert(label != null),
|
||||||
|
assert(clipBehavior != null),
|
||||||
|
assert(autofocus != null),
|
||||||
|
assert(pressElevation == null || pressElevation >= 0.0),
|
||||||
|
assert(elevation == null || elevation >= 0.0),
|
||||||
|
super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
final Widget? avatar;
|
||||||
|
@override
|
||||||
|
final Widget label;
|
||||||
|
@override
|
||||||
|
final TextStyle? labelStyle;
|
||||||
|
@override
|
||||||
|
final EdgeInsetsGeometry? labelPadding;
|
||||||
|
@override
|
||||||
|
final bool selected;
|
||||||
|
@override
|
||||||
|
final ValueChanged<bool>? onSelected;
|
||||||
|
@override
|
||||||
|
final double? pressElevation;
|
||||||
|
@override
|
||||||
|
final Color? disabledColor;
|
||||||
|
@override
|
||||||
|
final Color? selectedColor;
|
||||||
|
@override
|
||||||
|
final String? tooltip;
|
||||||
|
@override
|
||||||
|
final BorderSide? side;
|
||||||
|
@override
|
||||||
|
final OutlinedBorder? shape;
|
||||||
|
@override
|
||||||
|
final Clip clipBehavior;
|
||||||
|
@override
|
||||||
|
final FocusNode? focusNode;
|
||||||
|
@override
|
||||||
|
final bool autofocus;
|
||||||
|
@override
|
||||||
|
final Color? backgroundColor;
|
||||||
|
@override
|
||||||
|
final EdgeInsetsGeometry? padding;
|
||||||
|
@override
|
||||||
|
final VisualDensity? visualDensity;
|
||||||
|
@override
|
||||||
|
final MaterialTapTargetSize? materialTapTargetSize;
|
||||||
|
@override
|
||||||
|
final double? elevation;
|
||||||
|
@override
|
||||||
|
final Color? shadowColor;
|
||||||
|
@override
|
||||||
|
final Color? selectedShadowColor;
|
||||||
|
@override
|
||||||
|
final bool? showCheckmark;
|
||||||
|
@override
|
||||||
|
final Color? checkmarkColor;
|
||||||
|
@override
|
||||||
|
final ShapeBorder avatarBorder;
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool get isEnabled => onSelected != null;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
assert(debugCheckHasMaterial(context));
|
||||||
|
return RawChip(
|
||||||
|
avatar: avatar,
|
||||||
|
label: label,
|
||||||
|
labelStyle: labelStyle,
|
||||||
|
labelPadding: labelPadding,
|
||||||
|
onSelected: onSelected,
|
||||||
|
pressElevation: pressElevation,
|
||||||
|
selected: selected,
|
||||||
|
tooltip: tooltip,
|
||||||
|
side: side,
|
||||||
|
shape: shape,
|
||||||
|
clipBehavior: clipBehavior,
|
||||||
|
focusNode: focusNode,
|
||||||
|
autofocus: autofocus,
|
||||||
|
backgroundColor: backgroundColor,
|
||||||
|
disabledColor: disabledColor,
|
||||||
|
selectedColor: selectedColor,
|
||||||
|
padding: padding,
|
||||||
|
visualDensity: visualDensity,
|
||||||
|
isEnabled: isEnabled,
|
||||||
|
materialTapTargetSize: materialTapTargetSize,
|
||||||
|
elevation: elevation,
|
||||||
|
shadowColor: shadowColor,
|
||||||
|
selectedShadowColor: selectedShadowColor,
|
||||||
|
showCheckmark: showCheckmark,
|
||||||
|
checkmarkColor: checkmarkColor,
|
||||||
|
avatarBorder: avatarBorder,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
227
packages/flutter/lib/src/material/chip_input.dart
Normal file
227
packages/flutter/lib/src/material/chip_input.dart
Normal file
@ -0,0 +1,227 @@
|
|||||||
|
// 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/widgets.dart';
|
||||||
|
|
||||||
|
import 'chip.dart';
|
||||||
|
import 'debug.dart';
|
||||||
|
import 'theme_data.dart';
|
||||||
|
|
||||||
|
/// A material design input chip.
|
||||||
|
///
|
||||||
|
/// Input chips represent a complex piece of information, such as an entity
|
||||||
|
/// (person, place, or thing) or conversational text, in a compact form.
|
||||||
|
///
|
||||||
|
/// Input chips can be made selectable by setting [onSelected], deletable by
|
||||||
|
/// setting [onDeleted], and pressable like a button with [onPressed]. They have
|
||||||
|
/// a [label], and they can have a leading icon (see [avatar]) and a trailing
|
||||||
|
/// icon ([deleteIcon]). Colors and padding can be customized.
|
||||||
|
///
|
||||||
|
/// Requires one of its ancestors to be a [Material] widget.
|
||||||
|
///
|
||||||
|
/// Input chips work together with other UI elements. They can appear:
|
||||||
|
///
|
||||||
|
/// * In a [Wrap] widget.
|
||||||
|
/// * In a horizontally scrollable list, like a [ListView] whose
|
||||||
|
/// scrollDirection is [Axis.horizontal].
|
||||||
|
///
|
||||||
|
/// {@tool snippet}
|
||||||
|
///
|
||||||
|
/// ```dart
|
||||||
|
/// InputChip(
|
||||||
|
/// avatar: CircleAvatar(
|
||||||
|
/// backgroundColor: Colors.grey.shade800,
|
||||||
|
/// child: const Text('AB'),
|
||||||
|
/// ),
|
||||||
|
/// label: const Text('Aaron Burr'),
|
||||||
|
/// onPressed: () {
|
||||||
|
/// print('I am the one thing in life.');
|
||||||
|
/// }
|
||||||
|
/// )
|
||||||
|
/// ```
|
||||||
|
/// {@end-tool}
|
||||||
|
///
|
||||||
|
/// See also:
|
||||||
|
///
|
||||||
|
/// * [Chip], a chip that displays information and can be deleted.
|
||||||
|
/// * [ChoiceChip], allows a single selection from a set of options. Choice
|
||||||
|
/// chips contain related descriptive text or categories.
|
||||||
|
/// * [FilterChip], uses tags or descriptive words as a way to filter content.
|
||||||
|
/// * [ActionChip], represents an action related to primary content.
|
||||||
|
/// * [CircleAvatar], which shows images or initials of people.
|
||||||
|
/// * [Wrap], A widget that displays its children in multiple horizontal or
|
||||||
|
/// vertical runs.
|
||||||
|
/// * <https://material.io/design/components/chips.html>
|
||||||
|
class InputChip extends StatelessWidget
|
||||||
|
implements
|
||||||
|
ChipAttributes,
|
||||||
|
DeletableChipAttributes,
|
||||||
|
SelectableChipAttributes,
|
||||||
|
CheckmarkableChipAttributes,
|
||||||
|
DisabledChipAttributes,
|
||||||
|
TappableChipAttributes {
|
||||||
|
/// Creates an [InputChip].
|
||||||
|
///
|
||||||
|
/// The [onPressed] and [onSelected] callbacks must not both be specified at
|
||||||
|
/// the same time.
|
||||||
|
///
|
||||||
|
/// The [label], [isEnabled], [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 InputChip({
|
||||||
|
Key? key,
|
||||||
|
this.avatar,
|
||||||
|
required this.label,
|
||||||
|
this.labelStyle,
|
||||||
|
this.labelPadding,
|
||||||
|
this.selected = false,
|
||||||
|
this.isEnabled = true,
|
||||||
|
this.onSelected,
|
||||||
|
this.deleteIcon,
|
||||||
|
this.onDeleted,
|
||||||
|
this.deleteIconColor,
|
||||||
|
this.deleteButtonTooltipMessage,
|
||||||
|
this.onPressed,
|
||||||
|
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.selectedShadowColor,
|
||||||
|
this.showCheckmark,
|
||||||
|
this.checkmarkColor,
|
||||||
|
this.avatarBorder = const CircleBorder(),
|
||||||
|
@Deprecated(
|
||||||
|
'Migrate to deleteButtonTooltipMessage. '
|
||||||
|
'This feature was deprecated after v2.10.0-0.3.pre.'
|
||||||
|
)
|
||||||
|
this.useDeleteButtonTooltip = true,
|
||||||
|
}) : assert(selected != null),
|
||||||
|
assert(isEnabled != null),
|
||||||
|
assert(label != null),
|
||||||
|
assert(clipBehavior != null),
|
||||||
|
assert(autofocus != null),
|
||||||
|
assert(pressElevation == null || pressElevation >= 0.0),
|
||||||
|
assert(elevation == null || elevation >= 0.0),
|
||||||
|
super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
final Widget? avatar;
|
||||||
|
@override
|
||||||
|
final Widget label;
|
||||||
|
@override
|
||||||
|
final TextStyle? labelStyle;
|
||||||
|
@override
|
||||||
|
final EdgeInsetsGeometry? labelPadding;
|
||||||
|
@override
|
||||||
|
final bool selected;
|
||||||
|
@override
|
||||||
|
final bool isEnabled;
|
||||||
|
@override
|
||||||
|
final ValueChanged<bool>? onSelected;
|
||||||
|
@override
|
||||||
|
final Widget? deleteIcon;
|
||||||
|
@override
|
||||||
|
final VoidCallback? onDeleted;
|
||||||
|
@override
|
||||||
|
final Color? deleteIconColor;
|
||||||
|
@override
|
||||||
|
final String? deleteButtonTooltipMessage;
|
||||||
|
@override
|
||||||
|
final VoidCallback? onPressed;
|
||||||
|
@override
|
||||||
|
final double? pressElevation;
|
||||||
|
@override
|
||||||
|
final Color? disabledColor;
|
||||||
|
@override
|
||||||
|
final Color? selectedColor;
|
||||||
|
@override
|
||||||
|
final String? tooltip;
|
||||||
|
@override
|
||||||
|
final BorderSide? side;
|
||||||
|
@override
|
||||||
|
final OutlinedBorder? shape;
|
||||||
|
@override
|
||||||
|
final Clip clipBehavior;
|
||||||
|
@override
|
||||||
|
final FocusNode? focusNode;
|
||||||
|
@override
|
||||||
|
final bool autofocus;
|
||||||
|
@override
|
||||||
|
final Color? backgroundColor;
|
||||||
|
@override
|
||||||
|
final EdgeInsetsGeometry? padding;
|
||||||
|
@override
|
||||||
|
final VisualDensity? visualDensity;
|
||||||
|
@override
|
||||||
|
final MaterialTapTargetSize? materialTapTargetSize;
|
||||||
|
@override
|
||||||
|
final double? elevation;
|
||||||
|
@override
|
||||||
|
final Color? shadowColor;
|
||||||
|
@override
|
||||||
|
final Color? selectedShadowColor;
|
||||||
|
@override
|
||||||
|
final bool? showCheckmark;
|
||||||
|
@override
|
||||||
|
final Color? checkmarkColor;
|
||||||
|
@override
|
||||||
|
final ShapeBorder avatarBorder;
|
||||||
|
@override
|
||||||
|
@Deprecated(
|
||||||
|
'Migrate to deleteButtonTooltipMessage. '
|
||||||
|
'This feature was deprecated after v2.10.0-0.3.pre.'
|
||||||
|
)
|
||||||
|
final bool useDeleteButtonTooltip;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
assert(debugCheckHasMaterial(context));
|
||||||
|
return RawChip(
|
||||||
|
avatar: avatar,
|
||||||
|
label: label,
|
||||||
|
labelStyle: labelStyle,
|
||||||
|
labelPadding: labelPadding,
|
||||||
|
deleteIcon: deleteIcon,
|
||||||
|
onDeleted: onDeleted,
|
||||||
|
deleteIconColor: deleteIconColor,
|
||||||
|
useDeleteButtonTooltip: useDeleteButtonTooltip,
|
||||||
|
deleteButtonTooltipMessage: deleteButtonTooltipMessage,
|
||||||
|
onSelected: onSelected,
|
||||||
|
onPressed: onPressed,
|
||||||
|
pressElevation: pressElevation,
|
||||||
|
selected: selected,
|
||||||
|
disabledColor: disabledColor,
|
||||||
|
selectedColor: selectedColor,
|
||||||
|
tooltip: tooltip,
|
||||||
|
side: side,
|
||||||
|
shape: shape,
|
||||||
|
clipBehavior: clipBehavior,
|
||||||
|
focusNode: focusNode,
|
||||||
|
autofocus: autofocus,
|
||||||
|
backgroundColor: backgroundColor,
|
||||||
|
padding: padding,
|
||||||
|
visualDensity: visualDensity,
|
||||||
|
materialTapTargetSize: materialTapTargetSize,
|
||||||
|
elevation: elevation,
|
||||||
|
shadowColor: shadowColor,
|
||||||
|
selectedShadowColor: selectedShadowColor,
|
||||||
|
showCheckmark: showCheckmark,
|
||||||
|
checkmarkColor: checkmarkColor,
|
||||||
|
isEnabled: isEnabled && (onSelected != null || onDeleted != null || onPressed != null),
|
||||||
|
avatarBorder: avatarBorder,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
61
packages/flutter/test/material/chip_action_test.dart
Normal file
61
packages/flutter/test/material/chip_action_test.dart
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
// 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_test/flutter_test.dart';
|
||||||
|
|
||||||
|
/// Adds the basic requirements for a Chip.
|
||||||
|
Widget wrapForChip({
|
||||||
|
required Widget child,
|
||||||
|
TextDirection textDirection = TextDirection.ltr,
|
||||||
|
double textScaleFactor = 1.0,
|
||||||
|
Brightness brightness = Brightness.light,
|
||||||
|
}) {
|
||||||
|
return MaterialApp(
|
||||||
|
theme: ThemeData(brightness: brightness),
|
||||||
|
home: Directionality(
|
||||||
|
textDirection: textDirection,
|
||||||
|
child: MediaQuery(
|
||||||
|
data: MediaQueryData.fromWindow(WidgetsBinding.instance.window).copyWith(textScaleFactor: textScaleFactor),
|
||||||
|
child: Material(child: child),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
// last Material is from the "RawChip".
|
||||||
|
expect(materials.length, 2);
|
||||||
|
// The last Material from `RawChip` should have the clip behavior.
|
||||||
|
expect(materials.last.clipBehavior, clipBehavior);
|
||||||
|
}
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
testWidgets('ActionChip can be tapped', (WidgetTester tester) async {
|
||||||
|
await tester.pumpWidget(
|
||||||
|
MaterialApp(
|
||||||
|
home: Material(
|
||||||
|
child: ActionChip(
|
||||||
|
onPressed: () { },
|
||||||
|
label: const Text('action chip'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
await tester.tap(find.byType(ActionChip));
|
||||||
|
expect(tester.takeException(), null);
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('ActionChip clipBehavior properly passes through to the Material', (WidgetTester tester) async {
|
||||||
|
const Text label = Text('label');
|
||||||
|
await tester.pumpWidget(wrapForChip(child: ActionChip(label: label, onPressed: () { })));
|
||||||
|
checkChipMaterialClipBehavior(tester, Clip.none);
|
||||||
|
|
||||||
|
await tester.pumpWidget(wrapForChip(child: ActionChip(label: label, clipBehavior: Clip.antiAlias, onPressed: () { })));
|
||||||
|
checkChipMaterialClipBehavior(tester, Clip.antiAlias);
|
||||||
|
});
|
||||||
|
}
|
123
packages/flutter/test/material/chip_choice_test.dart
Normal file
123
packages/flutter/test/material/chip_choice_test.dart
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
// 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_test/flutter_test.dart';
|
||||||
|
|
||||||
|
import '../rendering/mock_canvas.dart';
|
||||||
|
|
||||||
|
RenderBox getMaterialBox(WidgetTester tester) {
|
||||||
|
return tester.firstRenderObject<RenderBox>(
|
||||||
|
find.descendant(
|
||||||
|
of: find.byType(RawChip),
|
||||||
|
matching: find.byType(CustomPaint),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Material getMaterial(WidgetTester tester) {
|
||||||
|
return tester.widget<Material>(
|
||||||
|
find.descendant(
|
||||||
|
of: find.byType(RawChip),
|
||||||
|
matching: find.byType(Material),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
DefaultTextStyle getLabelStyle(WidgetTester tester, String labelText) {
|
||||||
|
return tester.widget(
|
||||||
|
find.ancestor(
|
||||||
|
of: find.text(labelText),
|
||||||
|
matching: find.byType(DefaultTextStyle),
|
||||||
|
).first,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Adds the basic requirements for a Chip.
|
||||||
|
Widget wrapForChip({
|
||||||
|
required Widget child,
|
||||||
|
TextDirection textDirection = TextDirection.ltr,
|
||||||
|
double textScaleFactor = 1.0,
|
||||||
|
Brightness brightness = Brightness.light,
|
||||||
|
}) {
|
||||||
|
return MaterialApp(
|
||||||
|
theme: ThemeData(brightness: brightness),
|
||||||
|
home: Directionality(
|
||||||
|
textDirection: textDirection,
|
||||||
|
child: MediaQuery(
|
||||||
|
data: MediaQueryData.fromWindow(WidgetsBinding.instance.window).copyWith(textScaleFactor: textScaleFactor),
|
||||||
|
child: Material(child: child),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
// last Material is from the "RawChip".
|
||||||
|
expect(materials.length, 2);
|
||||||
|
// The last Material from `RawChip` should have the clip behavior.
|
||||||
|
expect(materials.last.clipBehavior, clipBehavior);
|
||||||
|
}
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
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..path(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..path(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);
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('ChoiceChip can be tapped', (WidgetTester tester) async {
|
||||||
|
await tester.pumpWidget(
|
||||||
|
const MaterialApp(
|
||||||
|
home: Material(
|
||||||
|
child: ChoiceChip(
|
||||||
|
selected: false,
|
||||||
|
label: Text('choice chip'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
await tester.tap(find.byType(ChoiceChip));
|
||||||
|
expect(tester.takeException(), null);
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('ChoiceChip clipBehavior properly passes through to the Material', (WidgetTester tester) async {
|
||||||
|
const Text label = Text('label');
|
||||||
|
await tester.pumpWidget(wrapForChip(child: const ChoiceChip(label: label, selected: false)));
|
||||||
|
checkChipMaterialClipBehavior(tester, Clip.none);
|
||||||
|
|
||||||
|
await tester.pumpWidget(wrapForChip(child: const ChoiceChip(label: label, selected: false, clipBehavior: Clip.antiAlias)));
|
||||||
|
checkChipMaterialClipBehavior(tester, Clip.antiAlias);
|
||||||
|
});
|
||||||
|
}
|
173
packages/flutter/test/material/chip_filter_test.dart
Normal file
173
packages/flutter/test/material/chip_filter_test.dart
Normal file
@ -0,0 +1,173 @@
|
|||||||
|
// 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_test/flutter_test.dart';
|
||||||
|
|
||||||
|
import '../rendering/mock_canvas.dart';
|
||||||
|
|
||||||
|
/// Adds the basic requirements for a Chip.
|
||||||
|
Widget wrapForChip({
|
||||||
|
required Widget child,
|
||||||
|
TextDirection textDirection = TextDirection.ltr,
|
||||||
|
double textScaleFactor = 1.0,
|
||||||
|
Brightness brightness = Brightness.light,
|
||||||
|
}) {
|
||||||
|
return MaterialApp(
|
||||||
|
theme: ThemeData(brightness: brightness),
|
||||||
|
home: Directionality(
|
||||||
|
textDirection: textDirection,
|
||||||
|
child: MediaQuery(
|
||||||
|
data: MediaQueryData.fromWindow(WidgetsBinding.instance.window).copyWith(textScaleFactor: textScaleFactor),
|
||||||
|
child: Material(child: child),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> pumpCheckmarkChip(
|
||||||
|
WidgetTester tester, {
|
||||||
|
required Widget chip,
|
||||||
|
Color? themeColor,
|
||||||
|
Brightness brightness = Brightness.light,
|
||||||
|
}) async {
|
||||||
|
await tester.pumpWidget(
|
||||||
|
wrapForChip(
|
||||||
|
brightness: brightness,
|
||||||
|
child: Builder(
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
final ChipThemeData chipTheme = ChipTheme.of(context);
|
||||||
|
return ChipTheme(
|
||||||
|
data: themeColor == null ? chipTheme : chipTheme.copyWith(
|
||||||
|
checkmarkColor: themeColor,
|
||||||
|
),
|
||||||
|
child: chip,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget selectedFilterChip({ Color? checkmarkColor }) {
|
||||||
|
return FilterChip(
|
||||||
|
label: const Text('InputChip'),
|
||||||
|
selected: true,
|
||||||
|
showCheckmark: true,
|
||||||
|
checkmarkColor: checkmarkColor,
|
||||||
|
onSelected: (bool _) { },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void expectCheckmarkColor(Finder finder, Color color) {
|
||||||
|
expect(
|
||||||
|
finder,
|
||||||
|
paints
|
||||||
|
// The first path that is painted is the selection overlay. We do not care
|
||||||
|
// how it is painted but it has to be added it to this pattern so that the
|
||||||
|
// check mark can be checked next.
|
||||||
|
..path()
|
||||||
|
// The second path that is painted is the check mark.
|
||||||
|
..path(color: color),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
// last Material is from the "RawChip".
|
||||||
|
expect(materials.length, 2);
|
||||||
|
// The last Material from `RawChip` should have the clip behavior.
|
||||||
|
expect(materials.last.clipBehavior, clipBehavior);
|
||||||
|
}
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
testWidgets('FilterChip can be tapped', (WidgetTester tester) async {
|
||||||
|
await tester.pumpWidget(
|
||||||
|
MaterialApp(
|
||||||
|
home: Material(
|
||||||
|
child: FilterChip(
|
||||||
|
onSelected: (bool valueChanged) { },
|
||||||
|
label: const Text('filter chip'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
await tester.tap(find.byType(FilterChip));
|
||||||
|
expect(tester.takeException(), null);
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('Filter chip check mark color is determined by platform brightness when light', (WidgetTester tester) async {
|
||||||
|
await pumpCheckmarkChip(
|
||||||
|
tester,
|
||||||
|
chip: selectedFilterChip(),
|
||||||
|
);
|
||||||
|
|
||||||
|
expectCheckmarkColor(
|
||||||
|
find.byType(FilterChip),
|
||||||
|
Colors.black.withAlpha(0xde),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('Filter chip check mark color is determined by platform brightness when dark', (WidgetTester tester) async {
|
||||||
|
await pumpCheckmarkChip(
|
||||||
|
tester,
|
||||||
|
chip: selectedFilterChip(),
|
||||||
|
brightness: Brightness.dark,
|
||||||
|
);
|
||||||
|
|
||||||
|
expectCheckmarkColor(
|
||||||
|
find.byType(FilterChip),
|
||||||
|
Colors.white.withAlpha(0xde),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('Filter chip check mark color can be set by the chip theme', (WidgetTester tester) async {
|
||||||
|
await pumpCheckmarkChip(
|
||||||
|
tester,
|
||||||
|
chip: selectedFilterChip(),
|
||||||
|
themeColor: const Color(0xff00ff00),
|
||||||
|
);
|
||||||
|
|
||||||
|
expectCheckmarkColor(
|
||||||
|
find.byType(FilterChip),
|
||||||
|
const Color(0xff00ff00),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('Filter chip check mark color can be set by the chip constructor', (WidgetTester tester) async {
|
||||||
|
await pumpCheckmarkChip(
|
||||||
|
tester,
|
||||||
|
chip: selectedFilterChip(checkmarkColor: const Color(0xff00ff00)),
|
||||||
|
);
|
||||||
|
|
||||||
|
expectCheckmarkColor(
|
||||||
|
find.byType(FilterChip),
|
||||||
|
const Color(0xff00ff00),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('Filter chip check mark color is set by chip constructor even when a theme color is specified', (WidgetTester tester) async {
|
||||||
|
await pumpCheckmarkChip(
|
||||||
|
tester,
|
||||||
|
chip: selectedFilterChip(checkmarkColor: const Color(0xffff0000)),
|
||||||
|
themeColor: const Color(0xff00ff00),
|
||||||
|
);
|
||||||
|
|
||||||
|
expectCheckmarkColor(
|
||||||
|
find.byType(FilterChip),
|
||||||
|
const Color(0xffff0000),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('FilterChip clipBehavior properly passes through to the Material', (WidgetTester tester) async {
|
||||||
|
const Text label = Text('label');
|
||||||
|
await tester.pumpWidget(wrapForChip(child: FilterChip(label: label, onSelected: (bool b) { })));
|
||||||
|
checkChipMaterialClipBehavior(tester, Clip.none);
|
||||||
|
|
||||||
|
await tester.pumpWidget(wrapForChip(child: FilterChip(label: label, onSelected: (bool b) { }, clipBehavior: Clip.antiAlias)));
|
||||||
|
checkChipMaterialClipBehavior(tester, Clip.antiAlias);
|
||||||
|
});
|
||||||
|
}
|
237
packages/flutter/test/material/chip_input_test.dart
Normal file
237
packages/flutter/test/material/chip_input_test.dart
Normal file
@ -0,0 +1,237 @@
|
|||||||
|
// 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_test/flutter_test.dart';
|
||||||
|
|
||||||
|
import '../rendering/mock_canvas.dart';
|
||||||
|
|
||||||
|
/// Adds the basic requirements for a Chip.
|
||||||
|
Widget wrapForChip({
|
||||||
|
required Widget child,
|
||||||
|
TextDirection textDirection = TextDirection.ltr,
|
||||||
|
double textScaleFactor = 1.0,
|
||||||
|
Brightness brightness = Brightness.light,
|
||||||
|
}) {
|
||||||
|
return MaterialApp(
|
||||||
|
theme: ThemeData(brightness: brightness),
|
||||||
|
home: Directionality(
|
||||||
|
textDirection: textDirection,
|
||||||
|
child: MediaQuery(
|
||||||
|
data: MediaQueryData.fromWindow(WidgetsBinding.instance.window).copyWith(textScaleFactor: textScaleFactor),
|
||||||
|
child: Material(child: child),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget selectedInputChip({ Color? checkmarkColor }) {
|
||||||
|
return InputChip(
|
||||||
|
label: const Text('InputChip'),
|
||||||
|
selected: true,
|
||||||
|
showCheckmark: true,
|
||||||
|
checkmarkColor: checkmarkColor,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Future<void> pumpCheckmarkChip(
|
||||||
|
WidgetTester tester, {
|
||||||
|
required Widget chip,
|
||||||
|
Color? themeColor,
|
||||||
|
Brightness brightness = Brightness.light,
|
||||||
|
}) async {
|
||||||
|
await tester.pumpWidget(
|
||||||
|
wrapForChip(
|
||||||
|
brightness: brightness,
|
||||||
|
child: Builder(
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
final ChipThemeData chipTheme = ChipTheme.of(context);
|
||||||
|
return ChipTheme(
|
||||||
|
data: themeColor == null ? chipTheme : chipTheme.copyWith(
|
||||||
|
checkmarkColor: themeColor,
|
||||||
|
),
|
||||||
|
child: chip,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void expectCheckmarkColor(Finder finder, Color color) {
|
||||||
|
expect(
|
||||||
|
finder,
|
||||||
|
paints
|
||||||
|
// The first path that is painted is the selection overlay. We do not care
|
||||||
|
// how it is painted but it has to be added it to this pattern so that the
|
||||||
|
// check mark can be checked next.
|
||||||
|
..path()
|
||||||
|
// The second path that is painted is the check mark.
|
||||||
|
..path(color: color),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
// last Material is from the "RawChip".
|
||||||
|
expect(materials.length, 2);
|
||||||
|
// The last Material from `RawChip` should have the clip behavior.
|
||||||
|
expect(materials.last.clipBehavior, clipBehavior);
|
||||||
|
}
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
testWidgets('InputChip can be tapped', (WidgetTester tester) async {
|
||||||
|
await tester.pumpWidget(
|
||||||
|
const MaterialApp(
|
||||||
|
home: Material(
|
||||||
|
child: InputChip(
|
||||||
|
label: Text('input chip'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
await tester.tap(find.byType(InputChip));
|
||||||
|
expect(tester.takeException(), null);
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('loses focus when disabled', (WidgetTester tester) async {
|
||||||
|
final FocusNode focusNode = FocusNode(debugLabel: 'InputChip');
|
||||||
|
await tester.pumpWidget(
|
||||||
|
wrapForChip(
|
||||||
|
child: InputChip(
|
||||||
|
focusNode: focusNode,
|
||||||
|
autofocus: true,
|
||||||
|
shape: const RoundedRectangleBorder(),
|
||||||
|
avatar: const CircleAvatar(child: Text('A')),
|
||||||
|
label: const Text('Chip A'),
|
||||||
|
onPressed: () { },
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
await tester.pump();
|
||||||
|
expect(focusNode.hasPrimaryFocus, isTrue);
|
||||||
|
|
||||||
|
await tester.pumpWidget(
|
||||||
|
wrapForChip(
|
||||||
|
child: InputChip(
|
||||||
|
focusNode: focusNode,
|
||||||
|
autofocus: true,
|
||||||
|
shape: const RoundedRectangleBorder(),
|
||||||
|
avatar: const CircleAvatar(child: Text('A')),
|
||||||
|
label: const Text('Chip A'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
await tester.pump();
|
||||||
|
expect(focusNode.hasPrimaryFocus, isFalse);
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('cannot be traversed to when disabled', (WidgetTester tester) async {
|
||||||
|
final FocusNode focusNode1 = FocusNode(debugLabel: 'InputChip 1');
|
||||||
|
final FocusNode focusNode2 = FocusNode(debugLabel: 'InputChip 2');
|
||||||
|
await tester.pumpWidget(
|
||||||
|
wrapForChip(
|
||||||
|
child: Column(
|
||||||
|
children: <Widget>[
|
||||||
|
InputChip(
|
||||||
|
focusNode: focusNode1,
|
||||||
|
autofocus: true,
|
||||||
|
label: const Text('Chip A'),
|
||||||
|
onPressed: () { },
|
||||||
|
),
|
||||||
|
InputChip(
|
||||||
|
focusNode: focusNode2,
|
||||||
|
autofocus: true,
|
||||||
|
label: const Text('Chip B'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
await tester.pump();
|
||||||
|
expect(focusNode1.hasPrimaryFocus, isTrue);
|
||||||
|
expect(focusNode2.hasPrimaryFocus, isFalse);
|
||||||
|
|
||||||
|
expect(focusNode1.nextFocus(), isTrue);
|
||||||
|
|
||||||
|
await tester.pump();
|
||||||
|
expect(focusNode1.hasPrimaryFocus, isTrue);
|
||||||
|
expect(focusNode2.hasPrimaryFocus, isFalse);
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('Input chip check mark color is determined by platform brightness when light', (WidgetTester tester) async {
|
||||||
|
await pumpCheckmarkChip(
|
||||||
|
tester,
|
||||||
|
chip: selectedInputChip(),
|
||||||
|
);
|
||||||
|
|
||||||
|
expectCheckmarkColor(
|
||||||
|
find.byType(InputChip),
|
||||||
|
Colors.black.withAlpha(0xde),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('Input chip check mark color is determined by platform brightness when dark', (WidgetTester tester) async {
|
||||||
|
await pumpCheckmarkChip(
|
||||||
|
tester,
|
||||||
|
chip: selectedInputChip(),
|
||||||
|
brightness: Brightness.dark,
|
||||||
|
);
|
||||||
|
|
||||||
|
expectCheckmarkColor(
|
||||||
|
find.byType(InputChip),
|
||||||
|
Colors.white.withAlpha(0xde),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('Input chip check mark color can be set by the chip theme', (WidgetTester tester) async {
|
||||||
|
await pumpCheckmarkChip(
|
||||||
|
tester,
|
||||||
|
chip: selectedInputChip(),
|
||||||
|
themeColor: const Color(0xff00ff00),
|
||||||
|
);
|
||||||
|
|
||||||
|
expectCheckmarkColor(
|
||||||
|
find.byType(InputChip),
|
||||||
|
const Color(0xff00ff00),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('Input chip check mark color can be set by the chip constructor', (WidgetTester tester) async {
|
||||||
|
await pumpCheckmarkChip(
|
||||||
|
tester,
|
||||||
|
chip: selectedInputChip(checkmarkColor: const Color(0xff00ff00)),
|
||||||
|
);
|
||||||
|
|
||||||
|
expectCheckmarkColor(
|
||||||
|
find.byType(InputChip),
|
||||||
|
const Color(0xff00ff00),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('Input chip check mark color is set by chip constructor even when a theme color is specified', (WidgetTester tester) async {
|
||||||
|
await pumpCheckmarkChip(
|
||||||
|
tester,
|
||||||
|
chip: selectedInputChip(checkmarkColor: const Color(0xffff0000)),
|
||||||
|
themeColor: const Color(0xff00ff00),
|
||||||
|
);
|
||||||
|
|
||||||
|
expectCheckmarkColor(
|
||||||
|
find.byType(InputChip),
|
||||||
|
const Color(0xffff0000),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('InputChip clipBehavior properly passes through to the Material', (WidgetTester tester) async {
|
||||||
|
const Text label = Text('label');
|
||||||
|
await tester.pumpWidget(wrapForChip(child: const InputChip(label: label)));
|
||||||
|
checkChipMaterialClipBehavior(tester, Clip.none);
|
||||||
|
|
||||||
|
await tester.pumpWidget(wrapForChip(child: const InputChip(label: label, clipBehavior: Clip.antiAlias)));
|
||||||
|
checkChipMaterialClipBehavior(tester, Clip.antiAlias);
|
||||||
|
});
|
||||||
|
}
|
@ -71,7 +71,7 @@ double getDeleteDrawerProgress(WidgetTester tester) => getRenderChip(tester)?.de
|
|||||||
double getEnableProgress(WidgetTester tester) => getRenderChip(tester)?.enableAnimation?.value as double;
|
double getEnableProgress(WidgetTester tester) => getRenderChip(tester)?.enableAnimation?.value as double;
|
||||||
|
|
||||||
/// Adds the basic requirements for a Chip.
|
/// Adds the basic requirements for a Chip.
|
||||||
Widget _wrapForChip({
|
Widget wrapForChip({
|
||||||
required Widget child,
|
required Widget child,
|
||||||
TextDirection textDirection = TextDirection.ltr,
|
TextDirection textDirection = TextDirection.ltr,
|
||||||
double textScaleFactor = 1.0,
|
double textScaleFactor = 1.0,
|
||||||
@ -93,7 +93,7 @@ Widget _wrapForChip({
|
|||||||
/// further constraining the size of its child, the label widget.
|
/// further constraining the size of its child, the label widget.
|
||||||
/// Optionally, adding an avatar or delete icon to the chip should not
|
/// Optionally, adding an avatar or delete icon to the chip should not
|
||||||
/// cause the chip or label to exceed its constrained height.
|
/// cause the chip or label to exceed its constrained height.
|
||||||
Future<void> _testConstrainedLabel(
|
Future<void> testConstrainedLabel(
|
||||||
WidgetTester tester, {
|
WidgetTester tester, {
|
||||||
CircleAvatar? avatar,
|
CircleAvatar? avatar,
|
||||||
VoidCallback? onDeleted,
|
VoidCallback? onDeleted,
|
||||||
@ -105,7 +105,7 @@ Future<void> _testConstrainedLabel(
|
|||||||
final Key labelKey = UniqueKey();
|
final Key labelKey = UniqueKey();
|
||||||
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
_wrapForChip(
|
wrapForChip(
|
||||||
child: Center(
|
child: Center(
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
width: chipParentWidth,
|
width: chipParentWidth,
|
||||||
@ -133,65 +133,9 @@ Future<void> _testConstrainedLabel(
|
|||||||
expect(chipSize.height, chipParentHeight);
|
expect(chipSize.height, chipParentHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _selectedInputChip({ Color? checkmarkColor }) {
|
void doNothing() {}
|
||||||
return InputChip(
|
|
||||||
label: const Text('InputChip'),
|
|
||||||
selected: true,
|
|
||||||
showCheckmark: true,
|
|
||||||
checkmarkColor: checkmarkColor,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget _selectedFilterChip({ Color? checkmarkColor }) {
|
Widget chipWithOptionalDeleteButton({
|
||||||
return FilterChip(
|
|
||||||
label: const Text('InputChip'),
|
|
||||||
selected: true,
|
|
||||||
showCheckmark: true,
|
|
||||||
checkmarkColor: checkmarkColor,
|
|
||||||
onSelected: (bool _) { },
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> _pumpCheckmarkChip(
|
|
||||||
WidgetTester tester, {
|
|
||||||
required Widget chip,
|
|
||||||
Color? themeColor,
|
|
||||||
Brightness brightness = Brightness.light,
|
|
||||||
}) async {
|
|
||||||
await tester.pumpWidget(
|
|
||||||
_wrapForChip(
|
|
||||||
brightness: brightness,
|
|
||||||
child: Builder(
|
|
||||||
builder: (BuildContext context) {
|
|
||||||
final ChipThemeData chipTheme = ChipTheme.of(context);
|
|
||||||
return ChipTheme(
|
|
||||||
data: themeColor == null ? chipTheme : chipTheme.copyWith(
|
|
||||||
checkmarkColor: themeColor,
|
|
||||||
),
|
|
||||||
child: chip,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
void _expectCheckmarkColor(Finder finder, Color color) {
|
|
||||||
expect(
|
|
||||||
finder,
|
|
||||||
paints
|
|
||||||
// The first path that is painted is the selection overlay. We do not care
|
|
||||||
// how it is painted but it has to be added it to this pattern so that the
|
|
||||||
// check mark can be checked next.
|
|
||||||
..path()
|
|
||||||
// The second path that is painted is the check mark.
|
|
||||||
..path(color: color),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
void _doNothing() {}
|
|
||||||
|
|
||||||
Widget _chipWithOptionalDeleteButton({
|
|
||||||
Key? deleteButtonKey,
|
Key? deleteButtonKey,
|
||||||
Key? labelKey,
|
Key? labelKey,
|
||||||
required bool deletable,
|
required bool deletable,
|
||||||
@ -199,16 +143,16 @@ Widget _chipWithOptionalDeleteButton({
|
|||||||
bool useDeleteButtonTooltip = true,
|
bool useDeleteButtonTooltip = true,
|
||||||
String? chipTooltip,
|
String? chipTooltip,
|
||||||
String? deleteButtonTooltipMessage,
|
String? deleteButtonTooltipMessage,
|
||||||
VoidCallback? onPressed = _doNothing,
|
VoidCallback? onPressed = doNothing,
|
||||||
}) {
|
}) {
|
||||||
return _wrapForChip(
|
return wrapForChip(
|
||||||
textDirection: textDirection,
|
textDirection: textDirection,
|
||||||
child: Wrap(
|
child: Wrap(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
RawChip(
|
RawChip(
|
||||||
tooltip: chipTooltip,
|
tooltip: chipTooltip,
|
||||||
onPressed: onPressed,
|
onPressed: onPressed,
|
||||||
onDeleted: deletable ? _doNothing : null,
|
onDeleted: deletable ? doNothing : null,
|
||||||
deleteIcon: Icon(Icons.close, key: deleteButtonKey),
|
deleteIcon: Icon(Icons.close, key: deleteButtonKey),
|
||||||
useDeleteButtonTooltip: useDeleteButtonTooltip,
|
useDeleteButtonTooltip: useDeleteButtonTooltip,
|
||||||
deleteButtonTooltipMessage: deleteButtonTooltipMessage,
|
deleteButtonTooltipMessage: deleteButtonTooltipMessage,
|
||||||
@ -347,44 +291,11 @@ void main() {
|
|||||||
expect(labelStyle.wordSpacing, textTheme.bodyText1?.wordSpacing);
|
expect(labelStyle.wordSpacing, textTheme.bodyText1?.wordSpacing);
|
||||||
});
|
});
|
||||||
|
|
||||||
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..path(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..path(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);
|
|
||||||
});
|
|
||||||
|
|
||||||
testWidgets('Chip control test', (WidgetTester tester) async {
|
testWidgets('Chip control test', (WidgetTester tester) async {
|
||||||
final FeedbackTester feedback = FeedbackTester();
|
final FeedbackTester feedback = FeedbackTester();
|
||||||
final List<String> deletedChipLabels = <String>[];
|
final List<String> deletedChipLabels = <String>[];
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
_wrapForChip(
|
wrapForChip(
|
||||||
child: Column(
|
child: Column(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Chip(
|
Chip(
|
||||||
@ -438,7 +349,7 @@ void main() {
|
|||||||
final Key labelKey = UniqueKey();
|
final Key labelKey = UniqueKey();
|
||||||
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
_wrapForChip(
|
wrapForChip(
|
||||||
child: Center(
|
child: Center(
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
width: 500.0,
|
width: 500.0,
|
||||||
@ -469,7 +380,7 @@ void main() {
|
|||||||
'Chip constrains the size of the label widget when it exceeds the '
|
'Chip constrains the size of the label widget when it exceeds the '
|
||||||
'available space',
|
'available space',
|
||||||
(WidgetTester tester) async {
|
(WidgetTester tester) async {
|
||||||
await _testConstrainedLabel(tester);
|
await testConstrainedLabel(tester);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -477,7 +388,7 @@ void main() {
|
|||||||
'Chip constrains the size of the label widget when it exceeds the '
|
'Chip constrains the size of the label widget when it exceeds the '
|
||||||
'available space and the avatar is present',
|
'available space and the avatar is present',
|
||||||
(WidgetTester tester) async {
|
(WidgetTester tester) async {
|
||||||
await _testConstrainedLabel(
|
await testConstrainedLabel(
|
||||||
tester,
|
tester,
|
||||||
avatar: const CircleAvatar(child: Text('A')),
|
avatar: const CircleAvatar(child: Text('A')),
|
||||||
);
|
);
|
||||||
@ -488,7 +399,7 @@ void main() {
|
|||||||
'Chip constrains the size of the label widget when it exceeds the '
|
'Chip constrains the size of the label widget when it exceeds the '
|
||||||
'available space and the delete icon is present',
|
'available space and the delete icon is present',
|
||||||
(WidgetTester tester) async {
|
(WidgetTester tester) async {
|
||||||
await _testConstrainedLabel(
|
await testConstrainedLabel(
|
||||||
tester,
|
tester,
|
||||||
onDeleted: () { },
|
onDeleted: () { },
|
||||||
);
|
);
|
||||||
@ -499,7 +410,7 @@ void main() {
|
|||||||
'Chip constrains the size of the label widget when it exceeds the '
|
'Chip constrains the size of the label widget when it exceeds the '
|
||||||
'available space and both avatar and delete icons are present',
|
'available space and both avatar and delete icons are present',
|
||||||
(WidgetTester tester) async {
|
(WidgetTester tester) async {
|
||||||
await _testConstrainedLabel(
|
await testConstrainedLabel(
|
||||||
tester,
|
tester,
|
||||||
avatar: const CircleAvatar(child: Text('A')),
|
avatar: const CircleAvatar(child: Text('A')),
|
||||||
onDeleted: () { },
|
onDeleted: () { },
|
||||||
@ -585,7 +496,7 @@ void main() {
|
|||||||
testWidgets('Chip in row works ok', (WidgetTester tester) async {
|
testWidgets('Chip in row works ok', (WidgetTester tester) async {
|
||||||
const TextStyle style = TextStyle(fontFamily: 'Ahem', fontSize: 10.0);
|
const TextStyle style = TextStyle(fontFamily: 'Ahem', fontSize: 10.0);
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
_wrapForChip(
|
wrapForChip(
|
||||||
child: Row(
|
child: Row(
|
||||||
children: const <Widget>[
|
children: const <Widget>[
|
||||||
Chip(label: Text('Test'), labelStyle: style),
|
Chip(label: Text('Test'), labelStyle: style),
|
||||||
@ -596,7 +507,7 @@ void main() {
|
|||||||
expect(tester.getSize(find.byType(Text)), const Size(40.0, 10.0));
|
expect(tester.getSize(find.byType(Text)), const Size(40.0, 10.0));
|
||||||
expect(tester.getSize(find.byType(Chip)), const Size(64.0, 48.0));
|
expect(tester.getSize(find.byType(Chip)), const Size(64.0, 48.0));
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
_wrapForChip(
|
wrapForChip(
|
||||||
child: Row(
|
child: Row(
|
||||||
children: const <Widget>[
|
children: const <Widget>[
|
||||||
Flexible(child: Chip(label: Text('Test'), labelStyle: style)),
|
Flexible(child: Chip(label: Text('Test'), labelStyle: style)),
|
||||||
@ -607,7 +518,7 @@ void main() {
|
|||||||
expect(tester.getSize(find.byType(Text)), const Size(40.0, 10.0));
|
expect(tester.getSize(find.byType(Text)), const Size(40.0, 10.0));
|
||||||
expect(tester.getSize(find.byType(Chip)), const Size(64.0, 48.0));
|
expect(tester.getSize(find.byType(Chip)), const Size(64.0, 48.0));
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
_wrapForChip(
|
wrapForChip(
|
||||||
child: Row(
|
child: Row(
|
||||||
children: const <Widget>[
|
children: const <Widget>[
|
||||||
Expanded(child: Chip(label: Text('Test'), labelStyle: style)),
|
Expanded(child: Chip(label: Text('Test'), labelStyle: style)),
|
||||||
@ -621,7 +532,7 @@ void main() {
|
|||||||
|
|
||||||
testWidgets('Chip responds to materialTapTargetSize', (WidgetTester tester) async {
|
testWidgets('Chip responds to materialTapTargetSize', (WidgetTester tester) async {
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
_wrapForChip(
|
wrapForChip(
|
||||||
child: Column(
|
child: Column(
|
||||||
children: const <Widget>[
|
children: const <Widget>[
|
||||||
Chip(
|
Chip(
|
||||||
@ -645,7 +556,7 @@ void main() {
|
|||||||
final UniqueKey deleteKey = UniqueKey();
|
final UniqueKey deleteKey = UniqueKey();
|
||||||
bool calledDelete = false;
|
bool calledDelete = false;
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
_wrapForChip(
|
wrapForChip(
|
||||||
child: Column(
|
child: Column(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Chip(
|
Chip(
|
||||||
@ -670,7 +581,7 @@ void main() {
|
|||||||
calledDelete = false;
|
calledDelete = false;
|
||||||
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
_wrapForChip(
|
wrapForChip(
|
||||||
child: Column(
|
child: Column(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Chip(
|
Chip(
|
||||||
@ -719,7 +630,7 @@ void main() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
_wrapForChip(
|
wrapForChip(
|
||||||
child: test,
|
child: test,
|
||||||
textDirection: TextDirection.rtl,
|
textDirection: TextDirection.rtl,
|
||||||
),
|
),
|
||||||
@ -727,7 +638,7 @@ void main() {
|
|||||||
await tester.pumpAndSettle(const Duration(milliseconds: 500));
|
await tester.pumpAndSettle(const Duration(milliseconds: 500));
|
||||||
expect(tester.getCenter(find.text('ABC')).dx, greaterThan(tester.getCenter(find.byKey(iconKey)).dx));
|
expect(tester.getCenter(find.text('ABC')).dx, greaterThan(tester.getCenter(find.byKey(iconKey)).dx));
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
_wrapForChip(
|
wrapForChip(
|
||||||
child: test,
|
child: test,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@ -737,7 +648,7 @@ void main() {
|
|||||||
|
|
||||||
testWidgets('Chip responds to textScaleFactor', (WidgetTester tester) async {
|
testWidgets('Chip responds to textScaleFactor', (WidgetTester tester) async {
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
_wrapForChip(
|
wrapForChip(
|
||||||
child: Column(
|
child: Column(
|
||||||
children: const <Widget>[
|
children: const <Widget>[
|
||||||
Chip(
|
Chip(
|
||||||
@ -767,7 +678,7 @@ void main() {
|
|||||||
expect(tester.getSize(find.byType(Chip).last), anyOf(const Size(132.0, 48.0), const Size(131.0, 48.0)));
|
expect(tester.getSize(find.byType(Chip).last), anyOf(const Size(132.0, 48.0), const Size(131.0, 48.0)));
|
||||||
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
_wrapForChip(
|
wrapForChip(
|
||||||
textScaleFactor: 3.0,
|
textScaleFactor: 3.0,
|
||||||
child: Column(
|
child: Column(
|
||||||
children: const <Widget>[
|
children: const <Widget>[
|
||||||
@ -795,7 +706,7 @@ void main() {
|
|||||||
|
|
||||||
// Check that individual text scales are taken into account.
|
// Check that individual text scales are taken into account.
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
_wrapForChip(
|
wrapForChip(
|
||||||
child: Column(
|
child: Column(
|
||||||
children: const <Widget>[
|
children: const <Widget>[
|
||||||
Chip(
|
Chip(
|
||||||
@ -824,7 +735,7 @@ void main() {
|
|||||||
final Key keyA = GlobalKey();
|
final Key keyA = GlobalKey();
|
||||||
final Key keyB = GlobalKey();
|
final Key keyB = GlobalKey();
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
_wrapForChip(
|
wrapForChip(
|
||||||
child: Column(
|
child: Column(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Chip(
|
Chip(
|
||||||
@ -857,7 +768,7 @@ void main() {
|
|||||||
testWidgets('Avatars can be non-circle avatar widgets', (WidgetTester tester) async {
|
testWidgets('Avatars can be non-circle avatar widgets', (WidgetTester tester) async {
|
||||||
final Key keyA = GlobalKey();
|
final Key keyA = GlobalKey();
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
_wrapForChip(
|
wrapForChip(
|
||||||
child: Column(
|
child: Column(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Chip(
|
Chip(
|
||||||
@ -875,7 +786,7 @@ void main() {
|
|||||||
testWidgets('Delete icons can be non-icon widgets', (WidgetTester tester) async {
|
testWidgets('Delete icons can be non-icon widgets', (WidgetTester tester) async {
|
||||||
final Key keyA = GlobalKey();
|
final Key keyA = GlobalKey();
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
_wrapForChip(
|
wrapForChip(
|
||||||
child: Column(
|
child: Column(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Chip(
|
Chip(
|
||||||
@ -895,7 +806,7 @@ void main() {
|
|||||||
final GlobalKey keyA = GlobalKey();
|
final GlobalKey keyA = GlobalKey();
|
||||||
final GlobalKey keyB = GlobalKey();
|
final GlobalKey keyB = GlobalKey();
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
_wrapForChip(
|
wrapForChip(
|
||||||
child: Overlay(
|
child: Overlay(
|
||||||
initialEntries: <OverlayEntry>[
|
initialEntries: <OverlayEntry>[
|
||||||
OverlayEntry(
|
OverlayEntry(
|
||||||
@ -931,7 +842,7 @@ void main() {
|
|||||||
final GlobalKey keyA = GlobalKey();
|
final GlobalKey keyA = GlobalKey();
|
||||||
final GlobalKey keyB = GlobalKey();
|
final GlobalKey keyB = GlobalKey();
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
_wrapForChip(
|
wrapForChip(
|
||||||
textDirection: TextDirection.rtl,
|
textDirection: TextDirection.rtl,
|
||||||
child: Overlay(
|
child: Overlay(
|
||||||
initialEntries: <OverlayEntry>[
|
initialEntries: <OverlayEntry>[
|
||||||
@ -969,7 +880,7 @@ void main() {
|
|||||||
final GlobalKey labelKey = GlobalKey();
|
final GlobalKey labelKey = GlobalKey();
|
||||||
Future<void> pushChip({ Widget? avatar }) async {
|
Future<void> pushChip({ Widget? avatar }) async {
|
||||||
return tester.pumpWidget(
|
return tester.pumpWidget(
|
||||||
_wrapForChip(
|
wrapForChip(
|
||||||
child: Wrap(
|
child: Wrap(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
RawChip(
|
RawChip(
|
||||||
@ -1083,7 +994,7 @@ void main() {
|
|||||||
bool wasDeleted = false;
|
bool wasDeleted = false;
|
||||||
Future<void> pushChip({ bool deletable = false }) async {
|
Future<void> pushChip({ bool deletable = false }) async {
|
||||||
return tester.pumpWidget(
|
return tester.pumpWidget(
|
||||||
_wrapForChip(
|
wrapForChip(
|
||||||
child: Wrap(
|
child: Wrap(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
StatefulBuilder(builder: (BuildContext context, StateSetter setState) {
|
StatefulBuilder(builder: (BuildContext context, StateSetter setState) {
|
||||||
@ -1199,7 +1110,7 @@ void main() {
|
|||||||
bool deletePressed = false;
|
bool deletePressed = false;
|
||||||
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
_wrapForChip(
|
wrapForChip(
|
||||||
child: Wrap(
|
child: Wrap(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
RawChip(
|
RawChip(
|
||||||
@ -1234,7 +1145,7 @@ void main() {
|
|||||||
final UniqueKey deleteButtonKey = UniqueKey();
|
final UniqueKey deleteButtonKey = UniqueKey();
|
||||||
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
_chipWithOptionalDeleteButton(
|
chipWithOptionalDeleteButton(
|
||||||
labelKey: labelKey,
|
labelKey: labelKey,
|
||||||
deleteButtonKey: deleteButtonKey,
|
deleteButtonKey: deleteButtonKey,
|
||||||
deletable: true,
|
deletable: true,
|
||||||
@ -1283,7 +1194,7 @@ void main() {
|
|||||||
final GlobalKey deleteButtonKey = GlobalKey();
|
final GlobalKey deleteButtonKey = GlobalKey();
|
||||||
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
_chipWithOptionalDeleteButton(
|
chipWithOptionalDeleteButton(
|
||||||
labelKey: labelKey,
|
labelKey: labelKey,
|
||||||
deleteButtonKey: deleteButtonKey,
|
deleteButtonKey: deleteButtonKey,
|
||||||
deletable: true,
|
deletable: true,
|
||||||
@ -1316,7 +1227,7 @@ void main() {
|
|||||||
final UniqueKey deleteButtonKey = UniqueKey();
|
final UniqueKey deleteButtonKey = UniqueKey();
|
||||||
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
_chipWithOptionalDeleteButton(
|
chipWithOptionalDeleteButton(
|
||||||
labelKey: labelKey,
|
labelKey: labelKey,
|
||||||
deleteButtonKey: deleteButtonKey,
|
deleteButtonKey: deleteButtonKey,
|
||||||
deletable: true,
|
deletable: true,
|
||||||
@ -1369,7 +1280,7 @@ void main() {
|
|||||||
final UniqueKey deleteButtonKey = UniqueKey();
|
final UniqueKey deleteButtonKey = UniqueKey();
|
||||||
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
_chipWithOptionalDeleteButton(
|
chipWithOptionalDeleteButton(
|
||||||
labelKey: labelKey,
|
labelKey: labelKey,
|
||||||
onPressed: null,
|
onPressed: null,
|
||||||
deleteButtonKey: deleteButtonKey,
|
deleteButtonKey: deleteButtonKey,
|
||||||
@ -1424,7 +1335,7 @@ void main() {
|
|||||||
final UniqueKey deleteButtonKey = UniqueKey();
|
final UniqueKey deleteButtonKey = UniqueKey();
|
||||||
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
_chipWithOptionalDeleteButton(
|
chipWithOptionalDeleteButton(
|
||||||
labelKey: labelKey,
|
labelKey: labelKey,
|
||||||
deleteButtonKey: deleteButtonKey,
|
deleteButtonKey: deleteButtonKey,
|
||||||
deletable: true,
|
deletable: true,
|
||||||
@ -1453,7 +1364,7 @@ void main() {
|
|||||||
final UniqueKey labelKey = UniqueKey();
|
final UniqueKey labelKey = UniqueKey();
|
||||||
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
_chipWithOptionalDeleteButton(
|
chipWithOptionalDeleteButton(
|
||||||
labelKey: labelKey,
|
labelKey: labelKey,
|
||||||
deletable: false,
|
deletable: false,
|
||||||
),
|
),
|
||||||
@ -1507,7 +1418,7 @@ void main() {
|
|||||||
final UniqueKey labelKey = UniqueKey();
|
final UniqueKey labelKey = UniqueKey();
|
||||||
Future<void> pushChip({ Widget? avatar, bool selectable = false }) async {
|
Future<void> pushChip({ Widget? avatar, bool selectable = false }) async {
|
||||||
return tester.pumpWidget(
|
return tester.pumpWidget(
|
||||||
_wrapForChip(
|
wrapForChip(
|
||||||
child: Wrap(
|
child: Wrap(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
StatefulBuilder(builder: (BuildContext context, StateSetter setState) {
|
StatefulBuilder(builder: (BuildContext context, StateSetter setState) {
|
||||||
@ -1587,7 +1498,7 @@ void main() {
|
|||||||
final UniqueKey labelKey = UniqueKey();
|
final UniqueKey labelKey = UniqueKey();
|
||||||
Future<void> pushChip({ bool selectable = false }) async {
|
Future<void> pushChip({ bool selectable = false }) async {
|
||||||
return tester.pumpWidget(
|
return tester.pumpWidget(
|
||||||
_wrapForChip(
|
wrapForChip(
|
||||||
child: Wrap(
|
child: Wrap(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
StatefulBuilder(builder: (BuildContext context, StateSetter setState) {
|
StatefulBuilder(builder: (BuildContext context, StateSetter setState) {
|
||||||
@ -1660,7 +1571,7 @@ void main() {
|
|||||||
final UniqueKey labelKey = UniqueKey();
|
final UniqueKey labelKey = UniqueKey();
|
||||||
Future<void> pushChip({ Widget? avatar, bool selectable = false }) async {
|
Future<void> pushChip({ Widget? avatar, bool selectable = false }) async {
|
||||||
return tester.pumpWidget(
|
return tester.pumpWidget(
|
||||||
_wrapForChip(
|
wrapForChip(
|
||||||
child: Wrap(
|
child: Wrap(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
StatefulBuilder(builder: (BuildContext context, StateSetter setState) {
|
StatefulBuilder(builder: (BuildContext context, StateSetter setState) {
|
||||||
@ -1719,7 +1630,7 @@ void main() {
|
|||||||
final ChipThemeData chipTheme = theme.chipTheme;
|
final ChipThemeData chipTheme = theme.chipTheme;
|
||||||
|
|
||||||
Widget buildChip(ChipThemeData data) {
|
Widget buildChip(ChipThemeData data) {
|
||||||
return _wrapForChip(
|
return wrapForChip(
|
||||||
child: Theme(
|
child: Theme(
|
||||||
data: theme,
|
data: theme,
|
||||||
child: const InputChip(
|
child: const InputChip(
|
||||||
@ -1748,7 +1659,7 @@ void main() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
Widget buildChip() {
|
Widget buildChip() {
|
||||||
return _wrapForChip(
|
return wrapForChip(
|
||||||
child: Theme(
|
child: Theme(
|
||||||
data: theme,
|
data: theme,
|
||||||
child: const Chip(
|
child: const Chip(
|
||||||
@ -1769,7 +1680,7 @@ void main() {
|
|||||||
|
|
||||||
testWidgets('ChipTheme labelStyle with inherit:true', (WidgetTester tester) async {
|
testWidgets('ChipTheme labelStyle with inherit:true', (WidgetTester tester) async {
|
||||||
Widget buildChip() {
|
Widget buildChip() {
|
||||||
return _wrapForChip(
|
return wrapForChip(
|
||||||
child: Theme(
|
child: Theme(
|
||||||
data: ThemeData.light().copyWith(
|
data: ThemeData.light().copyWith(
|
||||||
chipTheme: const ChipThemeData(
|
chipTheme: const ChipThemeData(
|
||||||
@ -1789,7 +1700,7 @@ void main() {
|
|||||||
|
|
||||||
testWidgets('Chip does not merge inherit:false label style with the theme label style', (WidgetTester tester) async {
|
testWidgets('Chip does not merge inherit:false label style with the theme label style', (WidgetTester tester) async {
|
||||||
Widget buildChip() {
|
Widget buildChip() {
|
||||||
return _wrapForChip(
|
return wrapForChip(
|
||||||
child: Theme(
|
child: Theme(
|
||||||
data: ThemeData(fontFamily: 'MyFont'),
|
data: ThemeData(fontFamily: 'MyFont'),
|
||||||
child: const DefaultTextStyle(
|
child: const DefaultTextStyle(
|
||||||
@ -1814,7 +1725,7 @@ void main() {
|
|||||||
testWidgets('Chip size is configurable by ThemeData.materialTapTargetSize', (WidgetTester tester) async {
|
testWidgets('Chip size is configurable by ThemeData.materialTapTargetSize', (WidgetTester tester) async {
|
||||||
final Key key1 = UniqueKey();
|
final Key key1 = UniqueKey();
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
_wrapForChip(
|
wrapForChip(
|
||||||
child: Theme(
|
child: Theme(
|
||||||
data: ThemeData(materialTapTargetSize: MaterialTapTargetSize.padded),
|
data: ThemeData(materialTapTargetSize: MaterialTapTargetSize.padded),
|
||||||
child: Center(
|
child: Center(
|
||||||
@ -1831,7 +1742,7 @@ void main() {
|
|||||||
|
|
||||||
final Key key2 = UniqueKey();
|
final Key key2 = UniqueKey();
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
_wrapForChip(
|
wrapForChip(
|
||||||
child: Theme(
|
child: Theme(
|
||||||
data: ThemeData(materialTapTargetSize: MaterialTapTargetSize.shrinkWrap),
|
data: ThemeData(materialTapTargetSize: MaterialTapTargetSize.shrinkWrap),
|
||||||
child: Center(
|
child: Center(
|
||||||
@ -1868,7 +1779,7 @@ void main() {
|
|||||||
bool showCheckmark = true,
|
bool showCheckmark = true,
|
||||||
}) {
|
}) {
|
||||||
chipTheme ??= defaultChipTheme;
|
chipTheme ??= defaultChipTheme;
|
||||||
return _wrapForChip(
|
return wrapForChip(
|
||||||
child: Theme(
|
child: Theme(
|
||||||
data: themeData,
|
data: themeData,
|
||||||
child: ChipTheme(
|
child: ChipTheme(
|
||||||
@ -2450,7 +2361,7 @@ void main() {
|
|||||||
testWidgets('can be tapped outside of chip delete icon', (WidgetTester tester) async {
|
testWidgets('can be tapped outside of chip delete icon', (WidgetTester tester) async {
|
||||||
bool deleted = false;
|
bool deleted = false;
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
_wrapForChip(
|
wrapForChip(
|
||||||
child: Row(
|
child: Row(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Chip(
|
Chip(
|
||||||
@ -2474,20 +2385,6 @@ void main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('Chips can be tapped', (WidgetTester tester) async {
|
testWidgets('Chips can be tapped', (WidgetTester tester) async {
|
||||||
await tester.pumpWidget(
|
|
||||||
const MaterialApp(
|
|
||||||
home: Material(
|
|
||||||
child: ChoiceChip(
|
|
||||||
selected: false,
|
|
||||||
label: Text('choice chip'),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
await tester.tap(find.byType(ChoiceChip));
|
|
||||||
expect(tester.takeException(), null);
|
|
||||||
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
const MaterialApp(
|
const MaterialApp(
|
||||||
home: Material(
|
home: Material(
|
||||||
@ -2500,47 +2397,6 @@ void main() {
|
|||||||
|
|
||||||
await tester.tap(find.byType(RawChip));
|
await tester.tap(find.byType(RawChip));
|
||||||
expect(tester.takeException(), null);
|
expect(tester.takeException(), null);
|
||||||
|
|
||||||
await tester.pumpWidget(
|
|
||||||
MaterialApp(
|
|
||||||
home: Material(
|
|
||||||
child: ActionChip(
|
|
||||||
onPressed: () { },
|
|
||||||
label: const Text('action chip'),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
await tester.tap(find.byType(ActionChip));
|
|
||||||
expect(tester.takeException(), null);
|
|
||||||
|
|
||||||
await tester.pumpWidget(
|
|
||||||
MaterialApp(
|
|
||||||
home: Material(
|
|
||||||
child: FilterChip(
|
|
||||||
onSelected: (bool valueChanged) { },
|
|
||||||
label: const Text('filter chip'),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
await tester.tap(find.byType(FilterChip));
|
|
||||||
expect(tester.takeException(), null);
|
|
||||||
|
|
||||||
await tester.pumpWidget(
|
|
||||||
const MaterialApp(
|
|
||||||
home: Material(
|
|
||||||
child: InputChip(
|
|
||||||
label: Text('input chip'),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
await tester.tap(find.byType(InputChip));
|
|
||||||
expect(tester.takeException(), null);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('Chip elevation and shadow color work correctly', (WidgetTester tester) async {
|
testWidgets('Chip elevation and shadow color work correctly', (WidgetTester tester) async {
|
||||||
@ -2554,7 +2410,7 @@ void main() {
|
|||||||
InputChip inputChip = const InputChip(label: Text('Label'));
|
InputChip inputChip = const InputChip(label: Text('Label'));
|
||||||
|
|
||||||
Widget buildChip(ChipThemeData data) {
|
Widget buildChip(ChipThemeData data) {
|
||||||
return _wrapForChip(
|
return wrapForChip(
|
||||||
child: Theme(
|
child: Theme(
|
||||||
data: theme,
|
data: theme,
|
||||||
child: inputChip,
|
child: inputChip,
|
||||||
@ -2596,7 +2452,7 @@ void main() {
|
|||||||
testWidgets('can be tapped outside of chip body', (WidgetTester tester) async {
|
testWidgets('can be tapped outside of chip body', (WidgetTester tester) async {
|
||||||
bool pressed = false;
|
bool pressed = false;
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
_wrapForChip(
|
wrapForChip(
|
||||||
child: Row(
|
child: Row(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
InputChip(
|
InputChip(
|
||||||
@ -2620,7 +2476,7 @@ void main() {
|
|||||||
|
|
||||||
testWidgets('is hitTestable', (WidgetTester tester) async {
|
testWidgets('is hitTestable', (WidgetTester tester) async {
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
_wrapForChip(
|
wrapForChip(
|
||||||
child: InputChip(
|
child: InputChip(
|
||||||
shape: const RoundedRectangleBorder(),
|
shape: const RoundedRectangleBorder(),
|
||||||
avatar: const CircleAvatar(child: Text('A')),
|
avatar: const CircleAvatar(child: Text('A')),
|
||||||
@ -2641,51 +2497,15 @@ void main() {
|
|||||||
|
|
||||||
testWidgets('Chip clipBehavior properly passes through to the Material', (WidgetTester tester) async {
|
testWidgets('Chip clipBehavior properly passes through to the Material', (WidgetTester tester) async {
|
||||||
const Text label = Text('label');
|
const Text label = Text('label');
|
||||||
await tester.pumpWidget(_wrapForChip(child: const Chip(label: label)));
|
await tester.pumpWidget(wrapForChip(child: const Chip(label: label)));
|
||||||
checkChipMaterialClipBehavior(tester, Clip.none);
|
checkChipMaterialClipBehavior(tester, Clip.none);
|
||||||
|
|
||||||
await tester.pumpWidget(_wrapForChip(child: const Chip(label: label, clipBehavior: Clip.antiAlias)));
|
await tester.pumpWidget(wrapForChip(child: const Chip(label: label, clipBehavior: Clip.antiAlias)));
|
||||||
checkChipMaterialClipBehavior(tester, Clip.antiAlias);
|
|
||||||
});
|
|
||||||
|
|
||||||
testWidgets('ChoiceChip clipBehavior properly passes through to the Material', (WidgetTester tester) async {
|
|
||||||
const Text label = Text('label');
|
|
||||||
await tester.pumpWidget(_wrapForChip(child: const ChoiceChip(label: label, selected: false)));
|
|
||||||
checkChipMaterialClipBehavior(tester, Clip.none);
|
|
||||||
|
|
||||||
await tester.pumpWidget(_wrapForChip(child: const ChoiceChip(label: label, selected: false, clipBehavior: Clip.antiAlias)));
|
|
||||||
checkChipMaterialClipBehavior(tester, Clip.antiAlias);
|
|
||||||
});
|
|
||||||
|
|
||||||
testWidgets('FilterChip clipBehavior properly passes through to the Material', (WidgetTester tester) async {
|
|
||||||
const Text label = Text('label');
|
|
||||||
await tester.pumpWidget(_wrapForChip(child: FilterChip(label: label, onSelected: (bool b) { })));
|
|
||||||
checkChipMaterialClipBehavior(tester, Clip.none);
|
|
||||||
|
|
||||||
await tester.pumpWidget(_wrapForChip(child: FilterChip(label: label, onSelected: (bool b) { }, clipBehavior: Clip.antiAlias)));
|
|
||||||
checkChipMaterialClipBehavior(tester, Clip.antiAlias);
|
|
||||||
});
|
|
||||||
|
|
||||||
testWidgets('ActionChip clipBehavior properly passes through to the Material', (WidgetTester tester) async {
|
|
||||||
const Text label = Text('label');
|
|
||||||
await tester.pumpWidget(_wrapForChip(child: ActionChip(label: label, onPressed: () { })));
|
|
||||||
checkChipMaterialClipBehavior(tester, Clip.none);
|
|
||||||
|
|
||||||
await tester.pumpWidget(_wrapForChip(child: ActionChip(label: label, clipBehavior: Clip.antiAlias, onPressed: () { })));
|
|
||||||
checkChipMaterialClipBehavior(tester, Clip.antiAlias);
|
|
||||||
});
|
|
||||||
|
|
||||||
testWidgets('InputChip clipBehavior properly passes through to the Material', (WidgetTester tester) async {
|
|
||||||
const Text label = Text('label');
|
|
||||||
await tester.pumpWidget(_wrapForChip(child: const InputChip(label: label)));
|
|
||||||
checkChipMaterialClipBehavior(tester, Clip.none);
|
|
||||||
|
|
||||||
await tester.pumpWidget(_wrapForChip(child: const InputChip(label: label, clipBehavior: Clip.antiAlias)));
|
|
||||||
checkChipMaterialClipBehavior(tester, Clip.antiAlias);
|
checkChipMaterialClipBehavior(tester, Clip.antiAlias);
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('selected chip and avatar draw darkened layer within avatar circle', (WidgetTester tester) async {
|
testWidgets('selected chip and avatar draw darkened layer within avatar circle', (WidgetTester tester) async {
|
||||||
await tester.pumpWidget(_wrapForChip(child: const FilterChip(
|
await tester.pumpWidget(wrapForChip(child: const FilterChip(
|
||||||
avatar: CircleAvatar(child: Text('t')),
|
avatar: CircleAvatar(child: Text('t')),
|
||||||
label: Text('test'),
|
label: Text('test'),
|
||||||
selected: true,
|
selected: true,
|
||||||
@ -3198,71 +3018,6 @@ void main() {
|
|||||||
expect(find.byType(RawChip), paints..drrect(color: selectedBorderSide.color));
|
expect(find.byType(RawChip), paints..drrect(color: selectedBorderSide.color));
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('loses focus when disabled', (WidgetTester tester) async {
|
|
||||||
final FocusNode focusNode = FocusNode(debugLabel: 'InputChip');
|
|
||||||
await tester.pumpWidget(
|
|
||||||
_wrapForChip(
|
|
||||||
child: InputChip(
|
|
||||||
focusNode: focusNode,
|
|
||||||
autofocus: true,
|
|
||||||
shape: const RoundedRectangleBorder(),
|
|
||||||
avatar: const CircleAvatar(child: Text('A')),
|
|
||||||
label: const Text('Chip A'),
|
|
||||||
onPressed: () { },
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
await tester.pump();
|
|
||||||
expect(focusNode.hasPrimaryFocus, isTrue);
|
|
||||||
|
|
||||||
await tester.pumpWidget(
|
|
||||||
_wrapForChip(
|
|
||||||
child: InputChip(
|
|
||||||
focusNode: focusNode,
|
|
||||||
autofocus: true,
|
|
||||||
shape: const RoundedRectangleBorder(),
|
|
||||||
avatar: const CircleAvatar(child: Text('A')),
|
|
||||||
label: const Text('Chip A'),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
await tester.pump();
|
|
||||||
expect(focusNode.hasPrimaryFocus, isFalse);
|
|
||||||
});
|
|
||||||
|
|
||||||
testWidgets('cannot be traversed to when disabled', (WidgetTester tester) async {
|
|
||||||
final FocusNode focusNode1 = FocusNode(debugLabel: 'InputChip 1');
|
|
||||||
final FocusNode focusNode2 = FocusNode(debugLabel: 'InputChip 2');
|
|
||||||
await tester.pumpWidget(
|
|
||||||
_wrapForChip(
|
|
||||||
child: Column(
|
|
||||||
children: <Widget>[
|
|
||||||
InputChip(
|
|
||||||
focusNode: focusNode1,
|
|
||||||
autofocus: true,
|
|
||||||
label: const Text('Chip A'),
|
|
||||||
onPressed: () { },
|
|
||||||
),
|
|
||||||
InputChip(
|
|
||||||
focusNode: focusNode2,
|
|
||||||
autofocus: true,
|
|
||||||
label: const Text('Chip B'),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
await tester.pump();
|
|
||||||
expect(focusNode1.hasPrimaryFocus, isTrue);
|
|
||||||
expect(focusNode2.hasPrimaryFocus, isFalse);
|
|
||||||
|
|
||||||
expect(focusNode1.nextFocus(), isTrue);
|
|
||||||
|
|
||||||
await tester.pump();
|
|
||||||
expect(focusNode1.hasPrimaryFocus, isTrue);
|
|
||||||
expect(focusNode2.hasPrimaryFocus, isFalse);
|
|
||||||
});
|
|
||||||
|
|
||||||
testWidgets('Chip responds to density changes.', (WidgetTester tester) async {
|
testWidgets('Chip responds to density changes.', (WidgetTester tester) async {
|
||||||
const Key key = Key('test');
|
const Key key = Key('test');
|
||||||
const Key textKey = Key('test text');
|
const Key textKey = Key('test text');
|
||||||
@ -3368,135 +3123,9 @@ void main() {
|
|||||||
expect(box.size, equals(const Size(128, 24.0 + 16.0)));
|
expect(box.size, equals(const Size(128, 24.0 + 16.0)));
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('Input chip check mark color is determined by platform brightness when light', (WidgetTester tester) async {
|
|
||||||
await _pumpCheckmarkChip(
|
|
||||||
tester,
|
|
||||||
chip: _selectedInputChip(),
|
|
||||||
);
|
|
||||||
|
|
||||||
_expectCheckmarkColor(
|
|
||||||
find.byType(InputChip),
|
|
||||||
Colors.black.withAlpha(0xde),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
testWidgets('Filter chip check mark color is determined by platform brightness when light', (WidgetTester tester) async {
|
|
||||||
await _pumpCheckmarkChip(
|
|
||||||
tester,
|
|
||||||
chip: _selectedFilterChip(),
|
|
||||||
);
|
|
||||||
|
|
||||||
_expectCheckmarkColor(
|
|
||||||
find.byType(FilterChip),
|
|
||||||
Colors.black.withAlpha(0xde),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
testWidgets('Input chip check mark color is determined by platform brightness when dark', (WidgetTester tester) async {
|
|
||||||
await _pumpCheckmarkChip(
|
|
||||||
tester,
|
|
||||||
chip: _selectedInputChip(),
|
|
||||||
brightness: Brightness.dark,
|
|
||||||
);
|
|
||||||
|
|
||||||
_expectCheckmarkColor(
|
|
||||||
find.byType(InputChip),
|
|
||||||
Colors.white.withAlpha(0xde),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
testWidgets('Filter chip check mark color is determined by platform brightness when dark', (WidgetTester tester) async {
|
|
||||||
await _pumpCheckmarkChip(
|
|
||||||
tester,
|
|
||||||
chip: _selectedFilterChip(),
|
|
||||||
brightness: Brightness.dark,
|
|
||||||
);
|
|
||||||
|
|
||||||
_expectCheckmarkColor(
|
|
||||||
find.byType(FilterChip),
|
|
||||||
Colors.white.withAlpha(0xde),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
testWidgets('Input chip check mark color can be set by the chip theme', (WidgetTester tester) async {
|
|
||||||
await _pumpCheckmarkChip(
|
|
||||||
tester,
|
|
||||||
chip: _selectedInputChip(),
|
|
||||||
themeColor: const Color(0xff00ff00),
|
|
||||||
);
|
|
||||||
|
|
||||||
_expectCheckmarkColor(
|
|
||||||
find.byType(InputChip),
|
|
||||||
const Color(0xff00ff00),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
testWidgets('Filter chip check mark color can be set by the chip theme', (WidgetTester tester) async {
|
|
||||||
await _pumpCheckmarkChip(
|
|
||||||
tester,
|
|
||||||
chip: _selectedFilterChip(),
|
|
||||||
themeColor: const Color(0xff00ff00),
|
|
||||||
);
|
|
||||||
|
|
||||||
_expectCheckmarkColor(
|
|
||||||
find.byType(FilterChip),
|
|
||||||
const Color(0xff00ff00),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
testWidgets('Input chip check mark color can be set by the chip constructor', (WidgetTester tester) async {
|
|
||||||
await _pumpCheckmarkChip(
|
|
||||||
tester,
|
|
||||||
chip: _selectedInputChip(checkmarkColor: const Color(0xff00ff00)),
|
|
||||||
);
|
|
||||||
|
|
||||||
_expectCheckmarkColor(
|
|
||||||
find.byType(InputChip),
|
|
||||||
const Color(0xff00ff00),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
testWidgets('Filter chip check mark color can be set by the chip constructor', (WidgetTester tester) async {
|
|
||||||
await _pumpCheckmarkChip(
|
|
||||||
tester,
|
|
||||||
chip: _selectedFilterChip(checkmarkColor: const Color(0xff00ff00)),
|
|
||||||
);
|
|
||||||
|
|
||||||
_expectCheckmarkColor(
|
|
||||||
find.byType(FilterChip),
|
|
||||||
const Color(0xff00ff00),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
testWidgets('Input chip check mark color is set by chip constructor even when a theme color is specified', (WidgetTester tester) async {
|
|
||||||
await _pumpCheckmarkChip(
|
|
||||||
tester,
|
|
||||||
chip: _selectedInputChip(checkmarkColor: const Color(0xffff0000)),
|
|
||||||
themeColor: const Color(0xff00ff00),
|
|
||||||
);
|
|
||||||
|
|
||||||
_expectCheckmarkColor(
|
|
||||||
find.byType(InputChip),
|
|
||||||
const Color(0xffff0000),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
testWidgets('Filter chip check mark color is set by chip constructor even when a theme color is specified', (WidgetTester tester) async {
|
|
||||||
await _pumpCheckmarkChip(
|
|
||||||
tester,
|
|
||||||
chip: _selectedFilterChip(checkmarkColor: const Color(0xffff0000)),
|
|
||||||
themeColor: const Color(0xff00ff00),
|
|
||||||
);
|
|
||||||
|
|
||||||
_expectCheckmarkColor(
|
|
||||||
find.byType(FilterChip),
|
|
||||||
const Color(0xffff0000),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
testWidgets('Chip delete button tooltip can be disabled using useDeleteButtonTooltip', (WidgetTester tester) async {
|
testWidgets('Chip delete button tooltip can be disabled using useDeleteButtonTooltip', (WidgetTester tester) async {
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
_chipWithOptionalDeleteButton(
|
chipWithOptionalDeleteButton(
|
||||||
deletable: true,
|
deletable: true,
|
||||||
useDeleteButtonTooltip: false,
|
useDeleteButtonTooltip: false,
|
||||||
),
|
),
|
||||||
@ -3522,7 +3151,7 @@ void main() {
|
|||||||
testWidgets('Chip delete button tooltip is disabled if deleteButtonTooltipMessage is empty', (WidgetTester tester) async {
|
testWidgets('Chip delete button tooltip is disabled if deleteButtonTooltipMessage is empty', (WidgetTester tester) async {
|
||||||
final UniqueKey deleteButtonKey = UniqueKey();
|
final UniqueKey deleteButtonKey = UniqueKey();
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
_chipWithOptionalDeleteButton(
|
chipWithOptionalDeleteButton(
|
||||||
deleteButtonKey: deleteButtonKey,
|
deleteButtonKey: deleteButtonKey,
|
||||||
deletable: true,
|
deletable: true,
|
||||||
deleteButtonTooltipMessage: '',
|
deleteButtonTooltipMessage: '',
|
||||||
@ -3547,7 +3176,7 @@ void main() {
|
|||||||
testWidgets('Disabling delete button tooltip does not disable chip tooltip', (WidgetTester tester) async {
|
testWidgets('Disabling delete button tooltip does not disable chip tooltip', (WidgetTester tester) async {
|
||||||
final UniqueKey deleteButtonKey = UniqueKey();
|
final UniqueKey deleteButtonKey = UniqueKey();
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
_chipWithOptionalDeleteButton(
|
chipWithOptionalDeleteButton(
|
||||||
deleteButtonKey: deleteButtonKey,
|
deleteButtonKey: deleteButtonKey,
|
||||||
deletable: true,
|
deletable: true,
|
||||||
deleteButtonTooltipMessage: '',
|
deleteButtonTooltipMessage: '',
|
||||||
@ -3575,7 +3204,7 @@ void main() {
|
|||||||
testWidgets('Triggering delete button tooltip does not trigger Chip tooltip', (WidgetTester tester) async {
|
testWidgets('Triggering delete button tooltip does not trigger Chip tooltip', (WidgetTester tester) async {
|
||||||
final UniqueKey deleteButtonKey = UniqueKey();
|
final UniqueKey deleteButtonKey = UniqueKey();
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
_chipWithOptionalDeleteButton(
|
chipWithOptionalDeleteButton(
|
||||||
deleteButtonKey: deleteButtonKey,
|
deleteButtonKey: deleteButtonKey,
|
||||||
deletable: true,
|
deletable: true,
|
||||||
chipTooltip: 'Chip Tooltip',
|
chipTooltip: 'Chip Tooltip',
|
||||||
@ -3601,7 +3230,7 @@ void main() {
|
|||||||
|
|
||||||
testWidgets('intrinsicHeight implementation meets constraints', (WidgetTester tester) async {
|
testWidgets('intrinsicHeight implementation meets constraints', (WidgetTester tester) async {
|
||||||
// Regression test for https://github.com/flutter/flutter/issues/49478.
|
// Regression test for https://github.com/flutter/flutter/issues/49478.
|
||||||
await tester.pumpWidget(_wrapForChip(
|
await tester.pumpWidget(wrapForChip(
|
||||||
child: const Chip(
|
child: const Chip(
|
||||||
label: Text('text'),
|
label: Text('text'),
|
||||||
padding: EdgeInsets.symmetric(horizontal: 20),
|
padding: EdgeInsets.symmetric(horizontal: 20),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user