Unverified Commit f8cd24de authored by Greg Spencer's avatar Greg Spencer Committed by GitHub

Revert "ListTile Material Ripple and Shape Patch (#74373)" (#76134)

This reverts commit 422916d2 because it causes unexpected changes in the rendering of the background of a ListTile.
parent 86a51b16
...@@ -215,13 +215,13 @@ class Ink extends StatefulWidget { ...@@ -215,13 +215,13 @@ class Ink extends StatefulWidget {
/// any [padding]. /// any [padding].
final double? height; final double? height;
EdgeInsetsGeometry get _paddingIncludingDecoration { EdgeInsetsGeometry? get _paddingIncludingDecoration {
if (decoration == null || decoration!.padding == null) if (decoration == null || decoration!.padding == null)
return padding ?? EdgeInsets.zero; return padding;
final EdgeInsetsGeometry decorationPadding = decoration!.padding!; final EdgeInsetsGeometry? decorationPadding = decoration!.padding;
if (padding == null) if (padding == null)
return decorationPadding; return decorationPadding;
return padding!.add(decorationPadding); return padding!.add(decorationPadding!);
} }
@override @override
...@@ -236,7 +236,6 @@ class Ink extends StatefulWidget { ...@@ -236,7 +236,6 @@ class Ink extends StatefulWidget {
} }
class _InkState extends State<Ink> { class _InkState extends State<Ink> {
final GlobalKey _boxKey = GlobalKey();
InkDecoration? _ink; InkDecoration? _ink;
void _handleRemoved() { void _handleRemoved() {
...@@ -250,31 +249,31 @@ class _InkState extends State<Ink> { ...@@ -250,31 +249,31 @@ class _InkState extends State<Ink> {
super.deactivate(); super.deactivate();
} }
Widget _build(BuildContext context) { Widget _build(BuildContext context, BoxConstraints constraints) {
// By creating the InkDecoration from within a Builder widget, we can
// use the RenderBox of the Padding widget.
if (_ink == null) { if (_ink == null) {
_ink = InkDecoration( _ink = InkDecoration(
decoration: widget.decoration, decoration: widget.decoration,
configuration: createLocalImageConfiguration(context), configuration: createLocalImageConfiguration(context),
controller: Material.of(context)!, controller: Material.of(context)!,
referenceBox: _boxKey.currentContext!.findRenderObject()! as RenderBox, referenceBox: context.findRenderObject()! as RenderBox,
onRemoved: _handleRemoved, onRemoved: _handleRemoved,
); );
} else { } else {
_ink!.decoration = widget.decoration; _ink!.decoration = widget.decoration;
_ink!.configuration = createLocalImageConfiguration(context); _ink!.configuration = createLocalImageConfiguration(context);
} }
return widget.child ?? Container(); Widget? current = widget.child;
final EdgeInsetsGeometry? effectivePadding = widget._paddingIncludingDecoration;
if (effectivePadding != null)
current = Padding(padding: effectivePadding, child: current);
return current ?? Container();
} }
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
assert(debugCheckHasMaterial(context)); assert(debugCheckHasMaterial(context));
Widget result = Padding( Widget result = LayoutBuilder(
key: _boxKey, builder: _build,
padding: widget._paddingIncludingDecoration,
child: Builder(builder: _build),
); );
if (widget.width != null || widget.height != null) { if (widget.width != null || widget.height != null) {
result = SizedBox( result = SizedBox(
......
...@@ -11,7 +11,6 @@ import 'colors.dart'; ...@@ -11,7 +11,6 @@ import 'colors.dart';
import 'constants.dart'; import 'constants.dart';
import 'debug.dart'; import 'debug.dart';
import 'divider.dart'; import 'divider.dart';
import 'ink_decoration.dart';
import 'ink_well.dart'; import 'ink_well.dart';
import 'material_state.dart'; import 'material_state.dart';
import 'theme.dart'; import 'theme.dart';
...@@ -109,7 +108,7 @@ class ListTileTheme extends InheritedTheme { ...@@ -109,7 +108,7 @@ class ListTileTheme extends InheritedTheme {
final bool dense; final bool dense;
/// {@template flutter.material.ListTileTheme.shape} /// {@template flutter.material.ListTileTheme.shape}
/// If specified, [shape] defines the [ListTile]'s shape. /// If specified, [shape] defines the shape of the [ListTile]'s [InkWell] border.
/// {@endtemplate} /// {@endtemplate}
final ShapeBorder? shape; final ShapeBorder? shape;
...@@ -838,12 +837,13 @@ class ListTile extends StatelessWidget { ...@@ -838,12 +837,13 @@ class ListTile extends StatelessWidget {
/// widgets within a [Theme]. /// widgets within a [Theme].
final VisualDensity? visualDensity; final VisualDensity? visualDensity;
/// The tile's shape. /// The shape of the tile's [InkWell].
/// ///
/// Defines the tile's [InkWell.customBorder] and [Ink.decoration] shape. /// Defines the tile's [InkWell.customBorder].
/// ///
/// If this property is null then [ListTileTheme.shape] is used. /// If this property is null then [CardTheme.shape] of [ThemeData.cardTheme]
/// If that's null then a rectangular [Border] will be used. /// is used. If that's null then the shape will be a [RoundedRectangleBorder]
/// with a circular corner radius of 4.0.
final ShapeBorder? shape; final ShapeBorder? shape;
/// The tile's internal padding. /// The tile's internal padding.
...@@ -1185,11 +1185,8 @@ class ListTile extends StatelessWidget { ...@@ -1185,11 +1185,8 @@ class ListTile extends StatelessWidget {
child: Semantics( child: Semantics(
selected: selected, selected: selected,
enabled: enabled, enabled: enabled,
child: Ink( child: ColoredBox(
decoration: ShapeDecoration(
shape: shape ?? tileTheme.shape ?? const Border(),
color: _tileBackgroundColor(tileTheme), color: _tileBackgroundColor(tileTheme),
),
child: SafeArea( child: SafeArea(
top: false, top: false,
bottom: false, bottom: false,
......
...@@ -577,13 +577,7 @@ abstract class RenderSliverMultiBoxAdaptor extends RenderSliver ...@@ -577,13 +577,7 @@ abstract class RenderSliverMultiBoxAdaptor extends RenderSliver
@override @override
void applyPaintTransform(RenderBox child, Matrix4 transform) { void applyPaintTransform(RenderBox child, Matrix4 transform) {
final SliverMultiBoxAdaptorParentData childParentData = child.parentData! as SliverMultiBoxAdaptorParentData; if (_keepAliveBucket.containsKey(indexOf(child))) {
if (childParentData.index == null) {
// If the child has no index, such as with the prototype of a
// SliverPrototypeExtentList, then it is not visible, so we give it a
// zero transform to prevent it from painting.
transform.setZero();
} else if (_keepAliveBucket.containsKey(childParentData.index)) {
// It is possible that widgets under kept alive children want to paint // It is possible that widgets under kept alive children want to paint
// themselves. For example, the Material widget tries to paint all // themselves. For example, the Material widget tries to paint all
// InkFeatures under its subtree as long as they are not disposed. In // InkFeatures under its subtree as long as they are not disposed. In
......
...@@ -134,7 +134,7 @@ void main() { ...@@ -134,7 +134,7 @@ void main() {
) )
); );
final Rect paddingRect = tester.getRect(find.byType(SafeArea)); final Rect paddingRect = tester.getRect(find.byType(Padding));
final Rect checkboxRect = tester.getRect(find.byType(Checkbox)); final Rect checkboxRect = tester.getRect(find.byType(Checkbox));
final Rect titleRect = tester.getRect(find.text('Title')); final Rect titleRect = tester.getRect(find.text('Title'));
...@@ -246,34 +246,35 @@ void main() { ...@@ -246,34 +246,35 @@ void main() {
}); });
testWidgets('CheckboxListTile respects tileColor', (WidgetTester tester) async { testWidgets('CheckboxListTile respects tileColor', (WidgetTester tester) async {
final Color tileColor = Colors.red.shade500; const Color tileColor = Colors.black;
await tester.pumpWidget( await tester.pumpWidget(
wrap( wrap(
child: Center( child: const Center(
child: CheckboxListTile( child: CheckboxListTile(
value: false, value: false,
onChanged: null, onChanged: null,
title: const Text('Title'), title: Text('Title'),
tileColor: tileColor, tileColor: tileColor,
), ),
), ),
), ),
); );
expect(find.byType(Material), paints..path(color: tileColor)); final ColoredBox coloredBox = tester.firstWidget(find.byType(ColoredBox));
expect(coloredBox.color, equals(tileColor));
}); });
testWidgets('CheckboxListTile respects selectedTileColor', (WidgetTester tester) async { testWidgets('CheckboxListTile respects selectedTileColor', (WidgetTester tester) async {
final Color selectedTileColor = Colors.green.shade500; const Color selectedTileColor = Colors.black;
await tester.pumpWidget( await tester.pumpWidget(
wrap( wrap(
child: Center( child: const Center(
child: CheckboxListTile( child: CheckboxListTile(
value: false, value: false,
onChanged: null, onChanged: null,
title: const Text('Title'), title: Text('Title'),
selected: true, selected: true,
selectedTileColor: selectedTileColor, selectedTileColor: selectedTileColor,
), ),
...@@ -281,6 +282,7 @@ void main() { ...@@ -281,6 +282,7 @@ void main() {
), ),
); );
expect(find.byType(Material), paints..path(color: selectedTileColor)); final ColoredBox coloredBox = tester.firstWidget(find.byType(ColoredBox));
expect(coloredBox.color, equals(selectedTileColor));
}); });
} }
...@@ -1254,6 +1254,7 @@ void main() { ...@@ -1254,6 +1254,7 @@ void main() {
testWidgets('ListTile is focusable and has correct focus color', (WidgetTester tester) async { testWidgets('ListTile is focusable and has correct focus color', (WidgetTester tester) async {
final FocusNode focusNode = FocusNode(debugLabel: 'ListTile'); final FocusNode focusNode = FocusNode(debugLabel: 'ListTile');
tester.binding.focusManager.highlightStrategy = FocusHighlightStrategy.alwaysTraditional; tester.binding.focusManager.highlightStrategy = FocusHighlightStrategy.alwaysTraditional;
const Key tileKey = Key('listTile');
Widget buildApp({bool enabled = true}) { Widget buildApp({bool enabled = true}) {
return MaterialApp( return MaterialApp(
home: Material( home: Material(
...@@ -1264,6 +1265,7 @@ void main() { ...@@ -1264,6 +1265,7 @@ void main() {
height: 100, height: 100,
color: Colors.white, color: Colors.white,
child: ListTile( child: ListTile(
key: tileKey,
onTap: enabled ? () {} : null, onTap: enabled ? () {} : null,
focusColor: Colors.orange[500], focusColor: Colors.orange[500],
autofocus: true, autofocus: true,
...@@ -1280,14 +1282,16 @@ void main() { ...@@ -1280,14 +1282,16 @@ void main() {
await tester.pumpAndSettle(); await tester.pumpAndSettle();
expect(focusNode.hasPrimaryFocus, isTrue); expect(focusNode.hasPrimaryFocus, isTrue);
expect( expect(
find.byType(Material), Material.of(tester.element(find.byKey(tileKey))),
paints paints
..rect( ..rect(
color: Colors.orange[500], color: Colors.orange[500],
rect: const Rect.fromLTRB(350.0, 250.0, 450.0, 350.0)) rect: const Rect.fromLTRB(350.0, 250.0, 450.0, 350.0),
)
..rect( ..rect(
color: const Color(0xffffffff), color: const Color(0xffffffff),
rect: const Rect.fromLTRB(350.0, 250.0, 450.0, 350.0)), rect: const Rect.fromLTRB(350.0, 250.0, 450.0, 350.0),
),
); );
// Check when the list tile is disabled. // Check when the list tile is disabled.
...@@ -1295,7 +1299,7 @@ void main() { ...@@ -1295,7 +1299,7 @@ void main() {
await tester.pumpAndSettle(); await tester.pumpAndSettle();
expect(focusNode.hasPrimaryFocus, isFalse); expect(focusNode.hasPrimaryFocus, isFalse);
expect( expect(
find.byType(Material), Material.of(tester.element(find.byKey(tileKey))),
paints paints
..rect( ..rect(
color: const Color(0xffffffff), color: const Color(0xffffffff),
...@@ -1305,6 +1309,7 @@ void main() { ...@@ -1305,6 +1309,7 @@ void main() {
testWidgets('ListTile can be hovered and has correct hover color', (WidgetTester tester) async { testWidgets('ListTile can be hovered and has correct hover color', (WidgetTester tester) async {
tester.binding.focusManager.highlightStrategy = FocusHighlightStrategy.alwaysTraditional; tester.binding.focusManager.highlightStrategy = FocusHighlightStrategy.alwaysTraditional;
const Key tileKey = Key('ListTile');
Widget buildApp({bool enabled = true}) { Widget buildApp({bool enabled = true}) {
return MaterialApp( return MaterialApp(
home: Material( home: Material(
...@@ -1315,6 +1320,7 @@ void main() { ...@@ -1315,6 +1320,7 @@ void main() {
height: 100, height: 100,
color: Colors.white, color: Colors.white,
child: ListTile( child: ListTile(
key: tileKey,
onTap: enabled ? () {} : null, onTap: enabled ? () {} : null,
hoverColor: Colors.orange[500], hoverColor: Colors.orange[500],
autofocus: true, autofocus: true,
...@@ -1330,7 +1336,7 @@ void main() { ...@@ -1330,7 +1336,7 @@ void main() {
await tester.pump(); await tester.pump();
await tester.pumpAndSettle(); await tester.pumpAndSettle();
expect( expect(
find.byType(Material), Material.of(tester.element(find.byKey(tileKey))),
paints paints
..rect( ..rect(
color: const Color(0x1f000000), color: const Color(0x1f000000),
...@@ -1343,13 +1349,13 @@ void main() { ...@@ -1343,13 +1349,13 @@ void main() {
// Start hovering // Start hovering
final TestGesture gesture = await tester.createGesture(kind: PointerDeviceKind.mouse); final TestGesture gesture = await tester.createGesture(kind: PointerDeviceKind.mouse);
addTearDown(gesture.removePointer); addTearDown(gesture.removePointer);
await gesture.moveTo(tester.getCenter(find.byType(ListTile))); await gesture.moveTo(tester.getCenter(find.byKey(tileKey)));
await tester.pumpWidget(buildApp()); await tester.pumpWidget(buildApp());
await tester.pump(); await tester.pump();
await tester.pumpAndSettle(); await tester.pumpAndSettle();
expect( expect(
find.byType(Material), Material.of(tester.element(find.byKey(tileKey))),
paints paints
..rect( ..rect(
color: const Color(0x1f000000), color: const Color(0x1f000000),
...@@ -1366,7 +1372,7 @@ void main() { ...@@ -1366,7 +1372,7 @@ void main() {
await tester.pump(); await tester.pump();
await tester.pumpAndSettle(); await tester.pumpAndSettle();
expect( expect(
find.byType(Material), Material.of(tester.element(find.byKey(tileKey))),
paints paints
..rect( ..rect(
color: Colors.orange[500], color: Colors.orange[500],
...@@ -1453,75 +1459,6 @@ void main() { ...@@ -1453,75 +1459,6 @@ void main() {
expect(box.size, equals(const Size(800, 44))); expect(box.size, equals(const Size(800, 44)));
}); });
testWidgets('ListTile shape is painted correctly', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/63877
const ShapeBorder rectShape = RoundedRectangleBorder();
const ShapeBorder stadiumShape = StadiumBorder();
final Color tileColor = Colors.red.shade500;
Widget buildListTile(ShapeBorder shape) {
return MaterialApp(
home: Material(
child: Center(
child: ListTile(shape: shape, tileColor: tileColor),
),
),
);
}
// Test rectangle shape
await tester.pumpWidget(buildListTile(rectShape));
Rect rect = tester.getRect(find.byType(ListTile));
// Check if a path was painted with the correct color and shape
expect(
find.byType(Material),
paints..path(
color: tileColor,
// Corners should be included
includes: <Offset>[
Offset(rect.left, rect.top),
Offset(rect.right, rect.top),
Offset(rect.left, rect.bottom),
Offset(rect.right, rect.bottom),
],
// Points outside rect should be excluded
excludes: <Offset>[
Offset(rect.left - 1, rect.top - 1),
Offset(rect.right + 1, rect.top - 1),
Offset(rect.left - 1, rect.bottom + 1),
Offset(rect.right + 1, rect.bottom + 1),
],
),
);
// Test stadium shape
await tester.pumpWidget(buildListTile(stadiumShape));
rect = tester.getRect(find.byType(ListTile));
// Check if a path was painted with the correct color and shape
expect(
find.byType(Material),
paints..path(
color: tileColor,
// Center points of sides should be included
includes: <Offset>[
Offset(rect.left + rect.width / 2, rect.top),
Offset(rect.left, rect.top + rect.height / 2),
Offset(rect.right, rect.top + rect.height / 2),
Offset(rect.left + rect.width / 2, rect.bottom),
],
// Corners should be excluded
excludes: <Offset>[
Offset(rect.left, rect.top),
Offset(rect.right, rect.top),
Offset(rect.left, rect.bottom),
Offset(rect.right, rect.bottom),
],
),
);
});
testWidgets('ListTile changes mouse cursor when hovered', (WidgetTester tester) async { testWidgets('ListTile changes mouse cursor when hovered', (WidgetTester tester) async {
// Test ListTile() constructor // Test ListTile() constructor
await tester.pumpWidget( await tester.pumpWidget(
...@@ -1603,8 +1540,8 @@ void main() { ...@@ -1603,8 +1540,8 @@ void main() {
testWidgets('ListTile respects tileColor & selectedTileColor', (WidgetTester tester) async { testWidgets('ListTile respects tileColor & selectedTileColor', (WidgetTester tester) async {
bool isSelected = false; bool isSelected = false;
final Color tileColor = Colors.green.shade500; const Color selectedTileColor = Colors.red;
final Color selectedTileColor = Colors.red.shade500; const Color tileColor = Colors.green;
await tester.pumpWidget( await tester.pumpWidget(
MaterialApp( MaterialApp(
...@@ -1629,48 +1566,16 @@ void main() { ...@@ -1629,48 +1566,16 @@ void main() {
); );
// Initially, when isSelected is false, the ListTile should respect tileColor. // Initially, when isSelected is false, the ListTile should respect tileColor.
expect(find.byType(Material), paints..path(color: tileColor)); ColoredBox coloredBox = tester.widget(find.byType(ColoredBox));
expect(coloredBox.color, tileColor);
// Tap on tile to change isSelected. // Tap on tile to change isSelected.
await tester.tap(find.byType(ListTile)); await tester.tap(find.byType(ListTile));
await tester.pumpAndSettle(); await tester.pumpAndSettle();
// When isSelected is true, the ListTile should respect selectedTileColor. // When isSelected is true, the ListTile should respect selectedTileColor.
expect(find.byType(Material), paints..path(color: selectedTileColor)); coloredBox = tester.widget(find.byType(ColoredBox));
}); expect(coloredBox.color, selectedTileColor);
testWidgets('ListTile shows Material ripple effects on top of tileColor', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/73616
final Color tileColor = Colors.red.shade500;
await tester.pumpWidget(
MaterialApp(
home: Material(
child: Center(
child: ListTile(
tileColor: tileColor,
onTap: () {},
title: const Text('Title'),
),
),
),
),
);
// Before ListTile is tapped, it should be tileColor
expect(find.byType(Material), paints..path(color: tileColor));
// Tap on tile to trigger ink effect and wait for it to be underway.
await tester.tap(find.byType(ListTile));
await tester.pump(const Duration(milliseconds: 200));
// After tap, the tile could be drawn in tileColor, with the ripple (circle) on top
expect(
find.byType(Material),
paints
..path(color: tileColor)
..circle(),
);
}); });
testWidgets('ListTile default tile color', (WidgetTester tester) async { testWidgets('ListTile default tile color', (WidgetTester tester) async {
...@@ -1697,13 +1602,16 @@ void main() { ...@@ -1697,13 +1602,16 @@ void main() {
), ),
); );
expect(find.byType(Material), paints..path(color: defaultColor)); ColoredBox coloredBox = tester.widget(find.byType(ColoredBox));
expect(coloredBox.color, defaultColor);
// Tap on tile to change isSelected. // Tap on tile to change isSelected.
await tester.tap(find.byType(ListTile)); await tester.tap(find.byType(ListTile));
await tester.pumpAndSettle(); await tester.pumpAndSettle();
expect(find.byType(Material), paints..path(color: defaultColor)); coloredBox = tester.widget(find.byType(ColoredBox));
expect(isSelected, isTrue);
expect(coloredBox.color, defaultColor);
}); });
testWidgets('ListTile respects ListTileTheme\'s tileColor & selectedTileColor', (WidgetTester tester) async { testWidgets('ListTile respects ListTileTheme\'s tileColor & selectedTileColor', (WidgetTester tester) async {
...@@ -1714,8 +1622,8 @@ void main() { ...@@ -1714,8 +1622,8 @@ void main() {
MaterialApp( MaterialApp(
home: Material( home: Material(
child: ListTileTheme( child: ListTileTheme(
tileColor: Colors.green.shade500, selectedTileColor: Colors.green,
selectedTileColor: Colors.red.shade500, tileColor: Colors.red,
child: Center( child: Center(
child: StatefulBuilder( child: StatefulBuilder(
builder: (BuildContext context, StateSetter setState) { builder: (BuildContext context, StateSetter setState) {
...@@ -1735,19 +1643,21 @@ void main() { ...@@ -1735,19 +1643,21 @@ void main() {
), ),
); );
expect(find.byType(Material), paints..path(color: theme.tileColor)); ColoredBox coloredBox = tester.widget(find.byType(ColoredBox));
expect(coloredBox.color, theme.tileColor);
// Tap on tile to change isSelected. // Tap on tile to change isSelected.
await tester.tap(find.byType(ListTile)); await tester.tap(find.byType(ListTile));
await tester.pumpAndSettle(); await tester.pumpAndSettle();
expect(find.byType(Material), paints..path(color: theme.selectedTileColor)); coloredBox = tester.widget(find.byType(ColoredBox));
expect(coloredBox.color, theme.selectedTileColor);
}); });
testWidgets('ListTileTheme\'s tileColor & selectedTileColor are overridden by ListTile properties', (WidgetTester tester) async { testWidgets('ListTileTheme\'s tileColor & selectedTileColor are overridden by ListTile properties', (WidgetTester tester) async {
bool isSelected = false; bool isSelected = false;
final Color tileColor = Colors.green.shade500; const Color tileColor = Colors.brown;
final Color selectedTileColor = Colors.red.shade500; const Color selectedTileColor = Colors.purple;
await tester.pumpWidget( await tester.pumpWidget(
MaterialApp( MaterialApp(
...@@ -1775,13 +1685,15 @@ void main() { ...@@ -1775,13 +1685,15 @@ void main() {
), ),
); );
expect(find.byType(Material), paints..path(color: tileColor)); ColoredBox coloredBox = tester.widget(find.byType(ColoredBox));
expect(coloredBox.color, tileColor);
// Tap on tile to change isSelected. // Tap on tile to change isSelected.
await tester.tap(find.byType(ListTile)); await tester.tap(find.byType(ListTile));
await tester.pumpAndSettle(); await tester.pumpAndSettle();
expect(find.byType(Material), paints..path(color: selectedTileColor)); coloredBox = tester.widget(find.byType(ColoredBox));
expect(coloredBox.color, selectedTileColor);
}); });
testWidgets('ListTile layout at zero size', (WidgetTester tester) async { testWidgets('ListTile layout at zero size', (WidgetTester tester) async {
......
...@@ -8,7 +8,6 @@ import 'package:flutter/rendering.dart'; ...@@ -8,7 +8,6 @@ import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import '../rendering/mock_canvas.dart';
import '../widgets/semantics_tester.dart'; import '../widgets/semantics_tester.dart';
...@@ -628,7 +627,7 @@ void main() { ...@@ -628,7 +627,7 @@ void main() {
) )
); );
final Rect paddingRect = tester.getRect(find.byType(SafeArea)); final Rect paddingRect = tester.getRect(find.byType(Padding));
final Rect radioRect = tester.getRect(find.byType(radioType)); final Rect radioRect = tester.getRect(find.byType(radioType));
final Rect titleRect = tester.getRect(find.text('Title')); final Rect titleRect = tester.getRect(find.text('Title'));
...@@ -668,36 +667,37 @@ void main() { ...@@ -668,36 +667,37 @@ void main() {
}); });
testWidgets('RadioListTile respects tileColor', (WidgetTester tester) async { testWidgets('RadioListTile respects tileColor', (WidgetTester tester) async {
final Color tileColor = Colors.red.shade500; const Color tileColor = Colors.red;
await tester.pumpWidget( await tester.pumpWidget(
wrap( wrap(
child: Center( child: const Center(
child: RadioListTile<bool>( child: RadioListTile<bool>(
value: false, value: false,
groupValue: true, groupValue: true,
onChanged: null, onChanged: null,
title: const Text('Title'), title: Text('Title'),
tileColor: tileColor, tileColor: tileColor,
), ),
), ),
), ),
); );
expect(find.byType(Material), paints..path(color: tileColor)); final ColoredBox coloredBox = tester.firstWidget(find.byType(ColoredBox));
expect(coloredBox.color, tileColor);
}); });
testWidgets('RadioListTile respects selectedTileColor', (WidgetTester tester) async { testWidgets('RadioListTile respects selectedTileColor', (WidgetTester tester) async {
final Color selectedTileColor = Colors.green.shade500; const Color selectedTileColor = Colors.black;
await tester.pumpWidget( await tester.pumpWidget(
wrap( wrap(
child: Center( child: const Center(
child: RadioListTile<bool>( child: RadioListTile<bool>(
value: false, value: false,
groupValue: true, groupValue: true,
onChanged: null, onChanged: null,
title: const Text('Title'), title: Text('Title'),
selected: true, selected: true,
selectedTileColor: selectedTileColor, selectedTileColor: selectedTileColor,
), ),
...@@ -705,6 +705,7 @@ void main() { ...@@ -705,6 +705,7 @@ void main() {
), ),
); );
expect(find.byType(Material), paints..path(color: selectedTileColor)); final ColoredBox coloredBox = tester.firstWidget(find.byType(ColoredBox));
expect(coloredBox.color, equals(selectedTileColor));
}); });
} }
...@@ -359,34 +359,35 @@ void main() { ...@@ -359,34 +359,35 @@ void main() {
}); });
testWidgets('SwitchListTile respects tileColor', (WidgetTester tester) async { testWidgets('SwitchListTile respects tileColor', (WidgetTester tester) async {
final Color tileColor = Colors.red.shade500; const Color tileColor = Colors.red;
await tester.pumpWidget( await tester.pumpWidget(
wrap( wrap(
child: Center( child: const Center(
child: SwitchListTile( child: SwitchListTile(
value: false, value: false,
onChanged: null, onChanged: null,
title: const Text('Title'), title: Text('Title'),
tileColor: tileColor, tileColor: tileColor,
), ),
), ),
), ),
); );
expect(find.byType(Material), paints..path(color: tileColor)); final ColoredBox coloredBox = tester.firstWidget(find.byType(ColoredBox));
expect(coloredBox.color, tileColor);
}); });
testWidgets('SwitchListTile respects selectedTileColor', (WidgetTester tester) async { testWidgets('SwitchListTile respects selectedTileColor', (WidgetTester tester) async {
final Color selectedTileColor = Colors.green.shade500; const Color selectedTileColor = Colors.black;
await tester.pumpWidget( await tester.pumpWidget(
wrap( wrap(
child: Center( child: const Center(
child: SwitchListTile( child: SwitchListTile(
value: false, value: false,
onChanged: null, onChanged: null,
title: const Text('Title'), title: Text('Title'),
selected: true, selected: true,
selectedTileColor: selectedTileColor, selectedTileColor: selectedTileColor,
), ),
...@@ -394,7 +395,8 @@ void main() { ...@@ -394,7 +395,8 @@ void main() {
), ),
); );
expect(find.byType(Material), paints..path(color: selectedTileColor)); final ColoredBox coloredBox = tester.firstWidget(find.byType(ColoredBox));
expect(coloredBox.color, equals(selectedTileColor));
}); });
} }
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
...@@ -22,14 +21,14 @@ class TestItem extends StatelessWidget { ...@@ -22,14 +21,14 @@ class TestItem extends StatelessWidget {
} }
} }
Widget buildFrame({ int? count, double? width, double? height, Axis? scrollDirection, Key? prototypeKey }) { Widget buildFrame({ int? count, double? width, double? height, Axis? scrollDirection }) {
return Directionality( return Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
child: CustomScrollView( child: CustomScrollView(
scrollDirection: scrollDirection ?? Axis.vertical, scrollDirection: scrollDirection ?? Axis.vertical,
slivers: <Widget>[ slivers: <Widget>[
SliverPrototypeExtentList( SliverPrototypeExtentList(
prototypeItem: TestItem(item: -1, width: width, height: height, key: prototypeKey), prototypeItem: TestItem(item: -1, width: width, height: height),
delegate: SliverChildBuilderDelegate( delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) => TestItem(item: index), (BuildContext context, int index) => TestItem(item: index),
childCount: count, childCount: count,
...@@ -137,18 +136,4 @@ void main() { ...@@ -137,18 +136,4 @@ void main() {
for (int i = 1; i < 10; i += 1) for (int i = 1; i < 10; i += 1)
expect(find.text('Item $i'), findsOneWidget); expect(find.text('Item $i'), findsOneWidget);
}); });
testWidgets('SliverPrototypeExtentList prototypeItem paint transform is zero.', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/67117
// This test ensures that the SliverPrototypeExtentList does not cause an
// assertion error when calculating the paint transform of its prototypeItem.
// The paint transform of the prototypeItem should be zero, since it is not visible.
final GlobalKey prototypeKey = GlobalKey();
await tester.pumpWidget(buildFrame(count: 20, height: 100.0, prototypeKey: prototypeKey));
final RenderObject scrollView = tester.renderObject(find.byType(CustomScrollView));
final RenderObject prototype = prototypeKey.currentContext!.findRenderObject()!;
expect(prototype.getTransformTo(scrollView), Matrix4.zero());
});
} }
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