Add onFocusChange property for ListTile widget (#111498)
This commit is contained in:
parent
50f101acd4
commit
a9c2f8b9e9
@ -176,6 +176,7 @@ class CheckboxListTile extends StatelessWidget {
|
|||||||
this.side,
|
this.side,
|
||||||
this.visualDensity,
|
this.visualDensity,
|
||||||
this.focusNode,
|
this.focusNode,
|
||||||
|
this.onFocusChange,
|
||||||
this.enableFeedback,
|
this.enableFeedback,
|
||||||
}) : assert(tristate != null),
|
}) : assert(tristate != null),
|
||||||
assert(tristate || value != null),
|
assert(tristate || value != null),
|
||||||
@ -320,6 +321,9 @@ class CheckboxListTile extends StatelessWidget {
|
|||||||
/// {@macro flutter.widgets.Focus.focusNode}
|
/// {@macro flutter.widgets.Focus.focusNode}
|
||||||
final FocusNode? focusNode;
|
final FocusNode? focusNode;
|
||||||
|
|
||||||
|
/// {@macro flutter.material.inkwell.onFocusChange}
|
||||||
|
final ValueChanged<bool>? onFocusChange;
|
||||||
|
|
||||||
/// {@macro flutter.material.ListTile.enableFeedback}
|
/// {@macro flutter.material.ListTile.enableFeedback}
|
||||||
///
|
///
|
||||||
/// See also:
|
/// See also:
|
||||||
@ -401,6 +405,7 @@ class CheckboxListTile extends StatelessWidget {
|
|||||||
tileColor: tileColor,
|
tileColor: tileColor,
|
||||||
visualDensity: visualDensity,
|
visualDensity: visualDensity,
|
||||||
focusNode: focusNode,
|
focusNode: focusNode,
|
||||||
|
onFocusChange: onFocusChange,
|
||||||
enableFeedback: enableFeedback,
|
enableFeedback: enableFeedback,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -559,10 +559,12 @@ class InkResponse extends StatelessWidget {
|
|||||||
/// duplication of information.
|
/// duplication of information.
|
||||||
final bool excludeFromSemantics;
|
final bool excludeFromSemantics;
|
||||||
|
|
||||||
|
/// {@template flutter.material.inkwell.onFocusChange}
|
||||||
/// Handler called when the focus changes.
|
/// Handler called when the focus changes.
|
||||||
///
|
///
|
||||||
/// Called with true if this widget's node gains focus, and false if it loses
|
/// Called with true if this widget's node gains focus, and false if it loses
|
||||||
/// focus.
|
/// focus.
|
||||||
|
/// {@endtemplate}
|
||||||
final ValueChanged<bool>? onFocusChange;
|
final ValueChanged<bool>? onFocusChange;
|
||||||
|
|
||||||
/// {@macro flutter.widgets.Focus.autofocus}
|
/// {@macro flutter.widgets.Focus.autofocus}
|
||||||
|
@ -282,6 +282,7 @@ class ListTile extends StatelessWidget {
|
|||||||
this.enabled = true,
|
this.enabled = true,
|
||||||
this.onTap,
|
this.onTap,
|
||||||
this.onLongPress,
|
this.onLongPress,
|
||||||
|
this.onFocusChange,
|
||||||
this.mouseCursor,
|
this.mouseCursor,
|
||||||
this.selected = false,
|
this.selected = false,
|
||||||
this.focusColor,
|
this.focusColor,
|
||||||
@ -456,6 +457,9 @@ class ListTile extends StatelessWidget {
|
|||||||
/// Inoperative if [enabled] is false.
|
/// Inoperative if [enabled] is false.
|
||||||
final GestureLongPressCallback? onLongPress;
|
final GestureLongPressCallback? onLongPress;
|
||||||
|
|
||||||
|
/// {@macro flutter.material.inkwell.onFocusChange}
|
||||||
|
final ValueChanged<bool>? onFocusChange;
|
||||||
|
|
||||||
/// {@template flutter.material.ListTile.mouseCursor}
|
/// {@template flutter.material.ListTile.mouseCursor}
|
||||||
/// The cursor for a mouse pointer when it enters or is hovering over the
|
/// The cursor for a mouse pointer when it enters or is hovering over the
|
||||||
/// widget.
|
/// widget.
|
||||||
@ -738,6 +742,7 @@ class ListTile extends StatelessWidget {
|
|||||||
customBorder: shape ?? tileTheme.shape,
|
customBorder: shape ?? tileTheme.shape,
|
||||||
onTap: enabled ? onTap : null,
|
onTap: enabled ? onTap : null,
|
||||||
onLongPress: enabled ? onLongPress : null,
|
onLongPress: enabled ? onLongPress : null,
|
||||||
|
onFocusChange: onFocusChange,
|
||||||
mouseCursor: effectiveMouseCursor,
|
mouseCursor: effectiveMouseCursor,
|
||||||
canRequestFocus: enabled,
|
canRequestFocus: enabled,
|
||||||
focusNode: focusNode,
|
focusNode: focusNode,
|
||||||
|
@ -171,6 +171,7 @@ class RadioListTile<T> extends StatelessWidget {
|
|||||||
this.selectedTileColor,
|
this.selectedTileColor,
|
||||||
this.visualDensity,
|
this.visualDensity,
|
||||||
this.focusNode,
|
this.focusNode,
|
||||||
|
this.onFocusChange,
|
||||||
this.enableFeedback,
|
this.enableFeedback,
|
||||||
}) : assert(toggleable != null),
|
}) : assert(toggleable != null),
|
||||||
assert(isThreeLine != null),
|
assert(isThreeLine != null),
|
||||||
@ -320,6 +321,9 @@ class RadioListTile<T> extends StatelessWidget {
|
|||||||
/// {@macro flutter.widgets.Focus.focusNode}
|
/// {@macro flutter.widgets.Focus.focusNode}
|
||||||
final FocusNode? focusNode;
|
final FocusNode? focusNode;
|
||||||
|
|
||||||
|
/// {@macro flutter.material.inkwell.onFocusChange}
|
||||||
|
final ValueChanged<bool>? onFocusChange;
|
||||||
|
|
||||||
/// {@macro flutter.material.ListTile.enableFeedback}
|
/// {@macro flutter.material.ListTile.enableFeedback}
|
||||||
///
|
///
|
||||||
/// See also:
|
/// See also:
|
||||||
@ -385,6 +389,7 @@ class RadioListTile<T> extends StatelessWidget {
|
|||||||
contentPadding: contentPadding,
|
contentPadding: contentPadding,
|
||||||
visualDensity: visualDensity,
|
visualDensity: visualDensity,
|
||||||
focusNode: focusNode,
|
focusNode: focusNode,
|
||||||
|
onFocusChange: onFocusChange,
|
||||||
enableFeedback: enableFeedback,
|
enableFeedback: enableFeedback,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -114,6 +114,7 @@ class Switch extends StatelessWidget {
|
|||||||
this.overlayColor,
|
this.overlayColor,
|
||||||
this.splashRadius,
|
this.splashRadius,
|
||||||
this.focusNode,
|
this.focusNode,
|
||||||
|
this.onFocusChange,
|
||||||
this.autofocus = false,
|
this.autofocus = false,
|
||||||
}) : _switchType = _SwitchType.material,
|
}) : _switchType = _SwitchType.material,
|
||||||
assert(dragStartBehavior != null),
|
assert(dragStartBehavior != null),
|
||||||
@ -158,6 +159,7 @@ class Switch extends StatelessWidget {
|
|||||||
this.overlayColor,
|
this.overlayColor,
|
||||||
this.splashRadius,
|
this.splashRadius,
|
||||||
this.focusNode,
|
this.focusNode,
|
||||||
|
this.onFocusChange,
|
||||||
this.autofocus = false,
|
this.autofocus = false,
|
||||||
}) : assert(autofocus != null),
|
}) : assert(autofocus != null),
|
||||||
assert(activeThumbImage != null || onActiveThumbImageError == null),
|
assert(activeThumbImage != null || onActiveThumbImageError == null),
|
||||||
@ -455,6 +457,9 @@ class Switch extends StatelessWidget {
|
|||||||
/// {@macro flutter.widgets.Focus.focusNode}
|
/// {@macro flutter.widgets.Focus.focusNode}
|
||||||
final FocusNode? focusNode;
|
final FocusNode? focusNode;
|
||||||
|
|
||||||
|
/// {@macro flutter.material.inkwell.onFocusChange}
|
||||||
|
final ValueChanged<bool>? onFocusChange;
|
||||||
|
|
||||||
/// {@macro flutter.widgets.Focus.autofocus}
|
/// {@macro flutter.widgets.Focus.autofocus}
|
||||||
final bool autofocus;
|
final bool autofocus;
|
||||||
|
|
||||||
@ -478,6 +483,7 @@ class Switch extends StatelessWidget {
|
|||||||
final Size size = _getSwitchSize(context);
|
final Size size = _getSwitchSize(context);
|
||||||
return Focus(
|
return Focus(
|
||||||
focusNode: focusNode,
|
focusNode: focusNode,
|
||||||
|
onFocusChange: onFocusChange,
|
||||||
autofocus: autofocus,
|
autofocus: autofocus,
|
||||||
child: Container(
|
child: Container(
|
||||||
width: size.width, // Same size as the Material switch.
|
width: size.width, // Same size as the Material switch.
|
||||||
@ -518,6 +524,7 @@ class Switch extends StatelessWidget {
|
|||||||
overlayColor: overlayColor,
|
overlayColor: overlayColor,
|
||||||
splashRadius: splashRadius,
|
splashRadius: splashRadius,
|
||||||
focusNode: focusNode,
|
focusNode: focusNode,
|
||||||
|
onFocusChange: onFocusChange,
|
||||||
autofocus: autofocus,
|
autofocus: autofocus,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -577,6 +584,7 @@ class _MaterialSwitch extends StatefulWidget {
|
|||||||
this.overlayColor,
|
this.overlayColor,
|
||||||
this.splashRadius,
|
this.splashRadius,
|
||||||
this.focusNode,
|
this.focusNode,
|
||||||
|
this.onFocusChange,
|
||||||
this.autofocus = false,
|
this.autofocus = false,
|
||||||
}) : assert(dragStartBehavior != null),
|
}) : assert(dragStartBehavior != null),
|
||||||
assert(activeThumbImage != null || onActiveThumbImageError == null),
|
assert(activeThumbImage != null || onActiveThumbImageError == null),
|
||||||
@ -603,6 +611,7 @@ class _MaterialSwitch extends StatefulWidget {
|
|||||||
final MaterialStateProperty<Color?>? overlayColor;
|
final MaterialStateProperty<Color?>? overlayColor;
|
||||||
final double? splashRadius;
|
final double? splashRadius;
|
||||||
final FocusNode? focusNode;
|
final FocusNode? focusNode;
|
||||||
|
final Function(bool)? onFocusChange;
|
||||||
final bool autofocus;
|
final bool autofocus;
|
||||||
final Size size;
|
final Size size;
|
||||||
|
|
||||||
@ -822,6 +831,7 @@ class _MaterialSwitchState extends State<_MaterialSwitch> with TickerProviderSta
|
|||||||
child: buildToggleable(
|
child: buildToggleable(
|
||||||
mouseCursor: effectiveMouseCursor,
|
mouseCursor: effectiveMouseCursor,
|
||||||
focusNode: widget.focusNode,
|
focusNode: widget.focusNode,
|
||||||
|
onFocusChange: widget.onFocusChange,
|
||||||
autofocus: widget.autofocus,
|
autofocus: widget.autofocus,
|
||||||
size: widget.size,
|
size: widget.size,
|
||||||
painter: _painter
|
painter: _painter
|
||||||
|
@ -176,6 +176,7 @@ class SwitchListTile extends StatelessWidget {
|
|||||||
this.selectedTileColor,
|
this.selectedTileColor,
|
||||||
this.visualDensity,
|
this.visualDensity,
|
||||||
this.focusNode,
|
this.focusNode,
|
||||||
|
this.onFocusChange,
|
||||||
this.enableFeedback,
|
this.enableFeedback,
|
||||||
this.hoverColor,
|
this.hoverColor,
|
||||||
}) : _switchListTileType = _SwitchListTileType.material,
|
}) : _switchListTileType = _SwitchListTileType.material,
|
||||||
@ -221,6 +222,7 @@ class SwitchListTile extends StatelessWidget {
|
|||||||
this.selectedTileColor,
|
this.selectedTileColor,
|
||||||
this.visualDensity,
|
this.visualDensity,
|
||||||
this.focusNode,
|
this.focusNode,
|
||||||
|
this.onFocusChange,
|
||||||
this.enableFeedback,
|
this.enableFeedback,
|
||||||
this.hoverColor,
|
this.hoverColor,
|
||||||
}) : _switchListTileType = _SwitchListTileType.adaptive,
|
}) : _switchListTileType = _SwitchListTileType.adaptive,
|
||||||
@ -368,6 +370,9 @@ class SwitchListTile extends StatelessWidget {
|
|||||||
/// {@macro flutter.widgets.Focus.focusNode}
|
/// {@macro flutter.widgets.Focus.focusNode}
|
||||||
final FocusNode? focusNode;
|
final FocusNode? focusNode;
|
||||||
|
|
||||||
|
/// {@macro flutter.material.inkwell.onFocusChange}
|
||||||
|
final ValueChanged<bool>? onFocusChange;
|
||||||
|
|
||||||
/// {@macro flutter.material.ListTile.enableFeedback}
|
/// {@macro flutter.material.ListTile.enableFeedback}
|
||||||
///
|
///
|
||||||
/// See also:
|
/// See also:
|
||||||
@ -394,6 +399,7 @@ class SwitchListTile extends StatelessWidget {
|
|||||||
inactiveTrackColor: inactiveTrackColor,
|
inactiveTrackColor: inactiveTrackColor,
|
||||||
inactiveThumbColor: inactiveThumbColor,
|
inactiveThumbColor: inactiveThumbColor,
|
||||||
autofocus: autofocus,
|
autofocus: autofocus,
|
||||||
|
onFocusChange: onFocusChange,
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -409,6 +415,7 @@ class SwitchListTile extends StatelessWidget {
|
|||||||
inactiveTrackColor: inactiveTrackColor,
|
inactiveTrackColor: inactiveTrackColor,
|
||||||
inactiveThumbColor: inactiveThumbColor,
|
inactiveThumbColor: inactiveThumbColor,
|
||||||
autofocus: autofocus,
|
autofocus: autofocus,
|
||||||
|
onFocusChange: onFocusChange,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -452,6 +459,7 @@ class SwitchListTile extends StatelessWidget {
|
|||||||
tileColor: tileColor,
|
tileColor: tileColor,
|
||||||
visualDensity: visualDensity,
|
visualDensity: visualDensity,
|
||||||
focusNode: focusNode,
|
focusNode: focusNode,
|
||||||
|
onFocusChange: onFocusChange,
|
||||||
enableFeedback: enableFeedback,
|
enableFeedback: enableFeedback,
|
||||||
hoverColor: hoverColor,
|
hoverColor: hoverColor,
|
||||||
),
|
),
|
||||||
|
@ -305,6 +305,7 @@ mixin ToggleableStateMixin<S extends StatefulWidget> on TickerProviderStateMixin
|
|||||||
/// build method - potentially after wrapping it in other widgets.
|
/// build method - potentially after wrapping it in other widgets.
|
||||||
Widget buildToggleable({
|
Widget buildToggleable({
|
||||||
FocusNode? focusNode,
|
FocusNode? focusNode,
|
||||||
|
Function(bool)? onFocusChange,
|
||||||
bool autofocus = false,
|
bool autofocus = false,
|
||||||
required MaterialStateProperty<MouseCursor> mouseCursor,
|
required MaterialStateProperty<MouseCursor> mouseCursor,
|
||||||
required Size size,
|
required Size size,
|
||||||
@ -314,6 +315,7 @@ mixin ToggleableStateMixin<S extends StatefulWidget> on TickerProviderStateMixin
|
|||||||
actions: _actionMap,
|
actions: _actionMap,
|
||||||
focusNode: focusNode,
|
focusNode: focusNode,
|
||||||
autofocus: autofocus,
|
autofocus: autofocus,
|
||||||
|
onFocusChange: onFocusChange,
|
||||||
enabled: isInteractive,
|
enabled: isInteractive,
|
||||||
onShowFocusHighlight: _handleFocusHighlightChanged,
|
onShowFocusHighlight: _handleFocusHighlightChanged,
|
||||||
onShowHoverHighlight: _handleHoverChanged,
|
onShowHoverHighlight: _handleHoverChanged,
|
||||||
|
@ -431,6 +431,35 @@ void main() {
|
|||||||
expect(tileNode.hasPrimaryFocus, isTrue);
|
expect(tileNode.hasPrimaryFocus, isTrue);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
testWidgets('CheckboxListTile onFocusChange callback', (WidgetTester tester) async {
|
||||||
|
final FocusNode node = FocusNode(debugLabel: 'CheckboxListTile onFocusChange');
|
||||||
|
bool gotFocus = false;
|
||||||
|
await tester.pumpWidget(
|
||||||
|
MaterialApp(
|
||||||
|
home: Material(
|
||||||
|
child: CheckboxListTile(
|
||||||
|
value: true,
|
||||||
|
focusNode: node,
|
||||||
|
onFocusChange: (bool focused) {
|
||||||
|
gotFocus = focused;
|
||||||
|
},
|
||||||
|
onChanged: (bool? value) {},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
node.requestFocus();
|
||||||
|
await tester.pump();
|
||||||
|
expect(gotFocus, isTrue);
|
||||||
|
expect(node.hasFocus, isTrue);
|
||||||
|
|
||||||
|
node.unfocus();
|
||||||
|
await tester.pump();
|
||||||
|
expect(gotFocus, isFalse);
|
||||||
|
expect(node.hasFocus, isFalse);
|
||||||
|
});
|
||||||
|
|
||||||
testWidgets('CheckboxListTile can be disabled', (WidgetTester tester) async {
|
testWidgets('CheckboxListTile can be disabled', (WidgetTester tester) async {
|
||||||
bool? value = false;
|
bool? value = false;
|
||||||
bool enabled = true;
|
bool enabled = true;
|
||||||
|
@ -1476,6 +1476,34 @@ void main() {
|
|||||||
expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.basic);
|
expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.basic);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
testWidgets('ListTile onFocusChange callback', (WidgetTester tester) async {
|
||||||
|
final FocusNode node = FocusNode(debugLabel: 'ListTile Focus');
|
||||||
|
bool gotFocus = false;
|
||||||
|
await tester.pumpWidget(
|
||||||
|
MaterialApp(
|
||||||
|
home: Material(
|
||||||
|
child: ListTile(
|
||||||
|
focusNode: node,
|
||||||
|
onFocusChange: (bool focused) {
|
||||||
|
gotFocus = focused;
|
||||||
|
},
|
||||||
|
onTap: () {},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
node.requestFocus();
|
||||||
|
await tester.pump();
|
||||||
|
expect(gotFocus, isTrue);
|
||||||
|
expect(node.hasFocus, isTrue);
|
||||||
|
|
||||||
|
node.unfocus();
|
||||||
|
await tester.pump();
|
||||||
|
expect(gotFocus, isFalse);
|
||||||
|
expect(node.hasFocus, isFalse);
|
||||||
|
});
|
||||||
|
|
||||||
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;
|
final Color tileColor = Colors.green.shade500;
|
||||||
|
@ -793,6 +793,36 @@ void main() {
|
|||||||
expect(tileNode.hasPrimaryFocus, isTrue);
|
expect(tileNode.hasPrimaryFocus, isTrue);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
testWidgets('RadioListTile onFocusChange callback', (WidgetTester tester) async {
|
||||||
|
final FocusNode node = FocusNode(debugLabel: 'RadioListTile onFocusChange');
|
||||||
|
bool gotFocus = false;
|
||||||
|
await tester.pumpWidget(
|
||||||
|
MaterialApp(
|
||||||
|
home: Material(
|
||||||
|
child: RadioListTile<bool>(
|
||||||
|
value: true,
|
||||||
|
focusNode: node,
|
||||||
|
onFocusChange: (bool focused) {
|
||||||
|
gotFocus = focused;
|
||||||
|
},
|
||||||
|
onChanged: (bool? value) {},
|
||||||
|
groupValue: true,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
node.requestFocus();
|
||||||
|
await tester.pump();
|
||||||
|
expect(gotFocus, isTrue);
|
||||||
|
expect(node.hasFocus, isTrue);
|
||||||
|
|
||||||
|
node.unfocus();
|
||||||
|
await tester.pump();
|
||||||
|
expect(gotFocus, isFalse);
|
||||||
|
expect(node.hasFocus, isFalse);
|
||||||
|
});
|
||||||
|
|
||||||
group('feedback', () {
|
group('feedback', () {
|
||||||
late FeedbackTester feedback;
|
late FeedbackTester feedback;
|
||||||
|
|
||||||
|
@ -480,6 +480,64 @@ void main() {
|
|||||||
expect(tileNode.hasPrimaryFocus, isTrue);
|
expect(tileNode.hasPrimaryFocus, isTrue);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
testWidgets('SwitchListTile onFocusChange callback', (WidgetTester tester) async {
|
||||||
|
final FocusNode node = FocusNode(debugLabel: 'SwitchListTile onFocusChange');
|
||||||
|
bool gotFocus = false;
|
||||||
|
await tester.pumpWidget(
|
||||||
|
MaterialApp(
|
||||||
|
home: Material(
|
||||||
|
child: SwitchListTile(
|
||||||
|
value: true,
|
||||||
|
focusNode: node,
|
||||||
|
onFocusChange: (bool focused) {
|
||||||
|
gotFocus = focused;
|
||||||
|
},
|
||||||
|
onChanged: (bool value) {},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
node.requestFocus();
|
||||||
|
await tester.pump();
|
||||||
|
expect(gotFocus, isTrue);
|
||||||
|
expect(node.hasFocus, isTrue);
|
||||||
|
|
||||||
|
node.unfocus();
|
||||||
|
await tester.pump();
|
||||||
|
expect(gotFocus, isFalse);
|
||||||
|
expect(node.hasFocus, isFalse);
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('SwitchListTile.adaptive onFocusChange Callback', (WidgetTester tester) async {
|
||||||
|
final FocusNode node = FocusNode(debugLabel: 'SwitchListTile.adaptive onFocusChange');
|
||||||
|
bool gotFocus = false;
|
||||||
|
await tester.pumpWidget(
|
||||||
|
MaterialApp(
|
||||||
|
home: Material(
|
||||||
|
child: SwitchListTile.adaptive(
|
||||||
|
value: true,
|
||||||
|
focusNode: node,
|
||||||
|
onFocusChange: (bool focused) {
|
||||||
|
gotFocus = focused;
|
||||||
|
},
|
||||||
|
onChanged: (bool value) {},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
node.requestFocus();
|
||||||
|
await tester.pump();
|
||||||
|
expect(gotFocus, isTrue);
|
||||||
|
expect(node.hasFocus, isTrue);
|
||||||
|
|
||||||
|
node.unfocus();
|
||||||
|
await tester.pump();
|
||||||
|
expect(gotFocus, isFalse);
|
||||||
|
expect(node.hasFocus, isFalse);
|
||||||
|
});
|
||||||
|
|
||||||
group('feedback', () {
|
group('feedback', () {
|
||||||
late FeedbackTester feedback;
|
late FeedbackTester feedback;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user