@@ -6805,4 +6805,101 @@ void main() {
6805
6805
}, variant: TargetPlatformVariant .all ());
6806
6806
});
6807
6807
});
6808
+
6809
+ testWidgets ('Can drag handles to change selection correctly in multiline' , (WidgetTester tester) async {
6810
+ final TextEditingController controller = TextEditingController ();
6811
+
6812
+ await tester.pumpWidget (
6813
+ CupertinoApp (
6814
+ debugShowCheckedModeBanner: false ,
6815
+ home: CupertinoPageScaffold (
6816
+ child: CupertinoTextField (
6817
+ dragStartBehavior: DragStartBehavior .down,
6818
+ controller: controller,
6819
+ style: const TextStyle (color: Colors .black, fontSize: 34.0 ),
6820
+ maxLines: 3 ,
6821
+ ),
6822
+ ),
6823
+ ),
6824
+ );
6825
+
6826
+ const String testValue =
6827
+ 'First line of text is\n '
6828
+ 'Second line goes until\n '
6829
+ 'Third line of stuff' ;
6830
+
6831
+ const String cutValue =
6832
+ 'First line of text is\n '
6833
+ 'Second until\n '
6834
+ 'Third line of stuff' ;
6835
+ await tester.enterText (find.byType (CupertinoTextField ), testValue);
6836
+
6837
+ // Skip past scrolling animation.
6838
+ await tester.pump ();
6839
+ await tester.pumpAndSettle (const Duration (milliseconds: 200 ));
6840
+
6841
+ // Check that the text spans multiple lines.
6842
+ final Offset firstPos = textOffsetToPosition (tester, testValue.indexOf ('First' ));
6843
+ final Offset secondPos = textOffsetToPosition (tester, testValue.indexOf ('Second' ));
6844
+ final Offset thirdPos = textOffsetToPosition (tester, testValue.indexOf ('Third' ));
6845
+ expect (firstPos.dx, secondPos.dx);
6846
+ expect (firstPos.dx, thirdPos.dx);
6847
+ expect (firstPos.dy, lessThan (secondPos.dy));
6848
+ expect (secondPos.dy, lessThan (thirdPos.dy));
6849
+
6850
+ // Double tap on the 'n' in 'until' to select the word.
6851
+ final Offset untilPos = textOffsetToPosition (tester, testValue.indexOf ('until' )+ 1 );
6852
+ await tester.tapAt (untilPos);
6853
+ await tester.pump (const Duration (milliseconds: 50 ));
6854
+ await tester.tapAt (untilPos);
6855
+ await tester.pumpAndSettle ();
6856
+
6857
+ // Skip past the frame where the opacity is zero.
6858
+ await tester.pump (const Duration (milliseconds: 200 ));
6859
+
6860
+ expect (controller.selection.baseOffset, 39 );
6861
+ expect (controller.selection.extentOffset, 44 );
6862
+
6863
+ final RenderEditable renderEditable = findRenderEditable (tester);
6864
+ final List <TextSelectionPoint > endpoints = globalize (
6865
+ renderEditable.getEndpointsForSelection (controller.selection),
6866
+ renderEditable,
6867
+ );
6868
+ expect (endpoints.length, 2 );
6869
+
6870
+ final Offset offsetFromEndPointToMiddlePoint = Offset (0.0 , - renderEditable.preferredLineHeight / 2 );
6871
+
6872
+ // Drag the left handle to just after 'Second', still on the second line.
6873
+ Offset handlePos = endpoints[0 ].point + offsetFromEndPointToMiddlePoint;
6874
+ Offset newHandlePos = textOffsetToPosition (tester, testValue.indexOf ('Second' ) + 6 ) + offsetFromEndPointToMiddlePoint;
6875
+ TestGesture gesture = await tester.startGesture (handlePos, pointer: 7 );
6876
+ await tester.pump ();
6877
+ await gesture.moveTo (newHandlePos);
6878
+ await tester.pump ();
6879
+ await gesture.up ();
6880
+ await tester.pump ();
6881
+
6882
+ expect (controller.selection.baseOffset, 28 );
6883
+ expect (controller.selection.extentOffset, 44 );
6884
+
6885
+ // Drag the right handle to just after 'goes', still on the second line.
6886
+ handlePos = endpoints[1 ].point + offsetFromEndPointToMiddlePoint;
6887
+ newHandlePos = textOffsetToPosition (tester, testValue.indexOf ('goes' ) + 4 ) + offsetFromEndPointToMiddlePoint;
6888
+ gesture = await tester.startGesture (handlePos, pointer: 7 );
6889
+ await tester.pump ();
6890
+ await gesture.moveTo (newHandlePos);
6891
+ await tester.pump ();
6892
+ await gesture.up ();
6893
+ await tester.pump ();
6894
+
6895
+ expect (controller.selection.baseOffset, 28 );
6896
+ expect (controller.selection.extentOffset, 38 );
6897
+
6898
+ if (! isContextMenuProvidedByPlatform) {
6899
+ await tester.tap (find.text ('Cut' ));
6900
+ await tester.pump ();
6901
+ expect (controller.selection.isCollapsed, true );
6902
+ expect (controller.text, cutValue);
6903
+ }
6904
+ });
6808
6905
}
0 commit comments