Added properties in DropdownButtonFormField to match DropdownButton (#36998)
* Added properties in DropdownFormField to match DropdownButton
* Minor style guide related changes
diff --git a/AUTHORS b/AUTHORS
index ccb6446..2a36d97 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -39,4 +39,5 @@
Frederik Schweiger <mail@flschweiger.net>
Martin Staadecker <machstg@gmail.com>
Igor Katsuba <katsuba.igor@gmail.com>
-Diego Velásquez <diego.velasquez.lopez@gmail.com>
\ No newline at end of file
+Diego Velásquez <diego.velasquez.lopez@gmail.com>
+Sarbagya Dhaubanjar <mail@sarbagyastha.com.np>
\ No newline at end of file
diff --git a/packages/flutter/lib/src/material/dropdown.dart b/packages/flutter/lib/src/material/dropdown.dart
index 840d051..b8e54bd 100644
--- a/packages/flutter/lib/src/material/dropdown.dart
+++ b/packages/flutter/lib/src/material/dropdown.dart
@@ -184,24 +184,24 @@
explicitChildNodes: true,
label: localizations.popupMenuLabel,
child: Material(
- type: MaterialType.transparency,
- textStyle: route.style,
- child: ScrollConfiguration(
- behavior: const _DropdownScrollBehavior(),
- child: Scrollbar(
- child: ListView(
- controller: widget.route.scrollController,
- padding: kMaterialListPadding,
- itemExtent: _kMenuItemHeight,
- shrinkWrap: true,
- children: children,
- ),
+ type: MaterialType.transparency,
+ textStyle: route.style,
+ child: ScrollConfiguration(
+ behavior: const _DropdownScrollBehavior(),
+ child: Scrollbar(
+ child: ListView(
+ controller: widget.route.scrollController,
+ padding: kMaterialListPadding,
+ itemExtent: _kMenuItemHeight,
+ shrinkWrap: true,
+ children: children,
),
),
),
),
),
- );
+ ),
+ );
}
}
@@ -253,7 +253,7 @@
double left;
switch (textDirection) {
case TextDirection.rtl:
- left = buttonRect.right.clamp(0.0, size.width) - childSize.width;
+ left = buttonRect.right.clamp(0.0, size.width) - childSize.width;
break;
case TextDirection.ltr:
left = buttonRect.left.clamp(0.0, size.width - childSize.width);
@@ -637,7 +637,7 @@
/// if the first item were selected.
final T value;
- /// Displayed if [value] is null.
+ /// A placeholder widget that is displayed if no item is selected, i.e. if [value] is null.
final Widget hint;
/// A message to show when the dropdown is disabled.
@@ -645,12 +645,14 @@
/// Displayed if [items] or [onChanged] is null.
final Widget disabledHint;
+ /// {@template flutter.material.dropdownButton.onChanged}
/// Called when the user selects an item.
///
/// If the [onChanged] callback is null or the list of [items] is null
/// then the dropdown button will be disabled, i.e. its arrow will be
/// displayed in grey and it will not respond to input. A disabled button
/// will display the [disabledHint] widget if it is non-null.
+ /// {@endtemplate}
final ValueChanged<T> onChanged;
/// The z-coordinate at which to place the menu when open.
@@ -777,7 +779,7 @@
final Rect itemRect = itemBox.localToGlobal(Offset.zero) & itemBox.size;
final TextDirection textDirection = Directionality.of(context);
final EdgeInsetsGeometry menuMargin = ButtonTheme.of(context).alignedDropdown
- ?_kAlignedMenuMargin
+ ? _kAlignedMenuMargin
: _kUnalignedMenuMargin;
assert(_dropdownRoute == null);
@@ -813,22 +815,20 @@
Color get _iconColor {
// These colors are not defined in the Material Design spec.
if (_enabled) {
- if (widget.iconEnabledColor != null) {
+ if (widget.iconEnabledColor != null)
return widget.iconEnabledColor;
- }
- switch(Theme.of(context).brightness) {
+ switch (Theme.of(context).brightness) {
case Brightness.light:
return Colors.grey.shade700;
case Brightness.dark:
return Colors.white70;
}
} else {
- if (widget.iconDisabledColor != null) {
+ if (widget.iconDisabledColor != null)
return widget.iconDisabledColor;
- }
- switch(Theme.of(context).brightness) {
+ switch (Theme.of(context).brightness) {
case Brightness.light:
return Colors.grey.shade400;
case Brightness.dark:
@@ -852,8 +852,9 @@
final List<Widget> items = _enabled ? List<Widget>.from(widget.items) : <Widget>[];
int hintIndex;
if (widget.hint != null || (!_enabled && widget.disabledHint != null)) {
- final Widget emplacedHint =
- _enabled ? widget.hint : DropdownMenuItem<Widget>(child: widget.disabledHint ?? widget.hint);
+ final Widget emplacedHint = _enabled
+ ? widget.hint
+ : DropdownMenuItem<Widget>(child: widget.disabledHint ?? widget.hint);
hintIndex = items.length;
items.add(DefaultTextStyle(
style: _textStyle.copyWith(color: Theme.of(context).hintColor),
@@ -893,7 +894,9 @@
mainAxisAlignment: MainAxisAlignment.spaceBetween,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
- widget.isExpanded ? Expanded(child: innerItemsWidget) : innerItemsWidget,
+ widget.isExpanded
+ ? Expanded(child: innerItemsWidget)
+ : innerItemsWidget,
IconTheme(
data: IconThemeData(
color: _iconColor,
@@ -918,7 +921,12 @@
child: widget.underline ?? Container(
height: 1.0,
decoration: const BoxDecoration(
- border: Border(bottom: BorderSide(color: Color(0xFFBDBDBD), width: 0.0))
+ border: Border(
+ bottom: BorderSide(
+ color: Color(0xFFBDBDBD),
+ width: 0.0,
+ ),
+ ),
),
),
),
@@ -947,39 +955,73 @@
Key key,
T value,
@required List<DropdownMenuItem<T>> items,
- this.onChanged,
- InputDecoration decoration = const InputDecoration(),
+ Widget hint,
+ @required this.onChanged,
+ this.decoration = const InputDecoration(),
FormFieldSetter<T> onSaved,
FormFieldValidator<T> validator,
- Widget hint,
- }) : assert(decoration != null),
+ bool autovalidate = false,
+ Widget disabledHint,
+ int elevation = 8,
+ TextStyle style,
+ Widget icon,
+ Color iconDisabledColor,
+ Color iconEnabledColor,
+ double iconSize = 24.0,
+ bool isDense = false,
+ bool isExpanded = false,
+ }) : assert(items == null || items.isEmpty || value == null || items.where((DropdownMenuItem<T> item) => item.value == value).length == 1),
+ assert(decoration != null),
+ assert(elevation != null),
+ assert(iconSize != null),
+ assert(isDense != null),
+ assert(isExpanded != null),
super(
key: key,
onSaved: onSaved,
initialValue: value,
validator: validator,
+ autovalidate: autovalidate,
builder: (FormFieldState<T> field) {
- final InputDecoration effectiveDecoration = decoration
- .applyDefaults(Theme.of(field.context).inputDecorationTheme);
+ final InputDecoration effectiveDecoration = decoration.applyDefaults(
+ Theme.of(field.context).inputDecorationTheme,
+ );
return InputDecorator(
decoration: effectiveDecoration.copyWith(errorText: field.errorText),
isEmpty: value == null,
child: DropdownButtonHideUnderline(
child: DropdownButton<T>(
- isDense: true,
value: value,
items: items,
hint: hint,
- onChanged: field.didChange,
+ onChanged: onChanged == null ? null : field.didChange,
+ disabledHint: disabledHint,
+ elevation: elevation,
+ style: style,
+ icon: icon,
+ iconDisabledColor: iconDisabledColor,
+ iconEnabledColor: iconEnabledColor,
+ iconSize: iconSize,
+ isDense: isDense,
+ isExpanded: isExpanded,
),
),
);
}
);
- /// Called when the user selects an item.
+ /// {@macro flutter.material.dropdownButton.onChanged}
final ValueChanged<T> onChanged;
+ /// The decoration to show around the dropdown button form field.
+ ///
+ /// By default, draws a horizontal line under the dropdown button field but can be
+ /// configured to show an icon, label, hint text, and error text.
+ ///
+ /// Specify null to remove the decoration entirely (including the
+ /// extra padding introduced by the decoration to save space for the labels).
+ final InputDecoration decoration;
+
@override
FormFieldState<T> createState() => _DropdownButtonFormFieldState<T>();
}
@@ -991,7 +1033,7 @@
@override
void didChange(T value) {
super.didChange(value);
- if (widget.onChanged != null)
- widget.onChanged(value);
+ assert(widget.onChanged != null);
+ widget.onChanged(value);
}
}
diff --git a/packages/flutter/test/material/dropdown_test.dart b/packages/flutter/test/material/dropdown_test.dart
index 03c480c..3048709 100644
--- a/packages/flutter/test/material/dropdown_test.dart
+++ b/packages/flutter/test/material/dropdown_test.dart
@@ -9,6 +9,7 @@
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
+import '../rendering/mock_canvas.dart';
import '../widgets/semantics_tester.dart';
const List<String> menuItems = <String>['one', 'two', 'three', 'four'];
@@ -76,6 +77,59 @@
);
}
+Widget buildFormFrame({
+ Key buttonKey,
+ bool autovalidate = false,
+ int elevation = 8,
+ String value = 'two',
+ ValueChanged<String> onChanged,
+ Widget icon,
+ Color iconDisabledColor,
+ Color iconEnabledColor,
+ double iconSize = 24.0,
+ bool isDense = false,
+ bool isExpanded = false,
+ Widget hint,
+ Widget disabledHint,
+ Widget underline,
+ List<String> items = menuItems,
+ Alignment alignment = Alignment.center,
+ TextDirection textDirection = TextDirection.ltr,
+}) {
+ return TestApp(
+ textDirection: textDirection,
+ child: Material(
+ child: Align(
+ alignment: alignment,
+ child: RepaintBoundary(
+ child: DropdownButtonFormField<String>(
+ key: buttonKey,
+ autovalidate: autovalidate,
+ elevation: elevation,
+ value: value,
+ hint: hint,
+ disabledHint: disabledHint,
+ onChanged: onChanged,
+ icon: icon,
+ iconSize: iconSize,
+ iconDisabledColor: iconDisabledColor,
+ iconEnabledColor: iconEnabledColor,
+ isDense: isDense,
+ isExpanded: isExpanded,
+ items: items == null ? null : items.map<DropdownMenuItem<String>>((String item) {
+ return DropdownMenuItem<String>(
+ key: ValueKey<String>(item),
+ value: item,
+ child: Text(item, key: ValueKey<String>(item + 'Text')),
+ );
+ }).toList(),
+ ),
+ ),
+ ),
+ ),
+ );
+}
+
class TestApp extends StatefulWidget {
const TestApp({ this.textDirection, this.child });
final TextDirection textDirection;
@@ -125,6 +179,29 @@
expect(box0.size, equals(box1.size));
}
+void verifyPaintedShadow(Finder customPaint, int elevation) {
+ const Rect originalRectangle = Rect.fromLTRB(0.0, 0.0, 800, 208.0);
+
+ final List<BoxShadow> boxShadows = List<BoxShadow>.generate(3, (int index) => kElevationToShadow[elevation][index]);
+ final List<RRect> rrects = List<RRect>.generate(3, (int index) {
+ return RRect.fromRectAndRadius(
+ originalRectangle.shift(
+ boxShadows[index].offset
+ ).inflate(boxShadows[index].spreadRadius),
+ const Radius.circular(2.0),
+ );
+ });
+
+ expect(
+ customPaint,
+ paints
+ ..save()
+ ..rrect(rrect: rrects[0], color: boxShadows[0].color, hasMaskFilter: true)
+ ..rrect(rrect: rrects[1], color: boxShadows[1].color, hasMaskFilter: true)
+ ..rrect(rrect: rrects[2], color: boxShadows[2].color, hasMaskFilter: true),
+ );
+}
+
bool sameGeometry(RenderBox box1, RenderBox box2) {
expect(box1.localToGlobal(Offset.zero), equals(box2.localToGlobal(Offset.zero)));
expect(box1.size.height, equals(box2.size.height));
@@ -257,48 +334,6 @@
expect(value, equals('two'));
});
- testWidgets('Dropdown form field', (WidgetTester tester) async {
- String value = 'one';
-
- await tester.pumpWidget(
- StatefulBuilder(
- builder: (BuildContext context, StateSetter setState) {
- return MaterialApp(
- home: Material(
- child: DropdownButtonFormField<String>(
- value: value,
- hint: const Text('Select Value'),
- decoration: const InputDecoration(
- prefixIcon: Icon(Icons.fastfood)
- ),
- items: menuItems.map((String val) {
- return DropdownMenuItem<String>(
- value: val,
- child: Text(val),
- );
- }).toList(),
- onChanged: (String v) {
- setState(() {
- value = v;
- });
- },
- validator: (String v) => v == null ? 'Must select value' : null,
- ),
- ),
- );
- }
- )
- );
-
- expect(value, equals('one'));
- await tester.tap(find.text('one'));
- await tester.pumpAndSettle();
- await tester.tap(find.text('three').last);
- await tester.pump();
- await tester.pumpAndSettle();
- expect(value, equals('three'));
- });
-
testWidgets('Dropdown in ListView', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/12053
// Positions a DropdownButton at the left and right edges of the screen,
@@ -1281,4 +1316,329 @@
await tester.pumpWidget(buildFrame(buttonKey: buttonKey, value: 'two', onChanged: onChanged));
expect(tester.widget<DecoratedBox>(decoratedBox).decoration, defaultDecoration);
});
+
+ testWidgets('Dropdown form field with autovalidation test', (WidgetTester tester) async {
+ String value = 'one';
+ int _validateCalled = 0;
+
+ await tester.pumpWidget(
+ StatefulBuilder(
+ builder: (BuildContext context, StateSetter setState) {
+ return MaterialApp(
+ home: Material(
+ child: DropdownButtonFormField<String>(
+ value: value,
+ hint: const Text('Select Value'),
+ decoration: const InputDecoration(
+ prefixIcon: Icon(Icons.fastfood)
+ ),
+ items: menuItems.map((String value) {
+ return DropdownMenuItem<String>(
+ value: value,
+ child: Text(value),
+ );
+ }).toList(),
+ onChanged: (String newValue) {
+ setState(() {
+ value = newValue;
+ });
+ },
+ validator: (String currentValue) {
+ _validateCalled++;
+ return currentValue == null ? 'Must select value' : null;
+ },
+ autovalidate: true,
+ ),
+ ),
+ );
+ },
+ ),
+ );
+
+ expect(_validateCalled, 1);
+ expect(value, equals('one'));
+ await tester.tap(find.text('one'));
+ await tester.pumpAndSettle();
+ await tester.tap(find.text('three').last);
+ await tester.pump();
+ expect(_validateCalled, 2);
+ await tester.pumpAndSettle();
+ expect(value, equals('three'));
+ });
+
+ testWidgets('Arrow icon aligns with the edge of button in form field when expanded', (WidgetTester tester) async {
+ final Key buttonKey = UniqueKey();
+
+ // There shouldn't be overflow when expanded although list contains longer items.
+ final List<String> items = <String>[
+ '1234567890',
+ 'abcdefghijklmnopqrstuvwxyz1234567890abcdefghijklmnopqrstuvwxyz1234567890',
+ ];
+
+ await tester.pumpWidget(
+ buildFormFrame(
+ buttonKey: buttonKey,
+ value: '1234567890',
+ isExpanded: true,
+ onChanged: onChanged,
+ items: items,
+ ),
+ );
+ final RenderBox buttonBox = tester.renderObject<RenderBox>(
+ find.byKey(buttonKey),
+ );
+ expect(buttonBox.attached, isTrue);
+
+ final RenderBox arrowIcon = tester.renderObject<RenderBox>(
+ find.byIcon(Icons.arrow_drop_down),
+ );
+ expect(arrowIcon.attached, isTrue);
+
+ // Arrow icon should be aligned with far right of button when expanded
+ expect(
+ arrowIcon.localToGlobal(Offset.zero).dx,
+ buttonBox.size.centerRight(Offset(-arrowIcon.size.width, 0.0)).dx,
+ );
+ });
+
+ testWidgets('Dropdown button form field with isDense:true aligns selected menu item', (WidgetTester tester) async {
+ final Key buttonKey = UniqueKey();
+ const String value = 'two';
+
+ await tester.pumpWidget(
+ buildFormFrame(
+ buttonKey: buttonKey,
+ value: value,
+ isDense: true,
+ onChanged: onChanged,
+ ),
+ );
+ final RenderBox buttonBox = tester.renderObject<RenderBox>(
+ find.byKey(buttonKey),
+ );
+ expect(buttonBox.attached, isTrue);
+
+ await tester.tap(find.text('two'));
+ await tester.pump();
+ await tester.pump(const Duration(seconds: 1)); // finish the menu animation
+
+ // The selected dropdown item is both in menu we just popped up, and in
+ // the IndexedStack contained by the dropdown button. Both of them should
+ // have the same vertical center as the button.
+ final List<RenderBox> itemBoxes = tester.renderObjectList<RenderBox>(
+ find.byKey(const ValueKey<String>('two')),
+ ).toList();
+ expect(itemBoxes.length, equals(2));
+
+ // When isDense is true, the button's height is reduced. The menu items'
+ // heights are not.
+ final List<double> itemBoxesHeight = itemBoxes.map<double>((RenderBox box) => box.size.height).toList();
+ final double menuItemHeight = itemBoxesHeight.reduce(math.max);
+ expect(menuItemHeight, greaterThanOrEqualTo(buttonBox.size.height));
+
+ for (RenderBox itemBox in itemBoxes) {
+ expect(itemBox.attached, isTrue);
+ final Offset buttonBoxCenter = buttonBox.size.center(buttonBox.localToGlobal(Offset.zero));
+ final Offset itemBoxCenter = itemBox.size.center(itemBox.localToGlobal(Offset.zero));
+ expect(buttonBoxCenter.dy, equals(itemBoxCenter.dy));
+ }
+ });
+
+ testWidgets('Dropdown button form field - custom text style', (WidgetTester tester) async {
+ const String value = 'foo';
+ final UniqueKey itemKey = UniqueKey();
+
+ await tester.pumpWidget(
+ TestApp(
+ textDirection: TextDirection.ltr,
+ child: Material(
+ child: DropdownButtonFormField<String>(
+ value: value,
+ items: <DropdownMenuItem<String>>[
+ DropdownMenuItem<String>(
+ key: itemKey,
+ value: 'foo',
+ child: const Text(value),
+ ),
+ ],
+ isDense: true,
+ onChanged: (_) { },
+ style: const TextStyle(
+ color: Colors.amber,
+ fontSize: 20.0,
+ ),
+ ),
+ ),
+ ),
+ );
+
+ final RichText richText = tester.widget<RichText>(
+ find.descendant(
+ of: find.byKey(itemKey),
+ matching: find.byType(RichText),
+ ),
+ );
+
+ expect(richText.text.style.color, Colors.amber);
+ expect(richText.text.style.fontSize, 20.0);
+ });
+
+ testWidgets('Dropdown form field - disabledHint displays when the items list is empty, when items is null', (WidgetTester tester) async {
+ final Key buttonKey = UniqueKey();
+
+ Widget build({ List<String> items }){
+ return buildFormFrame(
+ items: items,
+ buttonKey: buttonKey,
+ value: null,
+ hint: const Text('enabled'),
+ disabledHint: const Text('disabled'),
+ );
+ }
+ // [disabledHint] should display when [items] is null
+ await tester.pumpWidget(build(items: null));
+ expect(find.text('enabled'), findsNothing);
+ expect(find.text('disabled'), findsOneWidget);
+
+ // [disabledHint] should display when [items] is an empty list.
+ await tester.pumpWidget(build(items: <String>[]));
+ expect(find.text('enabled'), findsNothing);
+ expect(find.text('disabled'), findsOneWidget);
+ });
+
+ testWidgets('Dropdown form field - disabledHint displays when onChanged is null', (WidgetTester tester) async {
+ final Key buttonKey = UniqueKey();
+
+ Widget build({ List<String> items, ValueChanged<String> onChanged }){
+ return buildFormFrame(
+ items: items,
+ buttonKey: buttonKey,
+ value: null,
+ onChanged: onChanged,
+ hint: const Text('enabled'),
+ disabledHint: const Text('disabled'),
+ );
+ }
+ await tester.pumpWidget(build(items: menuItems, onChanged: null));
+ expect(find.text('enabled'), findsNothing);
+ expect(find.text('disabled'), findsOneWidget);
+ });
+
+ testWidgets('Dropdown form field - disabled hint should be of same size as enabled hint', (WidgetTester tester) async {
+ final Key buttonKey = UniqueKey();
+
+ Widget build({ List<String> items}){
+ return buildFormFrame(
+ items: items,
+ buttonKey: buttonKey,
+ value: null,
+ hint: const Text('enabled'),
+ disabledHint: const Text('disabled'),
+ );
+ }
+ await tester.pumpWidget(build(items: null));
+ final RenderBox disabledHintBox = tester.renderObject<RenderBox>(
+ find.byKey(buttonKey),
+ );
+
+ await tester.pumpWidget(build(items: menuItems));
+ final RenderBox enabledHintBox = tester.renderObject<RenderBox>(
+ find.byKey(buttonKey),
+ );
+ expect(enabledHintBox.localToGlobal(Offset.zero), equals(disabledHintBox.localToGlobal(Offset.zero)));
+ expect(enabledHintBox.size, equals(disabledHintBox.size));
+ });
+
+ testWidgets('Dropdown form field - Custom icon size and colors', (WidgetTester tester) async {
+ final Key iconKey = UniqueKey();
+ final Icon customIcon = Icon(Icons.assessment, key: iconKey);
+
+ await tester.pumpWidget(buildFormFrame(
+ icon: customIcon,
+ iconSize: 30.0,
+ iconEnabledColor: Colors.pink,
+ iconDisabledColor: Colors.orange,
+ onChanged: onChanged,
+ ));
+
+ // test for size
+ final RenderBox icon = tester.renderObject(find.byKey(iconKey));
+ expect(icon.size, const Size(30.0, 30.0));
+
+ // test for enabled color
+ final RichText enabledRichText = tester.widget<RichText>(_iconRichText(iconKey));
+ expect(enabledRichText.text.style.color, Colors.pink);
+
+ // test for disabled color
+ await tester.pumpWidget(buildFormFrame(
+ icon: customIcon,
+ iconSize: 30.0,
+ iconEnabledColor: Colors.pink,
+ iconDisabledColor: Colors.orange,
+ items: null,
+ ));
+
+ final RichText disabledRichText = tester.widget<RichText>(_iconRichText(iconKey));
+ expect(disabledRichText.text.style.color, Colors.orange);
+ });
+
+ testWidgets('Dropdown form field - default elevation', (WidgetTester tester) async {
+ final Key buttonKey = UniqueKey();
+ debugDisableShadows = false;
+ await tester.pumpWidget(buildFormFrame(
+ buttonKey: buttonKey,
+ items: menuItems,
+ onChanged: onChanged,
+ ));
+ await tester.tap(find.byKey(buttonKey));
+ await tester.pumpAndSettle();
+
+ final Finder customPaint = find.ancestor(
+ of: find.text('one').last,
+ matching: find.byType(CustomPaint),
+ ).last;
+
+ // Verifying whether or not default elevation(i.e. 8) paints desired shadow
+ verifyPaintedShadow(customPaint, 8);
+ debugDisableShadows = true;
+ });
+
+ testWidgets('Dropdown form field - custom elevation', (WidgetTester tester) async {
+ debugDisableShadows = false;
+ final Key buttonKeyOne = UniqueKey();
+ final Key buttonKeyTwo = UniqueKey();
+
+ await tester.pumpWidget(buildFormFrame(
+ buttonKey: buttonKeyOne,
+ items: menuItems,
+ elevation: 16,
+ onChanged: onChanged,
+ ));
+ await tester.tap(find.byKey(buttonKeyOne));
+ await tester.pumpAndSettle();
+
+ final Finder customPaintOne = find.ancestor(
+ of: find.text('one').last,
+ matching: find.byType(CustomPaint),
+ ).last;
+
+ verifyPaintedShadow(customPaintOne, 16);
+ await tester.tap(find.text('one').last);
+ await tester.pumpWidget(buildFormFrame(
+ buttonKey: buttonKeyTwo,
+ items: menuItems,
+ elevation: 24,
+ onChanged: onChanged,
+ ));
+ await tester.tap(find.byKey(buttonKeyTwo));
+ await tester.pumpAndSettle();
+
+ final Finder customPaintTwo = find.ancestor(
+ of: find.text('one').last,
+ matching: find.byType(CustomPaint),
+ ).last;
+
+ verifyPaintedShadow(customPaintTwo, 24);
+ debugDisableShadows = true;
+ });
}