Unverified Commit 0d5ee056 authored by Jonah Williams's avatar Jonah Williams Committed by GitHub

use ShapeBorder to draw avatar check on chip (#25984)

Adds avatarBorder property to SelectableChipAttributes and uses the outer path to draw the darkened layer.
parent b5c5bae4
...@@ -304,6 +304,14 @@ abstract class SelectableChipAttributes { ...@@ -304,6 +304,14 @@ abstract class SelectableChipAttributes {
/// Tooltip string to be used for the body area (where the label and avatar /// Tooltip string to be used for the body area (where the label and avatar
/// are) of the chip. /// are) of the chip.
String get tooltip; String get tooltip;
/// The shape of the translucent highlight painted over the avatar when the
/// [selected] property is true.
///
/// Only the outer path of the shape is used.
///
/// Defaults to [CircleBorder].
ShapeBorder get avatarBorder;
} }
/// An interface for material design chips that can be enabled and disabled. /// An interface for material design chips that can be enabled and disabled.
...@@ -604,6 +612,7 @@ class InputChip extends StatelessWidget ...@@ -604,6 +612,7 @@ class InputChip extends StatelessWidget
this.backgroundColor, this.backgroundColor,
this.padding, this.padding,
this.materialTapTargetSize, this.materialTapTargetSize,
this.avatarBorder = const CircleBorder(),
}) : assert(selected != null), }) : assert(selected != null),
assert(isEnabled != null), assert(isEnabled != null),
assert(label != null), assert(label != null),
...@@ -652,6 +661,8 @@ class InputChip extends StatelessWidget ...@@ -652,6 +661,8 @@ class InputChip extends StatelessWidget
final EdgeInsetsGeometry padding; final EdgeInsetsGeometry padding;
@override @override
final MaterialTapTargetSize materialTapTargetSize; final MaterialTapTargetSize materialTapTargetSize;
@override
final ShapeBorder avatarBorder;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
...@@ -679,6 +690,7 @@ class InputChip extends StatelessWidget ...@@ -679,6 +690,7 @@ class InputChip extends StatelessWidget
padding: padding, padding: padding,
materialTapTargetSize: materialTapTargetSize, materialTapTargetSize: materialTapTargetSize,
isEnabled: isEnabled && (onSelected != null || onDeleted != null || onPressed != null), isEnabled: isEnabled && (onSelected != null || onDeleted != null || onPressed != null),
avatarBorder: avatarBorder,
); );
} }
} }
...@@ -762,6 +774,7 @@ class ChoiceChip extends StatelessWidget ...@@ -762,6 +774,7 @@ class ChoiceChip extends StatelessWidget
this.backgroundColor, this.backgroundColor,
this.padding, this.padding,
this.materialTapTargetSize, this.materialTapTargetSize,
this.avatarBorder = const CircleBorder(),
}) : assert(selected != null), }) : assert(selected != null),
assert(label != null), assert(label != null),
assert(clipBehavior != null), assert(clipBehavior != null),
...@@ -797,6 +810,8 @@ class ChoiceChip extends StatelessWidget ...@@ -797,6 +810,8 @@ class ChoiceChip extends StatelessWidget
final EdgeInsetsGeometry padding; final EdgeInsetsGeometry padding;
@override @override
final MaterialTapTargetSize materialTapTargetSize; final MaterialTapTargetSize materialTapTargetSize;
@override
final ShapeBorder avatarBorder;
@override @override
bool get isEnabled => onSelected != null; bool get isEnabled => onSelected != null;
...@@ -824,6 +839,7 @@ class ChoiceChip extends StatelessWidget ...@@ -824,6 +839,7 @@ class ChoiceChip extends StatelessWidget
padding: padding, padding: padding,
isEnabled: isEnabled, isEnabled: isEnabled,
materialTapTargetSize: materialTapTargetSize, materialTapTargetSize: materialTapTargetSize,
avatarBorder: avatarBorder,
); );
} }
} }
...@@ -939,6 +955,7 @@ class FilterChip extends StatelessWidget ...@@ -939,6 +955,7 @@ class FilterChip extends StatelessWidget
this.backgroundColor, this.backgroundColor,
this.padding, this.padding,
this.materialTapTargetSize, this.materialTapTargetSize,
this.avatarBorder = const CircleBorder(),
}) : assert(selected != null), }) : assert(selected != null),
assert(label != null), assert(label != null),
assert(clipBehavior != null), assert(clipBehavior != null),
...@@ -974,6 +991,8 @@ class FilterChip extends StatelessWidget ...@@ -974,6 +991,8 @@ class FilterChip extends StatelessWidget
final EdgeInsetsGeometry padding; final EdgeInsetsGeometry padding;
@override @override
final MaterialTapTargetSize materialTapTargetSize; final MaterialTapTargetSize materialTapTargetSize;
@override
final ShapeBorder avatarBorder;
@override @override
bool get isEnabled => onSelected != null; bool get isEnabled => onSelected != null;
...@@ -998,6 +1017,7 @@ class FilterChip extends StatelessWidget ...@@ -998,6 +1017,7 @@ class FilterChip extends StatelessWidget
padding: padding, padding: padding,
isEnabled: isEnabled, isEnabled: isEnabled,
materialTapTargetSize: materialTapTargetSize, materialTapTargetSize: materialTapTargetSize,
avatarBorder: avatarBorder,
); );
} }
} }
...@@ -1190,6 +1210,7 @@ class RawChip extends StatefulWidget ...@@ -1190,6 +1210,7 @@ class RawChip extends StatefulWidget
this.clipBehavior = Clip.none, this.clipBehavior = Clip.none,
this.backgroundColor, this.backgroundColor,
this.materialTapTargetSize, this.materialTapTargetSize,
this.avatarBorder = const CircleBorder(),
}) : assert(label != null), }) : assert(label != null),
assert(isEnabled != null), assert(isEnabled != null),
assert(clipBehavior != null), assert(clipBehavior != null),
...@@ -1239,6 +1260,8 @@ class RawChip extends StatefulWidget ...@@ -1239,6 +1260,8 @@ class RawChip extends StatefulWidget
final EdgeInsetsGeometry padding; final EdgeInsetsGeometry padding;
@override @override
final MaterialTapTargetSize materialTapTargetSize; final MaterialTapTargetSize materialTapTargetSize;
@override
final CircleBorder avatarBorder;
/// Whether or not to show a check mark when [selected] is true. /// Whether or not to show a check mark when [selected] is true.
/// ///
...@@ -1544,6 +1567,7 @@ class _RawChipState extends State<RawChip> with TickerProviderStateMixin<RawChip ...@@ -1544,6 +1567,7 @@ class _RawChipState extends State<RawChip> with TickerProviderStateMixin<RawChip
avatarDrawerAnimation: avatarDrawerAnimation, avatarDrawerAnimation: avatarDrawerAnimation,
deleteDrawerAnimation: deleteDrawerAnimation, deleteDrawerAnimation: deleteDrawerAnimation,
isEnabled: widget.isEnabled, isEnabled: widget.isEnabled,
avatarBorder: widget.avatarBorder,
), ),
), ),
), ),
...@@ -1624,6 +1648,7 @@ class _ChipRenderWidget extends RenderObjectWidget { ...@@ -1624,6 +1648,7 @@ class _ChipRenderWidget extends RenderObjectWidget {
this.avatarDrawerAnimation, this.avatarDrawerAnimation,
this.deleteDrawerAnimation, this.deleteDrawerAnimation,
this.enableAnimation, this.enableAnimation,
this.avatarBorder,
}) : assert(theme != null), }) : assert(theme != null),
super(key: key); super(key: key);
...@@ -1634,6 +1659,7 @@ class _ChipRenderWidget extends RenderObjectWidget { ...@@ -1634,6 +1659,7 @@ class _ChipRenderWidget extends RenderObjectWidget {
final Animation<double> avatarDrawerAnimation; final Animation<double> avatarDrawerAnimation;
final Animation<double> deleteDrawerAnimation; final Animation<double> deleteDrawerAnimation;
final Animation<double> enableAnimation; final Animation<double> enableAnimation;
final ShapeBorder avatarBorder;
@override @override
_RenderChipElement createElement() => _RenderChipElement(this); _RenderChipElement createElement() => _RenderChipElement(this);
...@@ -1648,7 +1674,8 @@ class _ChipRenderWidget extends RenderObjectWidget { ...@@ -1648,7 +1674,8 @@ class _ChipRenderWidget extends RenderObjectWidget {
..checkmarkAnimation = checkmarkAnimation ..checkmarkAnimation = checkmarkAnimation
..avatarDrawerAnimation = avatarDrawerAnimation ..avatarDrawerAnimation = avatarDrawerAnimation
..deleteDrawerAnimation = deleteDrawerAnimation ..deleteDrawerAnimation = deleteDrawerAnimation
..enableAnimation = enableAnimation; ..enableAnimation = enableAnimation
..avatarBorder = avatarBorder;
} }
@override @override
...@@ -1662,6 +1689,7 @@ class _ChipRenderWidget extends RenderObjectWidget { ...@@ -1662,6 +1689,7 @@ class _ChipRenderWidget extends RenderObjectWidget {
avatarDrawerAnimation: avatarDrawerAnimation, avatarDrawerAnimation: avatarDrawerAnimation,
deleteDrawerAnimation: deleteDrawerAnimation, deleteDrawerAnimation: deleteDrawerAnimation,
enableAnimation: enableAnimation, enableAnimation: enableAnimation,
avatarBorder: avatarBorder,
); );
} }
} }
...@@ -1849,6 +1877,7 @@ class _RenderChip extends RenderBox { ...@@ -1849,6 +1877,7 @@ class _RenderChip extends RenderBox {
this.avatarDrawerAnimation, this.avatarDrawerAnimation,
this.deleteDrawerAnimation, this.deleteDrawerAnimation,
this.enableAnimation, this.enableAnimation,
this.avatarBorder,
}) : assert(theme != null), }) : assert(theme != null),
assert(textDirection != null), assert(textDirection != null),
_theme = theme, _theme = theme,
...@@ -1870,6 +1899,7 @@ class _RenderChip extends RenderBox { ...@@ -1870,6 +1899,7 @@ class _RenderChip extends RenderBox {
Animation<double> avatarDrawerAnimation; Animation<double> avatarDrawerAnimation;
Animation<double> deleteDrawerAnimation; Animation<double> deleteDrawerAnimation;
Animation<double> enableAnimation; Animation<double> enableAnimation;
ShapeBorder avatarBorder;
RenderBox _updateChild(RenderBox oldChild, RenderBox newChild, _ChipSlot slot) { RenderBox _updateChild(RenderBox oldChild, RenderBox newChild, _ChipSlot slot) {
if (oldChild != null) { if (oldChild != null) {
...@@ -2357,7 +2387,8 @@ class _RenderChip extends RenderBox { ...@@ -2357,7 +2387,8 @@ class _RenderChip extends RenderBox {
final Paint darkenPaint = Paint() final Paint darkenPaint = Paint()
..color = selectionScrimTween.evaluate(checkmarkAnimation) ..color = selectionScrimTween.evaluate(checkmarkAnimation)
..blendMode = BlendMode.srcATop; ..blendMode = BlendMode.srcATop;
context.canvas.drawRect(avatarRect, darkenPaint); final Path path = avatarBorder.getOuterPath(avatarRect);
context.canvas.drawPath(path, darkenPaint);
} }
// Need to make the check mark be a little smaller than the avatar. // Need to make the check mark be a little smaller than the avatar.
final double checkSize = avatar.size.height * 0.75; final double checkSize = avatar.size.height * 0.75;
......
...@@ -1596,4 +1596,27 @@ void main() { ...@@ -1596,4 +1596,27 @@ void main() {
await tester.pumpWidget(_wrapForChip(child: const InputChip(label: label, clipBehavior: Clip.antiAlias))); 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 {
await tester.pumpWidget(_wrapForChip(child: const FilterChip(
avatar: CircleAvatar(child: Text('t')),
label: Text('test'),
selected: true,
onSelected: null,
)));
final RenderBox rawChip = tester.firstRenderObject<RenderBox>(
find.descendant(
of: find.byType(RawChip),
matching: find.byWidgetPredicate((Widget widget) {
return widget.runtimeType.toString() == '_ChipRenderWidget';
})
)
);
const Color selectScrimColor = Color(0x60191919);
expect(rawChip, paints..path(color: selectScrimColor, includes: <Offset>[
const Offset(10, 10),
], excludes: <Offset>[
const Offset(4, 4),
]));
});
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment