diff --git a/packages/flutter/lib/src/rendering/editable.dart b/packages/flutter/lib/src/rendering/editable.dart index 6ad811c185..1fae8aaee1 100644 --- a/packages/flutter/lib/src/rendering/editable.dart +++ b/packages/flutter/lib/src/rendering/editable.dart @@ -1639,6 +1639,8 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin { _offset.addListener(markNeedsPaint); _showHideCursor(); _showCursor.addListener(_showHideCursor); + if (_listenerAttached) + RawKeyboard.instance.addListener(_handleKeyEvent); } @override diff --git a/packages/flutter/test/rendering/editable_test.dart b/packages/flutter/test/rendering/editable_test.dart index 616c8ed222..812410fbcc 100644 --- a/packages/flutter/test/rendering/editable_test.dart +++ b/packages/flutter/test/rendering/editable_test.dart @@ -955,6 +955,67 @@ void main() { expect(delegate.textEditingValue.text, ''); }, skip: isBrowser); // https://github.com/flutter/flutter/issues/61021 + test('arrow keys work after detaching the widget and attaching it again', () async { + final TextSelectionDelegate delegate = FakeEditableTextState() + ..textEditingValue = const TextEditingValue( + text: 'W Szczebrzeszynie chrząszcz brzmi w trzcinie', + selection: TextSelection.collapsed(offset: 0), + ); + final ViewportOffset viewportOffset = ViewportOffset.zero(); + final RenderEditable editable = RenderEditable( + backgroundCursorColor: Colors.grey, + selectionColor: Colors.black, + textDirection: TextDirection.ltr, + cursorColor: Colors.red, + offset: viewportOffset, + textSelectionDelegate: delegate, + onSelectionChanged: (TextSelection selection, RenderEditable renderObject, SelectionChangedCause cause) { + renderObject.selection = selection; + }, + startHandleLayerLink: LayerLink(), + endHandleLayerLink: LayerLink(), + text: const TextSpan( + text: 'W Szczebrzeszynie chrząszcz brzmi w trzcinie', + style: TextStyle( + height: 1.0, fontSize: 10.0, fontFamily: 'Ahem', + ), + ), + selection: const TextSelection.collapsed( + offset: 0, + ), + ); + + final PipelineOwner pipelineOwner = PipelineOwner(); + editable.attach(pipelineOwner); + editable.hasFocus = true; + editable.detach(); + layout(editable); + editable.hasFocus = true; + editable.selectPositionAt(from: Offset.zero, cause: SelectionChangedCause.tap); + editable.selection = const TextSelection.collapsed(offset: 0); + pumpFrame(); + + await simulateKeyDownEvent(LogicalKeyboardKey.arrowRight, platform: 'android'); + await simulateKeyUpEvent(LogicalKeyboardKey.arrowRight, platform: 'android'); + await simulateKeyDownEvent(LogicalKeyboardKey.arrowRight, platform: 'android'); + await simulateKeyUpEvent(LogicalKeyboardKey.arrowRight, platform: 'android'); + await simulateKeyDownEvent(LogicalKeyboardKey.arrowRight, platform: 'android'); + await simulateKeyUpEvent(LogicalKeyboardKey.arrowRight, platform: 'android'); + await simulateKeyDownEvent(LogicalKeyboardKey.arrowRight, platform: 'android'); + await simulateKeyUpEvent(LogicalKeyboardKey.arrowRight, platform: 'android'); + expect(editable.selection?.isCollapsed, true); + expect(editable.selection?.baseOffset, 4); + + await simulateKeyDownEvent(LogicalKeyboardKey.arrowLeft, platform: 'android'); + await simulateKeyUpEvent(LogicalKeyboardKey.arrowLeft, platform: 'android'); + expect(editable.selection?.isCollapsed, true); + expect(editable.selection?.baseOffset, 3); + + await simulateKeyDownEvent(LogicalKeyboardKey.delete, platform: 'android'); + await simulateKeyUpEvent(LogicalKeyboardKey.delete, platform: 'android'); + expect(delegate.textEditingValue.text, 'W Sczebrzeszynie chrząszcz brzmi w trzcinie'); + }, skip: isBrowser); // https://github.com/flutter/flutter/issues/61021 + test('arrow keys with selection text', () async { final TextSelectionDelegate delegate = FakeEditableTextState(); final ViewportOffset viewportOffset = ViewportOffset.zero();