Add elevation to Chips to allow for more flexibility (#27316)

Expose elevation on chips and allow for it to be customized by the developer.
This commit is contained in:
rami-a 2019-02-01 09:33:39 -05:00 committed by GitHub
parent fac051c778
commit e57f57c72c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 72 additions and 12 deletions

View File

@ -111,6 +111,13 @@ abstract class ChipAttributes {
///
/// * [MaterialTapTargetSize], for a description of how this affects tap targets.
MaterialTapTargetSize get materialTapTargetSize;
/// Elevation to be applied on the chip relative to its parent.
///
/// This controls the size of the shadow below the chip.
///
/// Defaults to 0. The value is always non-negative.
double get elevation;
}
/// An interface for material design chips that can be deleted.
@ -460,7 +467,8 @@ abstract class TappableChipAttributes {
class Chip extends StatelessWidget implements ChipAttributes, DeletableChipAttributes {
/// Creates a material design chip.
///
/// The [label] and [clipBehavior] arguments must not be null.
/// The [label], [elevation], and [clipBehavior] arguments must not be null.
/// Additionally, the [elevation] must be non-negative.
const Chip({
Key key,
this.avatar,
@ -476,8 +484,10 @@ class Chip extends StatelessWidget implements ChipAttributes, DeletableChipAttri
this.backgroundColor,
this.padding,
this.materialTapTargetSize,
this.elevation = 0.0,
}) : assert(label != null),
assert(clipBehavior != null),
assert(elevation != null && elevation >= 0.0),
super(key: key);
@override
@ -506,6 +516,8 @@ class Chip extends StatelessWidget implements ChipAttributes, DeletableChipAttri
final String deleteButtonTooltipMessage;
@override
final MaterialTapTargetSize materialTapTargetSize;
@override
final double elevation;
@override
Widget build(BuildContext context) {
@ -525,6 +537,7 @@ class Chip extends StatelessWidget implements ChipAttributes, DeletableChipAttri
backgroundColor: backgroundColor,
padding: padding,
materialTapTargetSize: materialTapTargetSize,
elevation: elevation,
isEnabled: true,
);
}
@ -587,8 +600,10 @@ class InputChip extends StatelessWidget
/// The [onPressed] and [onSelected] callbacks must not both be specified at
/// the same time.
///
/// The [label], [isEnabled], [selected], and [clipBehavior] arguments must
/// not be null.
/// The [label], [isEnabled], [selected], [pressElevation], [elevation] and
/// [clipBehavior] arguments must not be null. Additionally, [pressElevation]
/// and [elevation] must be non-negative. Typically, [pressElevation] is
/// greater than [elevation].
const InputChip({
Key key,
this.avatar,
@ -612,11 +627,14 @@ class InputChip extends StatelessWidget
this.backgroundColor,
this.padding,
this.materialTapTargetSize,
this.elevation = 0.0,
this.avatarBorder = const CircleBorder(),
}) : assert(selected != null),
assert(isEnabled != null),
assert(label != null),
assert(clipBehavior != null),
assert(pressElevation != null && pressElevation >= 0.0),
assert(elevation != null && elevation >= 0.0),
super(key: key);
@override
@ -662,6 +680,8 @@ class InputChip extends StatelessWidget
@override
final MaterialTapTargetSize materialTapTargetSize;
@override
final double elevation;
@override
final ShapeBorder avatarBorder;
@override
@ -689,6 +709,7 @@ class InputChip extends StatelessWidget
backgroundColor: backgroundColor,
padding: padding,
materialTapTargetSize: materialTapTargetSize,
elevation: elevation,
isEnabled: isEnabled && (onSelected != null || onDeleted != null || onPressed != null),
avatarBorder: avatarBorder,
);
@ -756,7 +777,10 @@ class ChoiceChip extends StatelessWidget
DisabledChipAttributes {
/// Create a chip that acts like a radio button.
///
/// The [label], [selected], and [clipBehavior] attributes must not be null.
/// The [label], [selected], [pressElevation], [elevation] and [clipBehavior]
/// arguments must not be null. Additionally, [pressElevation] and [elevation]
/// must be non-negative. Typically, [pressElevation] is greater than
/// [elevation].
const ChoiceChip({
Key key,
this.avatar,
@ -774,10 +798,13 @@ class ChoiceChip extends StatelessWidget
this.backgroundColor,
this.padding,
this.materialTapTargetSize,
this.elevation = 0.0,
this.avatarBorder = const CircleBorder(),
}) : assert(selected != null),
assert(label != null),
assert(clipBehavior != null),
assert(pressElevation != null && pressElevation >= 0.0),
assert(elevation != null && elevation >= 0.0),
super(key: key);
@override
@ -811,6 +838,8 @@ class ChoiceChip extends StatelessWidget
@override
final MaterialTapTargetSize materialTapTargetSize;
@override
final double elevation;
@override
final ShapeBorder avatarBorder;
@override
@ -839,6 +868,7 @@ class ChoiceChip extends StatelessWidget
padding: padding,
isEnabled: isEnabled,
materialTapTargetSize: materialTapTargetSize,
elevation: elevation,
avatarBorder: avatarBorder,
);
}
@ -937,7 +967,10 @@ class FilterChip extends StatelessWidget
DisabledChipAttributes {
/// Create a chip that acts like a checkbox.
///
/// The [selected] and [label] attributes must not be null.
/// The [selected], [label], [pressElevation], [elevation] and [clipBehavior]
/// arguments must not be null. Additionally, [pressElevation] and [elevation]
/// must be non-negative. Typically, [pressElevation] is greater than
/// [elevation].
const FilterChip({
Key key,
this.avatar,
@ -955,10 +988,13 @@ class FilterChip extends StatelessWidget
this.backgroundColor,
this.padding,
this.materialTapTargetSize,
this.elevation = 0.0,
this.avatarBorder = const CircleBorder(),
}) : assert(selected != null),
assert(label != null),
assert(clipBehavior != null),
assert(pressElevation != null && pressElevation >= 0.0),
assert(elevation != null && elevation >= 0.0),
super(key: key);
@override
@ -992,6 +1028,8 @@ class FilterChip extends StatelessWidget
@override
final MaterialTapTargetSize materialTapTargetSize;
@override
final double elevation;
@override
final ShapeBorder avatarBorder;
@override
@ -1017,6 +1055,7 @@ class FilterChip extends StatelessWidget
padding: padding,
isEnabled: isEnabled,
materialTapTargetSize: materialTapTargetSize,
elevation: elevation,
avatarBorder: avatarBorder,
);
}
@ -1072,7 +1111,10 @@ class FilterChip extends StatelessWidget
class ActionChip extends StatelessWidget implements ChipAttributes, TappableChipAttributes {
/// Create a chip that acts like a button.
///
/// The [label], [onPressed], and [clipBehavior] arguments must not be null.
/// The [label], [onPressed], [pressElevation], [elevation] and [clipBehavior]
/// arguments must not be null. Additionally, [pressElevation] and [elevation]
/// must be non-negative. Typically, [pressElevation] is greater than
/// [elevation].
const ActionChip({
Key key,
this.avatar,
@ -1087,12 +1129,15 @@ class ActionChip extends StatelessWidget implements ChipAttributes, TappableChip
this.backgroundColor,
this.padding,
this.materialTapTargetSize,
this.elevation = 0.0,
}) : assert(label != 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
@ -1119,6 +1164,8 @@ class ActionChip extends StatelessWidget implements ChipAttributes, TappableChip
final EdgeInsetsGeometry padding;
@override
final MaterialTapTargetSize materialTapTargetSize;
@override
final double elevation;
@override
Widget build(BuildContext context) {
@ -1136,7 +1183,8 @@ class ActionChip extends StatelessWidget implements ChipAttributes, TappableChip
padding: padding,
labelPadding: labelPadding,
isEnabled: true,
materialTapTargetSize: materialTapTargetSize
materialTapTargetSize: materialTapTargetSize,
elevation: elevation,
);
}
}
@ -1183,8 +1231,10 @@ class RawChip extends StatefulWidget
/// The [onPressed] and [onSelected] callbacks must not both be specified at
/// the same time.
///
/// The [label], [pressElevation], [isEnabled], and [clipBehavior] arguments
/// must not be null. Additionally, [pressElevation] must be non-negative.
/// The [label], [pressElevation], [elevation], [isEnabled], and
/// [clipBehavior] arguments must not be null. Additionally, [pressElevation]
/// and [elevation] must be non-negative. Typically, [pressElevation] is
/// greater than [elevation].
const RawChip({
Key key,
this.avatar,
@ -1210,11 +1260,13 @@ class RawChip extends StatefulWidget
this.clipBehavior = Clip.none,
this.backgroundColor,
this.materialTapTargetSize,
this.elevation = 0.0,
this.avatarBorder = const CircleBorder(),
}) : assert(label != null),
assert(isEnabled != null),
assert(clipBehavior != null),
assert(pressElevation != null && pressElevation >= 0.0),
assert(elevation != null && elevation >= 0.0),
deleteIcon = deleteIcon ?? _kDefaultDeleteIcon,
super(key: key);
@ -1261,6 +1313,8 @@ class RawChip extends StatefulWidget
@override
final MaterialTapTargetSize materialTapTargetSize;
@override
final double elevation;
@override
final CircleBorder avatarBorder;
/// Whether or not to show a check mark when [selected] is true.
@ -1512,7 +1566,7 @@ class _RawChipState extends State<RawChip> with TickerProviderStateMixin<RawChip
Widget result = Material(
elevation: isTapping ? widget.pressElevation : 0.0,
elevation: isTapping ? widget.pressElevation : widget.elevation,
animationDuration: pressedAnimationDuration,
shape: shape,
clipBehavior: widget.clipBehavior,

View File

@ -1484,7 +1484,7 @@ void main() {
final ChipThemeData chipTheme = theme.chipTheme;
InputChip inputChip = const InputChip(label: Text('Label'), pressElevation: 8.0);
InputChip inputChip = const InputChip(label: Text('Label'));
Widget buildChip(ChipThemeData data) {
return _wrapForChip(
@ -1498,12 +1498,18 @@ void main() {
await tester.pumpWidget(buildChip(chipTheme));
expect(inputChip.pressElevation, 8.0);
expect(inputChip.elevation, 0.0);
inputChip = const InputChip(label: Text('Label'), pressElevation: 12.0);
inputChip = const InputChip(
label: Text('Label'),
pressElevation: 12.0,
elevation: 4.0,
);
await tester.pumpWidget(buildChip(chipTheme));
await tester.pumpAndSettle();
expect(inputChip.pressElevation, 12.0);
expect(inputChip.elevation, 4.0);
});
testWidgets('can be tapped outside of chip body', (WidgetTester tester) async {