Commit 379c3f46 authored by shihchanghsiungsonos's avatar shihchanghsiungsonos Committed by Dan Field

Fix the issue of TextSelection could misbehave inside a Nested Overlay (#49257)

parent a499e05f
......@@ -242,8 +242,18 @@ class Overlay extends StatefulWidget {
/// ```dart
/// OverlayState overlay = Overlay.of(context);
/// ```
static OverlayState of(BuildContext context, { Widget debugRequiredFor }) {
final OverlayState result = context.findAncestorStateOfType<OverlayState>();
///
/// If `rootOverlay` is set to true, the state from the furthest instance of
/// this class is given instead. Useful for installing overlay entries
/// above all subsequent instances of [Overlay].
static OverlayState of(
BuildContext context, {
bool rootOverlay = false,
Widget debugRequiredFor,
}) {
final OverlayState result = rootOverlay
? context.findRootAncestorStateOfType<OverlayState>()
: context.findAncestorStateOfType<OverlayState>();
assert(() {
if (debugRequiredFor != null && result == null) {
final List<DiagnosticsNode> information = <DiagnosticsNode>[
......
......@@ -283,7 +283,7 @@ class TextSelectionOverlay {
assert(handlesVisible != null),
_handlesVisible = handlesVisible,
_value = value {
final OverlayState overlay = Overlay.of(context);
final OverlayState overlay = Overlay.of(context, rootOverlay: true);
assert(overlay != null,
'No Overlay widget exists above $context.\n'
'Usually the Navigator created by WidgetsApp provides the overlay. Perhaps your '
......@@ -410,7 +410,7 @@ class TextSelectionOverlay {
Overlay.of(context, debugRequiredFor: debugRequiredFor).insertAll(_handles);
Overlay.of(context, rootOverlay: true, debugRequiredFor: debugRequiredFor).insertAll(_handles);
}
/// Destroys the handles by removing them from overlay.
......@@ -426,7 +426,7 @@ class TextSelectionOverlay {
void showToolbar() {
assert(_toolbar == null);
_toolbar = OverlayEntry(builder: _buildToolbar);
Overlay.of(context, debugRequiredFor: debugRequiredFor).insert(_toolbar);
Overlay.of(context, rootOverlay: true, debugRequiredFor: debugRequiredFor).insert(_toolbar);
_toolbarController.forward(from: 0.0);
}
......
......@@ -7432,4 +7432,45 @@ void main() {
expect(textFieldSize1, equals(textFieldSize2));
});
testWidgets(
'The selection menu displays in an Overlay without error',
(WidgetTester tester) async {
// This is a regression test for
// https://github.com/flutter/flutter/issues/43787
final TextEditingController controller = TextEditingController(
text: 'This is a test that shows some odd behavior with Text Selection!',
);
await tester.pumpWidget(MaterialApp(
home: Scaffold(
body: Container(
color: Colors.grey,
child: Center(
child: Container(
color: Colors.red,
width: 300,
height: 600,
child: Overlay(
initialEntries: <OverlayEntry>[
OverlayEntry(
builder: (BuildContext context) => Center(
child: TextField(
controller: controller,
),
),
)
],
),
),
),
),
),
));
await _showSelectionMenuAt(tester, controller, controller.text.indexOf('test'));
await tester.pumpAndSettle();
expect(tester.takeException(), isNull);
},
);
}
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