mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
Do not crash when remove SelectableText during handle drag (#108369)
This commit is contained in:
parent
16c25caa44
commit
09b6672e77
@ -444,6 +444,9 @@ class TextSelectionOverlay {
|
||||
late Offset _dragEndPosition;
|
||||
|
||||
void _handleSelectionEndHandleDragStart(DragStartDetails details) {
|
||||
if (!renderObject.attached) {
|
||||
return;
|
||||
}
|
||||
final Size handleSize = selectionControls!.getHandleSize(
|
||||
renderObject.preferredLineHeight,
|
||||
);
|
||||
@ -451,6 +454,9 @@ class TextSelectionOverlay {
|
||||
}
|
||||
|
||||
void _handleSelectionEndHandleDragUpdate(DragUpdateDetails details) {
|
||||
if (!renderObject.attached) {
|
||||
return;
|
||||
}
|
||||
_dragEndPosition += details.delta;
|
||||
final TextPosition position = renderObject.getPositionForPoint(_dragEndPosition);
|
||||
|
||||
@ -492,6 +498,9 @@ class TextSelectionOverlay {
|
||||
late Offset _dragStartPosition;
|
||||
|
||||
void _handleSelectionStartHandleDragStart(DragStartDetails details) {
|
||||
if (!renderObject.attached) {
|
||||
return;
|
||||
}
|
||||
final Size handleSize = selectionControls!.getHandleSize(
|
||||
renderObject.preferredLineHeight,
|
||||
);
|
||||
@ -499,6 +508,9 @@ class TextSelectionOverlay {
|
||||
}
|
||||
|
||||
void _handleSelectionStartHandleDragUpdate(DragUpdateDetails details) {
|
||||
if (!renderObject.attached) {
|
||||
return;
|
||||
}
|
||||
_dragStartPosition += details.delta;
|
||||
final TextPosition position = renderObject.getPositionForPoint(_dragStartPosition);
|
||||
|
||||
|
@ -176,6 +176,74 @@ void main() {
|
||||
);
|
||||
}
|
||||
|
||||
testWidgets('Do not crash when remove SelectableText during handle drag', (WidgetTester tester) async {
|
||||
// Regression test https://github.com/flutter/flutter/issues/108242
|
||||
bool isShow = true;
|
||||
late StateSetter setter;
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
home: Material(
|
||||
child: StatefulBuilder(
|
||||
builder: (BuildContext context, StateSetter setState) {
|
||||
setter = setState;
|
||||
if (isShow) {
|
||||
return const SelectableText(
|
||||
'abc def ghi',
|
||||
dragStartBehavior: DragStartBehavior.down,
|
||||
);
|
||||
} else {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
final EditableText editableTextWidget = tester.widget(find.byType(EditableText));
|
||||
final TextEditingController controller = editableTextWidget.controller;
|
||||
|
||||
// Long press the 'e' to select 'def'.
|
||||
final Offset ePos = textOffsetToPosition(tester, 5);
|
||||
TestGesture gesture = await tester.startGesture(ePos, pointer: 7);
|
||||
await tester.pump(const Duration(seconds: 2));
|
||||
await gesture.up();
|
||||
await tester.pump();
|
||||
await tester.pump(const Duration(milliseconds: 200)); // skip past the frame where the opacity is zero
|
||||
|
||||
final TextSelection selection = controller.selection;
|
||||
expect(selection.baseOffset, 4);
|
||||
expect(selection.extentOffset, 7);
|
||||
|
||||
final RenderEditable renderEditable = findRenderEditable(tester);
|
||||
final List<TextSelectionPoint> endpoints = globalize(
|
||||
renderEditable.getEndpointsForSelection(selection),
|
||||
renderEditable,
|
||||
);
|
||||
expect(endpoints.length, 2);
|
||||
|
||||
// Drag the left handle to the left.
|
||||
final Offset handlePos = endpoints[0].point + const Offset(-1.0, 1.0);
|
||||
final Offset newHandlePos = textOffsetToPosition(tester, 1);
|
||||
final Offset newHandlePos1 = textOffsetToPosition(tester, 0);
|
||||
gesture = await tester.startGesture(handlePos, pointer: 7);
|
||||
await tester.pump();
|
||||
await gesture.moveTo(newHandlePos);
|
||||
await tester.pump();
|
||||
|
||||
// Unmount the SelectableText during handle drag
|
||||
setter(() {
|
||||
isShow = false;
|
||||
});
|
||||
await tester.pump();
|
||||
|
||||
await gesture.moveTo(newHandlePos1);
|
||||
await tester.pump(); // Do not crash here
|
||||
|
||||
await gesture.up();
|
||||
await tester.pump();
|
||||
});
|
||||
|
||||
testWidgets('has expected defaults', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
boilerplate(
|
||||
|
Loading…
Reference in New Issue
Block a user