@@ -33,6 +33,7 @@ import 'media_query.dart';
3333import 'scroll_configuration.dart' ;
3434import 'scroll_controller.dart' ;
3535import 'scroll_physics.dart' ;
36+ import 'scroll_position.dart' ;
3637import 'scrollable.dart' ;
3738import 'shortcuts.dart' ;
3839import 'spell_check.dart' ;
@@ -1907,6 +1908,7 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
19071908
19081909 TextSelectionOverlay ? _selectionOverlay;
19091910
1911+ final GlobalKey _scrollableKey = GlobalKey ();
19101912 ScrollController ? _internalScrollController;
19111913 ScrollController get _scrollController => widget.scrollController ?? (_internalScrollController ?? = ScrollController ());
19121914
@@ -3953,6 +3955,96 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
39533955 }
39543956 }
39553957
3958+ /// Handles [ScrollIntent] by scrolling the [Scrollable] inside of
3959+ /// [EditableText] .
3960+ void _scroll (ScrollIntent intent) {
3961+ if (intent.type != ScrollIncrementType .page) {
3962+ return ;
3963+ }
3964+
3965+ final ScrollPosition position = _scrollController.position;
3966+ if (widget.maxLines == 1 ) {
3967+ _scrollController.jumpTo (position.maxScrollExtent);
3968+ return ;
3969+ }
3970+
3971+ // If the field isn't scrollable, do nothing. For example, when the lines of
3972+ // text is less than maxLines, the field has nothing to scroll.
3973+ if (position.maxScrollExtent == 0.0 && position.minScrollExtent == 0.0 ) {
3974+ return ;
3975+ }
3976+
3977+ final ScrollableState ? state = _scrollableKey.currentState as ScrollableState ? ;
3978+ final double increment = ScrollAction .getDirectionalIncrement (state! , intent);
3979+ final double destination = clampDouble (
3980+ position.pixels + increment,
3981+ position.minScrollExtent,
3982+ position.maxScrollExtent,
3983+ );
3984+ if (destination == position.pixels) {
3985+ return ;
3986+ }
3987+ _scrollController.jumpTo (destination);
3988+ }
3989+
3990+ /// Extend the selection down by page if the `forward` parameter is true, or
3991+ /// up by page otherwise.
3992+ void _extendSelectionByPage (ExtendSelectionByPageIntent intent) {
3993+ if (widget.maxLines == 1 ) {
3994+ return ;
3995+ }
3996+
3997+ final TextSelection nextSelection;
3998+ final Rect extentRect = renderEditable.getLocalRectForCaret (
3999+ _value.selection.extent,
4000+ );
4001+ final ScrollableState ? state = _scrollableKey.currentState as ScrollableState ? ;
4002+ final double increment = ScrollAction .getDirectionalIncrement (
4003+ state! ,
4004+ ScrollIntent (
4005+ direction: intent.forward ? AxisDirection .down : AxisDirection .up,
4006+ type: ScrollIncrementType .page,
4007+ ),
4008+ );
4009+ final ScrollPosition position = _scrollController.position;
4010+ if (intent.forward) {
4011+ if (_value.selection.extentOffset >= _value.text.length) {
4012+ return ;
4013+ }
4014+ final Offset nextExtentOffset =
4015+ Offset (extentRect.left, extentRect.top + increment);
4016+ final double height = position.maxScrollExtent + renderEditable.size.height;
4017+ final TextPosition nextExtent = nextExtentOffset.dy + position.pixels >= height
4018+ ? TextPosition (offset: _value.text.length)
4019+ : renderEditable.getPositionForPoint (
4020+ renderEditable.localToGlobal (nextExtentOffset),
4021+ );
4022+ nextSelection = _value.selection.copyWith (
4023+ extentOffset: nextExtent.offset,
4024+ );
4025+ } else {
4026+ if (_value.selection.extentOffset <= 0 ) {
4027+ return ;
4028+ }
4029+ final Offset nextExtentOffset =
4030+ Offset (extentRect.left, extentRect.top + increment);
4031+ final TextPosition nextExtent = nextExtentOffset.dy + position.pixels <= 0
4032+ ? const TextPosition (offset: 0 )
4033+ : renderEditable.getPositionForPoint (
4034+ renderEditable.localToGlobal (nextExtentOffset),
4035+ );
4036+ nextSelection = _value.selection.copyWith (
4037+ extentOffset: nextExtent.offset,
4038+ );
4039+ }
4040+
4041+ bringIntoView (nextSelection.extent);
4042+ userUpdateTextEditingValue (
4043+ _value.copyWith (selection: nextSelection),
4044+ SelectionChangedCause .keyboard,
4045+ );
4046+ }
4047+
39564048 void _updateSelection (UpdateSelectionIntent intent) {
39574049 bringIntoView (intent.newSelection.extent);
39584050 userUpdateTextEditingValue (
@@ -4058,6 +4150,7 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
40584150
40594151 // Extend/Move Selection
40604152 ExtendSelectionByCharacterIntent : _makeOverridable (_UpdateTextSelectionAction <ExtendSelectionByCharacterIntent >(this , false , _characterBoundary)),
4153+ ExtendSelectionByPageIntent : _makeOverridable (CallbackAction <ExtendSelectionByPageIntent >(onInvoke: _extendSelectionByPage)),
40614154 ExtendSelectionToNextWordBoundaryIntent : _makeOverridable (_UpdateTextSelectionAction <ExtendSelectionToNextWordBoundaryIntent >(this , true , _nextWordBoundary)),
40624155 ExtendSelectionToLineBreakIntent : _makeOverridable (_UpdateTextSelectionAction <ExtendSelectionToLineBreakIntent >(this , true , _linebreak)),
40634156 ExpandSelectionToLineBreakIntent : _makeOverridable (CallbackAction <ExpandSelectionToLineBreakIntent >(onInvoke: _expandSelectionToLinebreak)),
@@ -4067,6 +4160,7 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
40674160 ExtendSelectionToDocumentBoundaryIntent : _makeOverridable (_UpdateTextSelectionAction <ExtendSelectionToDocumentBoundaryIntent >(this , true , _documentBoundary)),
40684161 ExtendSelectionToNextWordBoundaryOrCaretLocationIntent : _makeOverridable (_ExtendSelectionOrCaretPositionAction (this , _nextWordBoundary)),
40694162 ScrollToDocumentBoundaryIntent : _makeOverridable (CallbackAction <ScrollToDocumentBoundaryIntent >(onInvoke: _scrollToDocumentBoundary)),
4163+ ScrollIntent : CallbackAction <ScrollIntent >(onInvoke: _scroll),
40704164
40714165 // Copy Paste
40724166 SelectAllTextIntent : _makeOverridable (_SelectAllAction (this )),
@@ -4099,6 +4193,7 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
40994193 includeSemantics: false ,
41004194 debugLabel: kReleaseMode ? null : 'EditableText' ,
41014195 child: Scrollable (
4196+ key: _scrollableKey,
41024197 excludeFromSemantics: true ,
41034198 axisDirection: _isMultiline ? AxisDirection .down : AxisDirection .right,
41044199 controller: _scrollController,
0 commit comments