diff --git a/lib/src/widgets/editor.dart b/lib/src/widgets/editor.dart index bc7c9071..61ab6cfc 100644 --- a/lib/src/widgets/editor.dart +++ b/lib/src/widgets/editor.dart @@ -721,6 +721,7 @@ class RenderEditor extends RenderEditableContainerBox required TextDirection textDirection, required bool hasFocus, required this.selection, + required this.scrollable, required LayerLink startHandleLayerLink, required LayerLink endHandleLayerLink, required EdgeInsetsGeometry padding, @@ -750,6 +751,7 @@ class RenderEditor extends RenderEditableContainerBox final CursorCont _cursorController; final bool floatingCursorDisabled; + final bool scrollable; Document document; TextSelection selection; @@ -1125,17 +1127,18 @@ class RenderEditor extends RenderEditableContainerBox @override void performLayout() { assert(() { - if (!constraints.hasBoundedHeight) return true; + if (!scrollable || !constraints.hasBoundedHeight) return true; throw FlutterError.fromParts([ ErrorSummary('RenderEditableContainerBox must have ' - 'unlimited space along its main axis.'), + 'unlimited space along its main axis when it is scrollable.'), ErrorDescription('RenderEditableContainerBox does not clip or' ' resize its children, so it must be ' 'placed in a parent that does not constrain the main ' 'axis.'), ErrorHint( 'You probably want to put the RenderEditableContainerBox inside a ' - 'RenderViewport with a matching main axis.') + 'RenderViewport with a matching main axis or disable the ' + 'scrollable property.') ]); }()); assert(() { diff --git a/lib/src/widgets/raw_editor.dart b/lib/src/widgets/raw_editor.dart index 5ce4f400..22833768 100644 --- a/lib/src/widgets/raw_editor.dart +++ b/lib/src/widgets/raw_editor.dart @@ -295,6 +295,7 @@ class RawEditorState extends EditorState document: _doc, selection: widget.controller.selection, hasFocus: _hasFocus, + scrollable: widget.scrollable, cursorController: _cursorCont, textDirection: _textDirection, startHandleLayerLink: _startHandleLayerLink, @@ -333,6 +334,7 @@ class RawEditorState extends EditorState document: _doc, selection: widget.controller.selection, hasFocus: _hasFocus, + scrollable: widget.scrollable, textDirection: _textDirection, startHandleLayerLink: _startHandleLayerLink, endHandleLayerLink: _endHandleLayerLink, @@ -934,6 +936,7 @@ class _Editor extends MultiChildRenderObjectWidget { required this.document, required this.textDirection, required this.hasFocus, + required this.scrollable, required this.selection, required this.startHandleLayerLink, required this.endHandleLayerLink, @@ -951,6 +954,7 @@ class _Editor extends MultiChildRenderObjectWidget { final Document document; final TextDirection textDirection; final bool hasFocus; + final bool scrollable; final TextSelection selection; final LayerLink startHandleLayerLink; final LayerLink endHandleLayerLink; @@ -969,6 +973,7 @@ class _Editor extends MultiChildRenderObjectWidget { document: document, textDirection: textDirection, hasFocus: hasFocus, + scrollable: scrollable, selection: selection, startHandleLayerLink: startHandleLayerLink, endHandleLayerLink: endHandleLayerLink, diff --git a/lib/src/widgets/raw_editor/raw_editor_state_selection_delegate_mixin.dart b/lib/src/widgets/raw_editor/raw_editor_state_selection_delegate_mixin.dart index c5fe8317..0b4904ff 100644 --- a/lib/src/widgets/raw_editor/raw_editor_state_selection_delegate_mixin.dart +++ b/lib/src/widgets/raw_editor/raw_editor_state_selection_delegate_mixin.dart @@ -63,7 +63,9 @@ mixin RawEditorStateSelectionDelegateMixin on EditorState final localRect = renderEditor.getLocalRectForCaret(position); final targetOffset = _getOffsetToRevealCaret(localRect, position); - scrollController.jumpTo(targetOffset.offset); + if (scrollController.hasClients) { + scrollController.jumpTo(targetOffset.offset); + } renderEditor.showOnScreen(rect: targetOffset.rect); } @@ -77,7 +79,9 @@ mixin RawEditorStateSelectionDelegateMixin on EditorState // `renderEditable.preferredLineHeight`, before the target scroll offset is // calculated. RevealedOffset _getOffsetToRevealCaret(Rect rect, TextPosition position) { - if (!scrollController.position.allowImplicitScrolling) { + // Make sure scrollController is attached + if (scrollController.hasClients && + !scrollController.position.allowImplicitScrolling) { return RevealedOffset(offset: scrollController.offset, rect: rect); } @@ -102,12 +106,17 @@ mixin RawEditorStateSelectionDelegateMixin on EditorState // No overscrolling when encountering tall fonts/scripts that extend past // the ascent. - final targetOffset = (additionalOffset + scrollController.offset).clamp( - scrollController.position.minScrollExtent, - scrollController.position.maxScrollExtent, - ); + var targetOffset = additionalOffset; + if (scrollController.hasClients) { + targetOffset = (additionalOffset + scrollController.offset).clamp( + scrollController.position.minScrollExtent, + scrollController.position.maxScrollExtent, + ); + } - final offsetDelta = scrollController.offset - targetOffset; + final offsetDelta = + (scrollController.hasClients ? scrollController.offset : 0) - + targetOffset; return RevealedOffset( rect: rect.shift(unitOffset * offsetDelta), offset: targetOffset); }