diff --git a/packages/flutter/lib/src/cupertino/text_selection.dart b/packages/flutter/lib/src/cupertino/text_selection.dart index 03f4339ffbb..2eb110124d6 100644 --- a/packages/flutter/lib/src/cupertino/text_selection.dart +++ b/packages/flutter/lib/src/cupertino/text_selection.dart @@ -164,15 +164,13 @@ class _ToolbarRenderBox extends RenderShiftedBox { child.layout(heightConstraint.enforce(enforcedConstraint), parentUsesSize: true,); final _ToolbarParentData childParentData = child.parentData; - final Offset localTopCenter = globalToLocal(Offset(_arrowTipX, _barTopY)); - // The local x-coordinate of the center of the toolbar. final double lowerBound = child.size.width/2 + _kToolbarScreenPadding; final double upperBound = size.width - child.size.width/2 - _kToolbarScreenPadding; - final double adjustedCenterX = localTopCenter.dx.clamp(lowerBound, upperBound); + final double adjustedCenterX = _arrowTipX.clamp(lowerBound, upperBound); - childParentData.offset = Offset(adjustedCenterX - child.size.width / 2, localTopCenter.dy); - childParentData.arrowXOffsetFromCenter = localTopCenter.dx - adjustedCenterX; + childParentData.offset = Offset(adjustedCenterX - child.size.width / 2, _barTopY); + childParentData.arrowXOffsetFromCenter = _arrowTipX - adjustedCenterX; } // The path is described in the toolbar's coordinate system. diff --git a/packages/flutter/test/cupertino/text_field_test.dart b/packages/flutter/test/cupertino/text_field_test.dart index 943fb31dd2e..97d09628e0e 100644 --- a/packages/flutter/test/cupertino/text_field_test.dart +++ b/packages/flutter/test/cupertino/text_field_test.dart @@ -3276,6 +3276,55 @@ void main() { tester.binding.window.physicalSizeTestValue = null; tester.binding.window.devicePixelRatioTestValue = null; }); + + // This is a regression test for + // https://github.com/flutter/flutter/issues/37046. + testWidgets('No exceptions when showing selection menu inside of nested Navigators', (WidgetTester tester) async { + const String testValue = '123456'; + final TextEditingController controller = TextEditingController( + text: testValue, + ); + await tester.pumpWidget( + CupertinoApp( + home: CupertinoPageScaffold( + child: Center( + child: Column( + children: [ + Container( + height: 100, + color: CupertinoColors.activeOrange, + ), + Expanded( + child: Navigator( + onGenerateRoute: (_) => + CupertinoPageRoute(builder: (_) => Container( + child: CupertinoTextField( + controller: controller, + ), + )), + ), + ), + ], + ), + ), + ), + ), + ); + + // No text selection toolbar. + expect(find.byType(CupertinoTextSelectionToolbar), findsNothing); + + // Double tap on the text in the input. + await tester.pumpAndSettle(); + await tester.tapAt(textOffsetToPosition(tester, testValue.length ~/ 2)); + await tester.pump(const Duration(milliseconds: 100)); + await tester.tapAt(textOffsetToPosition(tester, testValue.length ~/ 2)); + await tester.pumpAndSettle(); + + // Now the text selection toolbar is showing and there were no exceptions. + expect(find.byType(CupertinoTextSelectionToolbar), findsOneWidget); + expect(tester.takeException(), null); + }); }); group('textAlignVertical position', () { diff --git a/packages/flutter/test/cupertino/text_selection_test.dart b/packages/flutter/test/cupertino/text_selection_test.dart index dc884da0036..5cc1a136b01 100644 --- a/packages/flutter/test/cupertino/text_selection_test.dart +++ b/packages/flutter/test/cupertino/text_selection_test.dart @@ -3,8 +3,8 @@ // found in the LICENSE file. import 'package:flutter_test/flutter_test.dart'; -import 'package:flutter/widgets.dart'; import 'package:flutter/cupertino.dart'; +import 'package:flutter/widgets.dart'; void main() { group('canSelectAll', () {