Commit 4da5e9b2 authored by paolosoares's avatar paolosoares Committed by Ian Hickson

Adds more customization options to the Chip widget (#11498)

* Adds more customization options to the Chip widget

Includes:
- Custom Tooltip message for the delete button;
- Custom background color for the chip
- Custom delete icon color
- Custom label text style

* Adds missing type annotations to tests and improves documentation.

* Tweaks labelStyle field documentation
parent db884141
...@@ -19,7 +19,7 @@ const TextStyle _kLabelStyle = const TextStyle( ...@@ -19,7 +19,7 @@ const TextStyle _kLabelStyle = const TextStyle(
fontSize: 13.0, fontSize: 13.0,
fontWeight: FontWeight.w400, fontWeight: FontWeight.w400,
color: Colors.black87, color: Colors.black87,
textBaseline: TextBaseline.alphabetic textBaseline: TextBaseline.alphabetic,
); );
/// A material design chip. /// A material design chip.
...@@ -57,6 +57,10 @@ class Chip extends StatelessWidget { ...@@ -57,6 +57,10 @@ class Chip extends StatelessWidget {
this.avatar, this.avatar,
@required this.label, @required this.label,
this.onDeleted, this.onDeleted,
this.labelStyle,
this.deleteButtonTooltipMessage,
this.backgroundColor,
this.deleteIconColor,
}) : super(key: key); }) : super(key: key);
/// A widget to display prior to the chip's label. /// A widget to display prior to the chip's label.
...@@ -74,6 +78,30 @@ class Chip extends StatelessWidget { ...@@ -74,6 +78,30 @@ class Chip extends StatelessWidget {
/// The delete button is included in the chip only if this callback is non-null. /// The delete button is included in the chip only if this callback is non-null.
final VoidCallback onDeleted; final VoidCallback onDeleted;
/// The style to be applied to the chip's label.
///
/// This only has effect on widgets that respect the [DefaultTextStyle],
/// such as [Text].
final TextStyle labelStyle;
/// Color to be used for the chip's background, the default being grey.
///
/// This color is used as the background of the container that will hold the
/// widget's label.
final Color backgroundColor;
/// Color for delete icon, the default being black.
///
/// This has no effect when [onDelete] is null since no delete icon will be
/// shown.
final Color deleteIconColor;
/// Message to be used for the chip delete button's tooltip.
///
/// This has no effect when [onDelete] is null since no delete icon will be
/// shown.
final String deleteButtonTooltipMessage;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
assert(debugCheckHasMaterial(context)); assert(debugCheckHasMaterial(context));
...@@ -90,14 +118,14 @@ class Chip extends StatelessWidget { ...@@ -90,14 +118,14 @@ class Chip extends StatelessWidget {
margin: const EdgeInsets.only(right: 8.0), margin: const EdgeInsets.only(right: 8.0),
width: _kAvatarDiamater, width: _kAvatarDiamater,
height: _kAvatarDiamater, height: _kAvatarDiamater,
child: avatar child: avatar,
) ),
)); ));
} }
children.add(new DefaultTextStyle( children.add(new DefaultTextStyle(
style: _kLabelStyle, style: labelStyle ?? _kLabelStyle,
child: label child: label,
)); ));
if (deletable) { if (deletable) {
...@@ -105,16 +133,16 @@ class Chip extends StatelessWidget { ...@@ -105,16 +133,16 @@ class Chip extends StatelessWidget {
children.add(new GestureDetector( children.add(new GestureDetector(
onTap: Feedback.wrapForTap(onDeleted, context), onTap: Feedback.wrapForTap(onDeleted, context),
child: new Tooltip( child: new Tooltip(
message: 'Delete "$label"', message: deleteButtonTooltipMessage ?? 'Delete "$label"',
child: new Container( child: new Container(
padding: const EdgeInsets.symmetric(horizontal: 4.0), padding: const EdgeInsets.symmetric(horizontal: 4.0),
child: const Icon( child: new Icon(
Icons.cancel, Icons.cancel,
size: 18.0, size: 18.0,
color: Colors.black54 color: deleteIconColor ?? Colors.black54,
) ),
) ),
) ),
)); ));
} }
...@@ -124,14 +152,14 @@ class Chip extends StatelessWidget { ...@@ -124,14 +152,14 @@ class Chip extends StatelessWidget {
height: _kChipHeight, height: _kChipHeight,
padding: new EdgeInsets.only(left: leftPadding, right: rightPadding), padding: new EdgeInsets.only(left: leftPadding, right: rightPadding),
decoration: new BoxDecoration( decoration: new BoxDecoration(
color: Colors.grey.shade300, color: backgroundColor ?? Colors.grey.shade300,
borderRadius: new BorderRadius.circular(16.0) borderRadius: new BorderRadius.circular(16.0),
), ),
child: new Row( child: new Row(
children: children, children: children,
mainAxisSize: MainAxisSize.min mainAxisSize: MainAxisSize.min,
) ),
) ),
); );
} }
} }
...@@ -10,34 +10,56 @@ import 'feedback_tester.dart'; ...@@ -10,34 +10,56 @@ import 'feedback_tester.dart';
void main() { void main() {
testWidgets('Chip control test', (WidgetTester tester) async { testWidgets('Chip control test', (WidgetTester tester) async {
final FeedbackTester feedback = new FeedbackTester(); final FeedbackTester feedback = new FeedbackTester();
bool didDeleteChip = false; final List<String> deletedChipLabels = <String>[];
await tester.pumpWidget( await tester.pumpWidget(
new MaterialApp( new MaterialApp(
home: new Material( home: new Material(
child: new Center( child: new Column(
child: new Chip( children: <Widget>[
new Chip(
avatar: const CircleAvatar( avatar: const CircleAvatar(
child: const Text('C') child: const Text('A')
), ),
label: const Text('Chip'), label: const Text('Chip A'),
onDeleted: () { onDeleted: () {
didDeleteChip = true; deletedChipLabels.add('A');
} },
) deleteButtonTooltipMessage: 'Delete chip A',
),
new Chip(
avatar: const CircleAvatar(
child: const Text('B')
),
label: const Text('Chip B'),
onDeleted: () {
deletedChipLabels.add('B');
},
deleteButtonTooltipMessage: 'Delete chip B',
),
]
) )
) )
) )
); );
expect(tester.widget(find.byTooltip('Delete chip A')), isNotNull);
expect(tester.widget(find.byTooltip('Delete chip B')), isNotNull);
expect(feedback.clickSoundCount, 0); expect(feedback.clickSoundCount, 0);
expect(didDeleteChip, isFalse); expect(deletedChipLabels, isEmpty);
await tester.tap(find.byType(Tooltip)); await tester.tap(find.byTooltip('Delete chip A'));
expect(didDeleteChip, isTrue); expect(deletedChipLabels, equals(<String>['A']));
await tester.pumpAndSettle(const Duration(seconds: 1)); await tester.pumpAndSettle(const Duration(seconds: 1));
expect(feedback.clickSoundCount, 1); expect(feedback.clickSoundCount, 1);
await tester.tap(find.byTooltip('Delete chip B'));
expect(deletedChipLabels, equals(<String>['A', 'B']));
await tester.pumpAndSettle(const Duration(seconds: 1));
expect(feedback.clickSoundCount, 2);
feedback.dispose(); feedback.dispose();
}); });
} }
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