Don't crash when TextField w/ explicit controller is activated via a11y (#17892)
Fixes #17801.
This commit is contained in:
parent
c4d6311a29
commit
1361071a21
@ -506,8 +506,8 @@ class _TextFieldState extends State<TextField> with AutomaticKeepAliveClientMixi
|
|||||||
|
|
||||||
return new Semantics(
|
return new Semantics(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
if (!_controller.selection.isValid)
|
if (!_effectiveController.selection.isValid)
|
||||||
_controller.selection = new TextSelection.collapsed(offset: _controller.text.length);
|
_effectiveController.selection = new TextSelection.collapsed(offset: _effectiveController.text.length);
|
||||||
_requestKeyboard();
|
_requestKeyboard();
|
||||||
},
|
},
|
||||||
child: new IgnorePointer(
|
child: new IgnorePointer(
|
||||||
|
@ -2059,6 +2059,76 @@ void main() {
|
|||||||
semantics.dispose();
|
semantics.dispose();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
testWidgets('Can activate TextField with explicit controller via semantics ', (WidgetTester tester) async {
|
||||||
|
// Regression test for https://github.com/flutter/flutter/issues/17801
|
||||||
|
|
||||||
|
const String textInTextField = 'Hello';
|
||||||
|
|
||||||
|
final SemanticsTester semantics = new SemanticsTester(tester);
|
||||||
|
final SemanticsOwner semanticsOwner = tester.binding.pipelineOwner.semanticsOwner;
|
||||||
|
final TextEditingController controller = new TextEditingController()
|
||||||
|
..text = textInTextField;
|
||||||
|
final Key key = new UniqueKey();
|
||||||
|
|
||||||
|
await tester.pumpWidget(
|
||||||
|
overlay(
|
||||||
|
child: new TextField(
|
||||||
|
key: key,
|
||||||
|
controller: controller,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
const int inputFieldId = 1;
|
||||||
|
|
||||||
|
expect(semantics, hasSemantics(
|
||||||
|
new TestSemantics.root(
|
||||||
|
children: <TestSemantics>[
|
||||||
|
new TestSemantics(
|
||||||
|
id: inputFieldId,
|
||||||
|
flags: <SemanticsFlag>[SemanticsFlag.isTextField],
|
||||||
|
actions: <SemanticsAction>[SemanticsAction.tap],
|
||||||
|
value: textInTextField,
|
||||||
|
textDirection: TextDirection.ltr,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
ignoreRect: true, ignoreTransform: true,
|
||||||
|
));
|
||||||
|
|
||||||
|
semanticsOwner.performAction(inputFieldId, SemanticsAction.tap);
|
||||||
|
await tester.pump();
|
||||||
|
|
||||||
|
expect(semantics, hasSemantics(
|
||||||
|
new TestSemantics.root(
|
||||||
|
children: <TestSemantics>[
|
||||||
|
new TestSemantics(
|
||||||
|
id: inputFieldId,
|
||||||
|
flags: <SemanticsFlag>[
|
||||||
|
SemanticsFlag.isTextField,
|
||||||
|
SemanticsFlag.isFocused,
|
||||||
|
],
|
||||||
|
actions: <SemanticsAction>[
|
||||||
|
SemanticsAction.tap,
|
||||||
|
SemanticsAction.moveCursorBackwardByCharacter,
|
||||||
|
SemanticsAction.setSelection,
|
||||||
|
SemanticsAction.paste,
|
||||||
|
],
|
||||||
|
value: textInTextField,
|
||||||
|
textDirection: TextDirection.ltr,
|
||||||
|
textSelection: const TextSelection(
|
||||||
|
baseOffset: textInTextField.length,
|
||||||
|
extentOffset: textInTextField.length,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
ignoreRect: true, ignoreTransform: true,
|
||||||
|
));
|
||||||
|
|
||||||
|
semantics.dispose();
|
||||||
|
});
|
||||||
|
|
||||||
testWidgets('TextField throws when not descended from a Material widget', (WidgetTester tester) async {
|
testWidgets('TextField throws when not descended from a Material widget', (WidgetTester tester) async {
|
||||||
const Widget textField = const TextField();
|
const Widget textField = const TextField();
|
||||||
await tester.pumpWidget(textField);
|
await tester.pumpWidget(textField);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user