Handle the case of no selection rects (#117419)
Fixes an error that can occur when selection contains a partial glyph.
This commit is contained in:
parent
8ff1b6eb5e
commit
2931e50c30
@ -3266,8 +3266,15 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
|
|||||||
rectToReveal = targetOffset.rect;
|
rectToReveal = targetOffset.rect;
|
||||||
} else {
|
} else {
|
||||||
final List<Rect> selectionBoxes = renderEditable.getBoxesForSelection(selection);
|
final List<Rect> selectionBoxes = renderEditable.getBoxesForSelection(selection);
|
||||||
rectToReveal = selection.baseOffset < selection.extentOffset ?
|
// selectionBoxes may be empty if, for example, the selection does not
|
||||||
selectionBoxes.last : selectionBoxes.first;
|
// encompass a full character, like if it only contained part of an
|
||||||
|
// extended grapheme cluster.
|
||||||
|
if (selectionBoxes.isEmpty) {
|
||||||
|
rectToReveal = targetOffset.rect;
|
||||||
|
} else {
|
||||||
|
rectToReveal = selection.baseOffset < selection.extentOffset ?
|
||||||
|
selectionBoxes.last : selectionBoxes.first;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (withAnimation) {
|
if (withAnimation) {
|
||||||
|
@ -14354,6 +14354,50 @@ testWidgets('Floating cursor ending with selection', (WidgetTester tester) async
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Regression test for: https://github.com/flutter/flutter/issues/117418.
|
||||||
|
testWidgets('can handle the partial selection of a multi-code-unit glyph', (WidgetTester tester) async {
|
||||||
|
await tester.pumpWidget(
|
||||||
|
MaterialApp(
|
||||||
|
home: EditableText(
|
||||||
|
controller: controller,
|
||||||
|
showSelectionHandles: true,
|
||||||
|
autofocus: true,
|
||||||
|
focusNode: FocusNode(),
|
||||||
|
style: Typography.material2018().black.titleMedium!,
|
||||||
|
cursorColor: Colors.blue,
|
||||||
|
backgroundCursorColor: Colors.grey,
|
||||||
|
selectionControls: materialTextSelectionControls,
|
||||||
|
keyboardType: TextInputType.text,
|
||||||
|
textAlign: TextAlign.right,
|
||||||
|
minLines: 2,
|
||||||
|
maxLines: 2,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
await tester.enterText(find.byType(EditableText), '12345');
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
|
final EditableTextState state =
|
||||||
|
tester.state<EditableTextState>(find.byType(EditableText));
|
||||||
|
state.userUpdateTextEditingValue(
|
||||||
|
const TextEditingValue(
|
||||||
|
// This is an extended grapheme cluster made up of several code units,
|
||||||
|
// which has length 8. A selection from 0-1 does not fully select it.
|
||||||
|
text: '👨👩👦',
|
||||||
|
selection: TextSelection(
|
||||||
|
baseOffset: 0,
|
||||||
|
extentOffset: 1,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SelectionChangedCause.keyboard,
|
||||||
|
);
|
||||||
|
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
|
expect(tester.takeException(), null);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
class UnsettableController extends TextEditingController {
|
class UnsettableController extends TextEditingController {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user