Unverified Commit ff9d9fc2 authored by Ayush Bherwani's avatar Ayush Bherwani Committed by GitHub

[MaterialSlice] adds property to customize slice color (#63466)

parent 25986102
...@@ -41,6 +41,7 @@ class MaterialSlice extends MergeableMaterialItem { ...@@ -41,6 +41,7 @@ class MaterialSlice extends MergeableMaterialItem {
const MaterialSlice({ const MaterialSlice({
required LocalKey key, required LocalKey key,
required this.child, required this.child,
this.color,
}) : assert(key != null), }) : assert(key != null),
super(key); super(key);
...@@ -49,9 +50,14 @@ class MaterialSlice extends MergeableMaterialItem { ...@@ -49,9 +50,14 @@ class MaterialSlice extends MergeableMaterialItem {
/// {@macro flutter.widgets.ProxyWidget.child} /// {@macro flutter.widgets.ProxyWidget.child}
final Widget child; final Widget child;
/// Defines the color for the slice.
///
/// By default, the value of `color` is [ThemeData.cardColor].
final Color? color;
@override @override
String toString() { String toString() {
return 'MergeableSlice(key: $key, child: $child)'; return 'MergeableSlice(key: $key, child: $child, color: $color)';
} }
} }
...@@ -534,16 +540,9 @@ class _MergeableMaterialState extends State<MergeableMaterial> with TickerProvid ...@@ -534,16 +540,9 @@ class _MergeableMaterialState extends State<MergeableMaterial> with TickerProvid
if (_children[i] is MaterialGap) { if (_children[i] is MaterialGap) {
assert(slices.isNotEmpty); assert(slices.isNotEmpty);
widgets.add( widgets.add(
Container( ListBody(
decoration: BoxDecoration( mainAxis: widget.mainAxis,
color: Theme.of(context).cardColor, children: slices,
borderRadius: _borderRadius(i - 1, widgets.isEmpty, false),
shape: BoxShape.rectangle,
),
child: ListBody(
mainAxis: widget.mainAxis,
children: slices,
),
), ),
); );
slices = <Widget>[]; slices = <Widget>[];
...@@ -594,9 +593,16 @@ class _MergeableMaterialState extends State<MergeableMaterial> with TickerProvid ...@@ -594,9 +593,16 @@ class _MergeableMaterialState extends State<MergeableMaterial> with TickerProvid
} }
slices.add( slices.add(
Material( Container(
type: MaterialType.transparency, decoration: BoxDecoration(
child: child, color: (_children[i] as MaterialSlice).color ?? Theme.of(context).cardColor,
borderRadius: _borderRadius(i, i == 0, i == _children.length - 1),
shape: BoxShape.rectangle,
),
child: Material(
type: MaterialType.transparency,
child: child,
),
), ),
); );
} }
...@@ -604,16 +610,9 @@ class _MergeableMaterialState extends State<MergeableMaterial> with TickerProvid ...@@ -604,16 +610,9 @@ class _MergeableMaterialState extends State<MergeableMaterial> with TickerProvid
if (slices.isNotEmpty) { if (slices.isNotEmpty) {
widgets.add( widgets.add(
Container( ListBody(
decoration: BoxDecoration( mainAxis: widget.mainAxis,
color: Theme.of(context).cardColor, children: slices,
borderRadius: _borderRadius(i - 1, widgets.isEmpty, true),
shape: BoxShape.rectangle,
),
child: ListBody(
mainAxis: widget.mainAxis,
children: slices,
),
), ),
); );
slices = <Widget>[]; slices = <Widget>[];
......
...@@ -159,7 +159,8 @@ void main() { ...@@ -159,7 +159,8 @@ void main() {
RenderBox box = tester.renderObject(find.byType(MergeableMaterial)); RenderBox box = tester.renderObject(find.byType(MergeableMaterial));
expect(box.size.height, equals(200.0)); expect(box.size.height, equals(200.0));
matches(getBorderRadius(tester, 0), RadiusType.Round, RadiusType.Round); matches(getBorderRadius(tester, 0), RadiusType.Round, RadiusType.Sharp);
matches(getBorderRadius(tester, 1), RadiusType.Sharp, RadiusType.Round);
await tester.pumpWidget( await tester.pumpWidget(
const MaterialApp( const MaterialApp(
...@@ -194,7 +195,8 @@ void main() { ...@@ -194,7 +195,8 @@ void main() {
await tester.pump(const Duration(milliseconds: 100)); await tester.pump(const Duration(milliseconds: 100));
expect(box.size.height, equals(200.0)); expect(box.size.height, equals(200.0));
matches(getBorderRadius(tester, 0), RadiusType.Round, RadiusType.Round); matches(getBorderRadius(tester, 0), RadiusType.Round, RadiusType.Sharp);
matches(getBorderRadius(tester, 1), RadiusType.Sharp, RadiusType.Round);
}); });
testWidgets('MergeableMaterial paints shadows', (WidgetTester tester) async { testWidgets('MergeableMaterial paints shadows', (WidgetTester tester) async {
...@@ -338,7 +340,8 @@ void main() { ...@@ -338,7 +340,8 @@ void main() {
final RenderBox box = tester.renderObject(find.byType(MergeableMaterial)); final RenderBox box = tester.renderObject(find.byType(MergeableMaterial));
expect(box.size.height, equals(200)); expect(box.size.height, equals(200));
matches(getBorderRadius(tester, 0), RadiusType.Round, RadiusType.Round); matches(getBorderRadius(tester, 0), RadiusType.Round, RadiusType.Sharp);
matches(getBorderRadius(tester, 1), RadiusType.Sharp, RadiusType.Round);
await tester.pumpWidget( await tester.pumpWidget(
const MaterialApp( const MaterialApp(
...@@ -414,7 +417,9 @@ void main() { ...@@ -414,7 +417,9 @@ void main() {
final RenderBox box = tester.renderObject(find.byType(MergeableMaterial)); final RenderBox box = tester.renderObject(find.byType(MergeableMaterial));
expect(box.size.height, equals(200)); expect(box.size.height, equals(200));
matches(getBorderRadius(tester, 0), RadiusType.Round, RadiusType.Round); matches(getBorderRadius(tester, 0), RadiusType.Round, RadiusType.Sharp);
matches(getBorderRadius(tester, 1), RadiusType.Sharp, RadiusType.Round);
await tester.pumpWidget( await tester.pumpWidget(
const MaterialApp( const MaterialApp(
...@@ -571,7 +576,8 @@ void main() { ...@@ -571,7 +576,8 @@ void main() {
final RenderBox box = tester.renderObject(find.byType(MergeableMaterial)); final RenderBox box = tester.renderObject(find.byType(MergeableMaterial));
expect(box.size.height, equals(200)); expect(box.size.height, equals(200));
matches(getBorderRadius(tester, 0), RadiusType.Round, RadiusType.Round); matches(getBorderRadius(tester, 0), RadiusType.Round, RadiusType.Sharp);
matches(getBorderRadius(tester, 1), RadiusType.Sharp, RadiusType.Round);
await tester.pumpWidget( await tester.pumpWidget(
const MaterialApp( const MaterialApp(
...@@ -609,7 +615,9 @@ void main() { ...@@ -609,7 +615,9 @@ void main() {
expect(box.size.height, equals(300)); expect(box.size.height, equals(300));
matches(getBorderRadius(tester, 0), RadiusType.Round, RadiusType.Round); matches(getBorderRadius(tester, 0), RadiusType.Round, RadiusType.Sharp);
matches(getBorderRadius(tester, 1), RadiusType.Sharp, RadiusType.Sharp);
matches(getBorderRadius(tester, 2), RadiusType.Sharp, RadiusType.Round);
}); });
testWidgets('MergeableMaterial remove slice', (WidgetTester tester) async { testWidgets('MergeableMaterial remove slice', (WidgetTester tester) async {
...@@ -650,7 +658,9 @@ void main() { ...@@ -650,7 +658,9 @@ void main() {
final RenderBox box = tester.renderObject(find.byType(MergeableMaterial)); final RenderBox box = tester.renderObject(find.byType(MergeableMaterial));
expect(box.size.height, equals(300)); expect(box.size.height, equals(300));
matches(getBorderRadius(tester, 0), RadiusType.Round, RadiusType.Round); matches(getBorderRadius(tester, 0), RadiusType.Round, RadiusType.Sharp);
matches(getBorderRadius(tester, 1), RadiusType.Sharp, RadiusType.Sharp);
matches(getBorderRadius(tester, 2), RadiusType.Sharp, RadiusType.Round);
await tester.pumpWidget( await tester.pumpWidget(
const MaterialApp( const MaterialApp(
...@@ -682,7 +692,8 @@ void main() { ...@@ -682,7 +692,8 @@ void main() {
await tester.pump(); await tester.pump();
expect(box.size.height, equals(200)); expect(box.size.height, equals(200));
matches(getBorderRadius(tester, 0), RadiusType.Round, RadiusType.Round); matches(getBorderRadius(tester, 0), RadiusType.Round, RadiusType.Sharp);
matches(getBorderRadius(tester, 1), RadiusType.Sharp, RadiusType.Round);
}); });
testWidgets('MergeableMaterial insert chunk', (WidgetTester tester) async { testWidgets('MergeableMaterial insert chunk', (WidgetTester tester) async {
...@@ -716,7 +727,8 @@ void main() { ...@@ -716,7 +727,8 @@ void main() {
final RenderBox box = tester.renderObject(find.byType(MergeableMaterial)); final RenderBox box = tester.renderObject(find.byType(MergeableMaterial));
expect(box.size.height, equals(200)); expect(box.size.height, equals(200));
matches(getBorderRadius(tester, 0), RadiusType.Round, RadiusType.Round); matches(getBorderRadius(tester, 0), RadiusType.Round, RadiusType.Sharp);
matches(getBorderRadius(tester, 1), RadiusType.Sharp, RadiusType.Round);
await tester.pumpWidget( await tester.pumpWidget(
const MaterialApp( const MaterialApp(
...@@ -1044,11 +1056,10 @@ void main() { ...@@ -1044,11 +1056,10 @@ void main() {
matches(getBorderRadius(tester, 1), RadiusType.Round, RadiusType.Round); matches(getBorderRadius(tester, 1), RadiusType.Round, RadiusType.Round);
}); });
bool isDivider(Widget widget, bool top, bool bottom) { bool isDivider(BoxDecoration decoration, bool top, bool bottom) {
final DecoratedBox box = widget as DecoratedBox;
const BorderSide side = BorderSide(color: Color(0x1F000000), width: 0.5); const BorderSide side = BorderSide(color: Color(0x1F000000), width: 0.5);
return box.decoration == BoxDecoration( return decoration == BoxDecoration(
border: Border( border: Border(
top: top ? side : BorderSide.none, top: top ? side : BorderSide.none,
bottom: bottom ? side : BorderSide.none, bottom: bottom ? side : BorderSide.none,
...@@ -1099,8 +1110,15 @@ void main() { ...@@ -1099,8 +1110,15 @@ void main() {
), ),
); );
List<Widget> boxes = tester.widgetList(find.byType(DecoratedBox)).toList(); List<Widget> animatedContainers = tester.widgetList(
int offset = 1; find.byType(AnimatedContainer),
).toList();
List<BoxDecoration> boxes = <BoxDecoration>[];
for (final Widget container in animatedContainers) {
boxes.add((container as AnimatedContainer).decoration! as BoxDecoration);
}
int offset = 0;
expect(isDivider(boxes[offset], false, true), isTrue); expect(isDivider(boxes[offset], false, true), isTrue);
expect(isDivider(boxes[offset + 1], true, true), isTrue); expect(isDivider(boxes[offset + 1], true, true), isTrue);
...@@ -1155,14 +1173,21 @@ void main() { ...@@ -1155,14 +1173,21 @@ void main() {
// Wait for dividers to shrink. // Wait for dividers to shrink.
await tester.pump(const Duration(milliseconds: 200)); await tester.pump(const Duration(milliseconds: 200));
boxes = tester.widgetList(find.byType(DecoratedBox)).toList(); animatedContainers = tester.widgetList(
offset = 1; find.byType(AnimatedContainer),
).toList();
boxes = <BoxDecoration>[];
for (final Widget container in animatedContainers) {
boxes.add((container as AnimatedContainer).decoration! as BoxDecoration);
}
offset = 0;
expect(isDivider(boxes[offset], false, true), isTrue); expect(isDivider(boxes[offset], false, true), isTrue);
expect(isDivider(boxes[offset + 1], true, false), isTrue); expect(isDivider(boxes[offset + 1], true, false), isTrue);
// offset + 2 is gap expect(isDivider(boxes[offset + 2], false, true), isTrue);
expect(isDivider(boxes[offset + 3], false, true), isTrue); expect(isDivider(boxes[offset + 3], true, false), isTrue);
expect(isDivider(boxes[offset + 4], true, false), isTrue);
}); });
testWidgets('MergeableMaterial respects dividerColor', (WidgetTester tester) async { testWidgets('MergeableMaterial respects dividerColor', (WidgetTester tester) async {
...@@ -1201,4 +1226,49 @@ void main() { ...@@ -1201,4 +1226,49 @@ void main() {
// Since we are getting the last DecoratedBox, it will have a Border.top. // Since we are getting the last DecoratedBox, it will have a Border.top.
expect(decoration.border!.top.color, dividerColor); expect(decoration.border!.top.color, dividerColor);
}); });
testWidgets('MergeableMaterial respects MaterialSlice.color', (WidgetTester tester) async {
const Color themeCardColor = Colors.red;
const Color materialSliceColor = Colors.green;
await tester.pumpWidget(
MaterialApp(
theme: ThemeData(
cardColor: themeCardColor,
),
home: const Scaffold(
body: SingleChildScrollView(
child: MergeableMaterial(
children: <MergeableMaterialItem>[
MaterialSlice(
key: ValueKey<String>('A'),
color: materialSliceColor,
child: SizedBox(
height: 100,
width: 100,
),
),
MaterialGap(
key: ValueKey<String>('B'),
),
MaterialSlice(
key: ValueKey<String>('C'),
child: SizedBox(
height: 100,
width: 100,
),
),
],
),
),
),
),
);
BoxDecoration boxDecoration = tester.widget<Container>(find.byType(Container).first).decoration! as BoxDecoration;
expect(boxDecoration.color, materialSliceColor);
boxDecoration = tester.widget<Container>(find.byType(Container).last).decoration! as BoxDecoration;
expect(boxDecoration.color, themeCardColor);
});
} }
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