mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
showDialogs adds a requestFocus
parameter. (#162928)
Fixes: #162920 ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [x] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview [Tree Hygiene]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md [test-exempt]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests [Flutter Style Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md [Features we expect every widget to implement]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md [Data Driven Fixes]: https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
This commit is contained in:
parent
01fe4e262a
commit
a6ff677120
@ -1277,6 +1277,10 @@ class CupertinoModalPopupRoute<T> extends PopupRoute<T> {
|
|||||||
/// [StatefulBuilder] or a custom [StatefulWidget] if the widget needs to
|
/// [StatefulBuilder] or a custom [StatefulWidget] if the widget needs to
|
||||||
/// update dynamically.
|
/// update dynamically.
|
||||||
///
|
///
|
||||||
|
/// The [requestFocus] parameter is used to specify whether the popup should
|
||||||
|
/// request focus when shown.
|
||||||
|
/// {@macro flutter.widgets.navigator.Route.requestFocus}
|
||||||
|
///
|
||||||
/// {@macro flutter.widgets.RawDialogRoute}
|
/// {@macro flutter.widgets.RawDialogRoute}
|
||||||
///
|
///
|
||||||
/// Returns a `Future` that resolves to the value that was passed to
|
/// Returns a `Future` that resolves to the value that was passed to
|
||||||
@ -1318,6 +1322,7 @@ Future<T?> showCupertinoModalPopup<T>({
|
|||||||
bool semanticsDismissible = false,
|
bool semanticsDismissible = false,
|
||||||
RouteSettings? routeSettings,
|
RouteSettings? routeSettings,
|
||||||
Offset? anchorPoint,
|
Offset? anchorPoint,
|
||||||
|
bool? requestFocus,
|
||||||
}) {
|
}) {
|
||||||
return Navigator.of(context, rootNavigator: useRootNavigator).push(
|
return Navigator.of(context, rootNavigator: useRootNavigator).push(
|
||||||
CupertinoModalPopupRoute<T>(
|
CupertinoModalPopupRoute<T>(
|
||||||
@ -1328,6 +1333,7 @@ Future<T?> showCupertinoModalPopup<T>({
|
|||||||
semanticsDismissible: semanticsDismissible,
|
semanticsDismissible: semanticsDismissible,
|
||||||
settings: routeSettings,
|
settings: routeSettings,
|
||||||
anchorPoint: anchorPoint,
|
anchorPoint: anchorPoint,
|
||||||
|
requestFocus: requestFocus,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -1361,6 +1367,9 @@ Widget _buildCupertinoDialogTransitions(
|
|||||||
/// By default, `useRootNavigator` is `true` and the dialog route created by
|
/// By default, `useRootNavigator` is `true` and the dialog route created by
|
||||||
/// this method is pushed to the root navigator.
|
/// this method is pushed to the root navigator.
|
||||||
///
|
///
|
||||||
|
/// {@macro flutter.material.dialog.requestFocus}
|
||||||
|
/// {@macro flutter.widgets.navigator.Route.requestFocus}
|
||||||
|
///
|
||||||
/// {@macro flutter.widgets.RawDialogRoute}
|
/// {@macro flutter.widgets.RawDialogRoute}
|
||||||
///
|
///
|
||||||
/// If the application has multiple [Navigator] objects, it may be necessary to
|
/// If the application has multiple [Navigator] objects, it may be necessary to
|
||||||
@ -1405,6 +1414,7 @@ Future<T?> showCupertinoDialog<T>({
|
|||||||
bool barrierDismissible = false,
|
bool barrierDismissible = false,
|
||||||
RouteSettings? routeSettings,
|
RouteSettings? routeSettings,
|
||||||
Offset? anchorPoint,
|
Offset? anchorPoint,
|
||||||
|
bool? requestFocus,
|
||||||
}) {
|
}) {
|
||||||
return Navigator.of(context, rootNavigator: useRootNavigator).push<T>(
|
return Navigator.of(context, rootNavigator: useRootNavigator).push<T>(
|
||||||
CupertinoDialogRoute<T>(
|
CupertinoDialogRoute<T>(
|
||||||
@ -1415,6 +1425,7 @@ Future<T?> showCupertinoDialog<T>({
|
|||||||
barrierColor: CupertinoDynamicColor.resolve(kCupertinoModalBarrierColor, context),
|
barrierColor: CupertinoDynamicColor.resolve(kCupertinoModalBarrierColor, context),
|
||||||
settings: routeSettings,
|
settings: routeSettings,
|
||||||
anchorPoint: anchorPoint,
|
anchorPoint: anchorPoint,
|
||||||
|
requestFocus: requestFocus,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1202,6 +1202,10 @@ class ModalBottomSheetRoute<T> extends PopupRoute<T> {
|
|||||||
/// The [sheetAnimationStyle] parameter is used to override the modal bottom sheet
|
/// The [sheetAnimationStyle] parameter is used to override the modal bottom sheet
|
||||||
/// animation duration and reverse animation duration.
|
/// animation duration and reverse animation duration.
|
||||||
///
|
///
|
||||||
|
/// The [requestFocus] parameter is used to specify whether the bottom sheet should
|
||||||
|
/// request focus when shown.
|
||||||
|
/// {@macro flutter.widgets.navigator.Route.requestFocus}
|
||||||
|
///
|
||||||
/// If [AnimationStyle.duration] is provided, it will be used to override
|
/// If [AnimationStyle.duration] is provided, it will be used to override
|
||||||
/// the modal bottom sheet animation duration in the underlying
|
/// the modal bottom sheet animation duration in the underlying
|
||||||
/// [BottomSheet.createAnimationController].
|
/// [BottomSheet.createAnimationController].
|
||||||
@ -1254,6 +1258,7 @@ Future<T?> showModalBottomSheet<T>({
|
|||||||
AnimationController? transitionAnimationController,
|
AnimationController? transitionAnimationController,
|
||||||
Offset? anchorPoint,
|
Offset? anchorPoint,
|
||||||
AnimationStyle? sheetAnimationStyle,
|
AnimationStyle? sheetAnimationStyle,
|
||||||
|
bool? requestFocus,
|
||||||
}) {
|
}) {
|
||||||
assert(debugCheckHasMediaQuery(context));
|
assert(debugCheckHasMediaQuery(context));
|
||||||
assert(debugCheckHasMaterialLocalizations(context));
|
assert(debugCheckHasMaterialLocalizations(context));
|
||||||
@ -1282,6 +1287,7 @@ Future<T?> showModalBottomSheet<T>({
|
|||||||
anchorPoint: anchorPoint,
|
anchorPoint: anchorPoint,
|
||||||
useSafeArea: useSafeArea,
|
useSafeArea: useSafeArea,
|
||||||
sheetAnimationStyle: sheetAnimationStyle,
|
sheetAnimationStyle: sheetAnimationStyle,
|
||||||
|
requestFocus: requestFocus,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1395,6 +1395,12 @@ Widget _buildMaterialDialogTransitions(
|
|||||||
/// [TraversalEdgeBehavior.closedLoop] is used, because it's typical for dialogs
|
/// [TraversalEdgeBehavior.closedLoop] is used, because it's typical for dialogs
|
||||||
/// to allow users to cycle through dialog widgets without leaving the dialog.
|
/// to allow users to cycle through dialog widgets without leaving the dialog.
|
||||||
///
|
///
|
||||||
|
/// {@template flutter.material.dialog.requestFocus}
|
||||||
|
/// The `requestFocus` argument is used to specify whether the dialog should
|
||||||
|
/// request focus when shown.
|
||||||
|
/// {@endtemplate}
|
||||||
|
/// {@macro flutter.widgets.navigator.Route.requestFocus}
|
||||||
|
///
|
||||||
/// {@macro flutter.widgets.RawDialogRoute}
|
/// {@macro flutter.widgets.RawDialogRoute}
|
||||||
///
|
///
|
||||||
/// If the application has multiple [Navigator] objects, it may be necessary to
|
/// If the application has multiple [Navigator] objects, it may be necessary to
|
||||||
@ -1459,6 +1465,7 @@ Future<T?> showDialog<T>({
|
|||||||
RouteSettings? routeSettings,
|
RouteSettings? routeSettings,
|
||||||
Offset? anchorPoint,
|
Offset? anchorPoint,
|
||||||
TraversalEdgeBehavior? traversalEdgeBehavior,
|
TraversalEdgeBehavior? traversalEdgeBehavior,
|
||||||
|
bool? requestFocus,
|
||||||
}) {
|
}) {
|
||||||
assert(_debugIsActive(context));
|
assert(_debugIsActive(context));
|
||||||
assert(debugCheckHasMaterialLocalizations(context));
|
assert(debugCheckHasMaterialLocalizations(context));
|
||||||
@ -1484,6 +1491,7 @@ Future<T?> showDialog<T>({
|
|||||||
themes: themes,
|
themes: themes,
|
||||||
anchorPoint: anchorPoint,
|
anchorPoint: anchorPoint,
|
||||||
traversalEdgeBehavior: traversalEdgeBehavior ?? TraversalEdgeBehavior.closedLoop,
|
traversalEdgeBehavior: traversalEdgeBehavior ?? TraversalEdgeBehavior.closedLoop,
|
||||||
|
requestFocus: requestFocus,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -1507,6 +1515,7 @@ Future<T?> showAdaptiveDialog<T>({
|
|||||||
RouteSettings? routeSettings,
|
RouteSettings? routeSettings,
|
||||||
Offset? anchorPoint,
|
Offset? anchorPoint,
|
||||||
TraversalEdgeBehavior? traversalEdgeBehavior,
|
TraversalEdgeBehavior? traversalEdgeBehavior,
|
||||||
|
bool? requestFocus,
|
||||||
}) {
|
}) {
|
||||||
final ThemeData theme = Theme.of(context);
|
final ThemeData theme = Theme.of(context);
|
||||||
switch (theme.platform) {
|
switch (theme.platform) {
|
||||||
@ -1525,6 +1534,7 @@ Future<T?> showAdaptiveDialog<T>({
|
|||||||
routeSettings: routeSettings,
|
routeSettings: routeSettings,
|
||||||
anchorPoint: anchorPoint,
|
anchorPoint: anchorPoint,
|
||||||
traversalEdgeBehavior: traversalEdgeBehavior,
|
traversalEdgeBehavior: traversalEdgeBehavior,
|
||||||
|
requestFocus: requestFocus,
|
||||||
);
|
);
|
||||||
case TargetPlatform.iOS:
|
case TargetPlatform.iOS:
|
||||||
case TargetPlatform.macOS:
|
case TargetPlatform.macOS:
|
||||||
@ -1536,6 +1546,7 @@ Future<T?> showAdaptiveDialog<T>({
|
|||||||
useRootNavigator: useRootNavigator,
|
useRootNavigator: useRootNavigator,
|
||||||
anchorPoint: anchorPoint,
|
anchorPoint: anchorPoint,
|
||||||
routeSettings: routeSettings,
|
routeSettings: routeSettings,
|
||||||
|
requestFocus: requestFocus,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -164,8 +164,10 @@ abstract class Route<T> extends _RoutePlaceholder {
|
|||||||
/// If the [settings] are not provided, an empty [RouteSettings] object is
|
/// If the [settings] are not provided, an empty [RouteSettings] object is
|
||||||
/// used instead.
|
/// used instead.
|
||||||
///
|
///
|
||||||
|
/// {@template flutter.widgets.navigator.Route.requestFocus}
|
||||||
/// If [requestFocus] is not provided, the value of [Navigator.requestFocus] is
|
/// If [requestFocus] is not provided, the value of [Navigator.requestFocus] is
|
||||||
/// used instead.
|
/// used instead.
|
||||||
|
/// {@endtemplate}
|
||||||
Route({RouteSettings? settings, bool? requestFocus})
|
Route({RouteSettings? settings, bool? requestFocus})
|
||||||
: _settings = settings ?? const RouteSettings(),
|
: _settings = settings ?? const RouteSettings(),
|
||||||
_requestFocus = requestFocus {
|
_requestFocus = requestFocus {
|
||||||
|
@ -2631,6 +2631,9 @@ class RawDialogRoute<T> extends PopupRoute<T> {
|
|||||||
/// The `routeSettings` will be used in the construction of the dialog's route.
|
/// The `routeSettings` will be used in the construction of the dialog's route.
|
||||||
/// See [RouteSettings] for more details.
|
/// See [RouteSettings] for more details.
|
||||||
///
|
///
|
||||||
|
/// {@macro flutter.material.dialog.requestFocus}
|
||||||
|
/// {@macro flutter.widgets.navigator.Route.requestFocus}
|
||||||
|
///
|
||||||
/// {@macro flutter.widgets.RawDialogRoute}
|
/// {@macro flutter.widgets.RawDialogRoute}
|
||||||
///
|
///
|
||||||
/// Returns a [Future] that resolves to the value (if any) that was passed to
|
/// Returns a [Future] that resolves to the value (if any) that was passed to
|
||||||
@ -2672,6 +2675,7 @@ Future<T?> showGeneralDialog<T extends Object?>({
|
|||||||
bool useRootNavigator = true,
|
bool useRootNavigator = true,
|
||||||
RouteSettings? routeSettings,
|
RouteSettings? routeSettings,
|
||||||
Offset? anchorPoint,
|
Offset? anchorPoint,
|
||||||
|
bool? requestFocus,
|
||||||
}) {
|
}) {
|
||||||
assert(!barrierDismissible || barrierLabel != null);
|
assert(!barrierDismissible || barrierLabel != null);
|
||||||
return Navigator.of(context, rootNavigator: useRootNavigator).push<T>(
|
return Navigator.of(context, rootNavigator: useRootNavigator).push<T>(
|
||||||
@ -2684,6 +2688,7 @@ Future<T?> showGeneralDialog<T extends Object?>({
|
|||||||
transitionBuilder: transitionBuilder,
|
transitionBuilder: transitionBuilder,
|
||||||
settings: routeSettings,
|
settings: routeSettings,
|
||||||
anchorPoint: anchorPoint,
|
anchorPoint: anchorPoint,
|
||||||
|
requestFocus: requestFocus,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -3111,6 +3111,76 @@ void main() {
|
|||||||
expect(focusScopeNode.hasFocus, isFalse);
|
expect(focusScopeNode.hasFocus, isFalse);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
testWidgets('requestFocus works correctly in showCupertinoModalPopup.', (
|
||||||
|
WidgetTester tester,
|
||||||
|
) async {
|
||||||
|
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
|
||||||
|
final FocusNode focusNode = FocusNode();
|
||||||
|
addTearDown(focusNode.dispose);
|
||||||
|
await tester.pumpWidget(
|
||||||
|
CupertinoApp(navigatorKey: navigatorKey, home: CupertinoTextField(focusNode: focusNode)),
|
||||||
|
);
|
||||||
|
focusNode.requestFocus();
|
||||||
|
await tester.pump();
|
||||||
|
expect(focusNode.hasFocus, true);
|
||||||
|
|
||||||
|
showCupertinoModalPopup<void>(
|
||||||
|
context: navigatorKey.currentContext!,
|
||||||
|
requestFocus: true,
|
||||||
|
builder: (BuildContext context) => const Text('popup'),
|
||||||
|
);
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
expect(FocusScope.of(tester.element(find.text('popup'))).hasFocus, true);
|
||||||
|
expect(focusNode.hasFocus, false);
|
||||||
|
|
||||||
|
navigatorKey.currentState!.pop();
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
expect(focusNode.hasFocus, true);
|
||||||
|
|
||||||
|
showCupertinoModalPopup<void>(
|
||||||
|
context: navigatorKey.currentContext!,
|
||||||
|
requestFocus: false,
|
||||||
|
builder: (BuildContext context) => const Text('popup'),
|
||||||
|
);
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
expect(FocusScope.of(tester.element(find.text('popup'))).hasFocus, false);
|
||||||
|
expect(focusNode.hasFocus, true);
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('requestFocus works correctly in showCupertinoDialog.', (WidgetTester tester) async {
|
||||||
|
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
|
||||||
|
final FocusNode focusNode = FocusNode();
|
||||||
|
addTearDown(focusNode.dispose);
|
||||||
|
await tester.pumpWidget(
|
||||||
|
CupertinoApp(navigatorKey: navigatorKey, home: CupertinoTextField(focusNode: focusNode)),
|
||||||
|
);
|
||||||
|
focusNode.requestFocus();
|
||||||
|
await tester.pump();
|
||||||
|
expect(focusNode.hasFocus, true);
|
||||||
|
|
||||||
|
showCupertinoDialog<void>(
|
||||||
|
context: navigatorKey.currentContext!,
|
||||||
|
requestFocus: true,
|
||||||
|
builder: (BuildContext context) => const Text('dialog'),
|
||||||
|
);
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
expect(FocusScope.of(tester.element(find.text('dialog'))).hasFocus, true);
|
||||||
|
expect(focusNode.hasFocus, false);
|
||||||
|
|
||||||
|
navigatorKey.currentState!.pop();
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
expect(focusNode.hasFocus, true);
|
||||||
|
|
||||||
|
showCupertinoDialog<void>(
|
||||||
|
context: navigatorKey.currentContext!,
|
||||||
|
requestFocus: false,
|
||||||
|
builder: (BuildContext context) => const Text('dialog'),
|
||||||
|
);
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
expect(FocusScope.of(tester.element(find.text('dialog'))).hasFocus, false);
|
||||||
|
expect(focusNode.hasFocus, true);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
class MockNavigatorObserver extends NavigatorObserver {
|
class MockNavigatorObserver extends NavigatorObserver {
|
||||||
|
@ -2750,6 +2750,43 @@ void main() {
|
|||||||
expect(getTextFieldFocusNode()?.hasFocus, true);
|
expect(getTextFieldFocusNode()?.hasFocus, true);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
testWidgets('requestFocus works correctly in showModalBottomSheet.', (WidgetTester tester) async {
|
||||||
|
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
|
||||||
|
final FocusNode focusNode = FocusNode();
|
||||||
|
addTearDown(focusNode.dispose);
|
||||||
|
await tester.pumpWidget(
|
||||||
|
MaterialApp(
|
||||||
|
navigatorKey: navigatorKey,
|
||||||
|
home: Scaffold(body: TextField(focusNode: focusNode)),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
focusNode.requestFocus();
|
||||||
|
await tester.pump();
|
||||||
|
expect(focusNode.hasFocus, true);
|
||||||
|
|
||||||
|
showModalBottomSheet<void>(
|
||||||
|
context: navigatorKey.currentContext!,
|
||||||
|
requestFocus: true,
|
||||||
|
builder: (BuildContext context) => const Text('BottomSheet'),
|
||||||
|
);
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
expect(FocusScope.of(tester.element(find.text('BottomSheet'))).hasFocus, true);
|
||||||
|
expect(focusNode.hasFocus, false);
|
||||||
|
|
||||||
|
navigatorKey.currentState!.pop();
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
expect(focusNode.hasFocus, true);
|
||||||
|
|
||||||
|
showModalBottomSheet<void>(
|
||||||
|
context: navigatorKey.currentContext!,
|
||||||
|
requestFocus: false,
|
||||||
|
builder: (BuildContext context) => const Text('BottomSheet'),
|
||||||
|
);
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
expect(FocusScope.of(tester.element(find.text('BottomSheet'))).hasFocus, false);
|
||||||
|
expect(focusNode.hasFocus, true);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
class _TestPage extends StatelessWidget {
|
class _TestPage extends StatelessWidget {
|
||||||
|
@ -2820,6 +2820,43 @@ void main() {
|
|||||||
expect(find.text(dialogText), findsOneWidget);
|
expect(find.text(dialogText), findsOneWidget);
|
||||||
expect(getTextFieldFocusNode()?.hasFocus, true);
|
expect(getTextFieldFocusNode()?.hasFocus, true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
testWidgets('requestFocus works correctly in showDialog.', (WidgetTester tester) async {
|
||||||
|
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
|
||||||
|
final FocusNode focusNode = FocusNode();
|
||||||
|
addTearDown(focusNode.dispose);
|
||||||
|
await tester.pumpWidget(
|
||||||
|
MaterialApp(
|
||||||
|
navigatorKey: navigatorKey,
|
||||||
|
home: Scaffold(body: TextField(focusNode: focusNode)),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
focusNode.requestFocus();
|
||||||
|
await tester.pump();
|
||||||
|
expect(focusNode.hasFocus, true);
|
||||||
|
|
||||||
|
showDialog<void>(
|
||||||
|
context: navigatorKey.currentContext!,
|
||||||
|
requestFocus: true,
|
||||||
|
builder: (BuildContext context) => const Text('dialog'),
|
||||||
|
);
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
expect(FocusScope.of(tester.element(find.text('dialog'))).hasFocus, true);
|
||||||
|
expect(focusNode.hasFocus, false);
|
||||||
|
|
||||||
|
navigatorKey.currentState!.pop();
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
expect(focusNode.hasFocus, true);
|
||||||
|
|
||||||
|
showDialog<void>(
|
||||||
|
context: navigatorKey.currentContext!,
|
||||||
|
requestFocus: false,
|
||||||
|
builder: (BuildContext context) => const Text('dialog'),
|
||||||
|
);
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
expect(FocusScope.of(tester.element(find.text('dialog'))).hasFocus, false);
|
||||||
|
expect(focusNode.hasFocus, true);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@pragma('vm:entry-point')
|
@pragma('vm:entry-point')
|
||||||
|
@ -2656,6 +2656,53 @@ void main() {
|
|||||||
expect(focusScope.directionalTraversalEdgeBehavior, element);
|
expect(focusScope.directionalTraversalEdgeBehavior, element);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
testWidgets('requestFocus works correctly in showGeneralDialog.', (WidgetTester tester) async {
|
||||||
|
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
|
||||||
|
final FocusNode focusNode = FocusNode();
|
||||||
|
addTearDown(focusNode.dispose);
|
||||||
|
await tester.pumpWidget(
|
||||||
|
MaterialApp(
|
||||||
|
navigatorKey: navigatorKey,
|
||||||
|
home: Scaffold(body: TextField(focusNode: focusNode)),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
focusNode.requestFocus();
|
||||||
|
await tester.pump();
|
||||||
|
expect(focusNode.hasFocus, true);
|
||||||
|
|
||||||
|
showGeneralDialog<void>(
|
||||||
|
context: navigatorKey.currentContext!,
|
||||||
|
requestFocus: true,
|
||||||
|
pageBuilder:
|
||||||
|
(
|
||||||
|
BuildContext context,
|
||||||
|
Animation<double> animation,
|
||||||
|
Animation<double> secondaryAnimation,
|
||||||
|
) => const Text('dialog'),
|
||||||
|
);
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
expect(FocusScope.of(tester.element(find.text('dialog'))).hasFocus, true);
|
||||||
|
expect(focusNode.hasFocus, false);
|
||||||
|
|
||||||
|
navigatorKey.currentState!.pop();
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
expect(focusNode.hasFocus, true);
|
||||||
|
|
||||||
|
showGeneralDialog<void>(
|
||||||
|
context: navigatorKey.currentContext!,
|
||||||
|
requestFocus: false,
|
||||||
|
pageBuilder:
|
||||||
|
(
|
||||||
|
BuildContext context,
|
||||||
|
Animation<double> animation,
|
||||||
|
Animation<double> secondaryAnimation,
|
||||||
|
) => const Text('dialog'),
|
||||||
|
);
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
expect(FocusScope.of(tester.element(find.text('dialog'))).hasFocus, false);
|
||||||
|
expect(focusNode.hasFocus, true);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
double _getOpacity(GlobalKey key, WidgetTester tester) {
|
double _getOpacity(GlobalKey key, WidgetTester tester) {
|
||||||
|
Loading…
Reference in New Issue
Block a user