@@ -205,18 +205,18 @@ class TextEditingElement {
205205
206206 /// Timer that times when to set the location of the input text.
207207 ///
208- /// This is only used for IOS . In IOS , virtual keyboard shifts the screen.
208+ /// This is only used for iOS . In iOS , virtual keyboard shifts the screen.
209209 /// There is no callback to know if the keyboard is up and how much the screen
210210 /// has shifted. Therefore instead of listening to the shift and passing this
211211 /// information to Flutter Framework, we are trying to stop the shift.
212212 ///
213- /// In IOS , the virtual keyboard shifts the screen up if the focused input
213+ /// In iOS , the virtual keyboard shifts the screen up if the focused input
214214 /// element is under the keyboard or very close to the keyboard. Before the
215215 /// focus is called we are positioning it offscreen. The location of the input
216- /// in IOS is set to correct place, 100ms after focus. We use this timer for
216+ /// in iOS is set to correct place, 100ms after focus. We use this timer for
217217 /// timing this delay.
218218 Timer _positionInputElementTimer;
219- static const Duration _delayBeforePositining =
219+ static const Duration _delayBeforePositioning =
220220 const Duration (milliseconds: 100 );
221221
222222 final HybridTextEditing owner;
@@ -247,7 +247,7 @@ class TextEditingElement {
247247 void configureInputElementForIOS () {
248248 if (browserEngine != BrowserEngine .webkit ||
249249 operatingSystem != OperatingSystem .iOs) {
250- // Only relevant on Safari Mobile and Chrome on IOS .
250+ // Only relevant on Safari-based on iOS .
251251 return ;
252252 }
253253
@@ -293,30 +293,8 @@ class TextEditingElement {
293293 }
294294
295295 if (owner.doesKeyboardShiftInput) {
296- /// Position the element outside of the page before focusing on it.
297- ///
298- /// See [_positionInputElementTimer] .
299- owner.setStyleOutsideOfScreen (domElement);
300-
301- _subscriptions.add (domElement.onFocus.listen ((_) {
302- // Cancel previous timer if exists.
303- _positionInputElementTimer? .cancel ();
304- _positionInputElementTimer = Timer (_delayBeforePositining, () {
305- if (textEditing.inputElementNeedsToBePositioned) {
306- configureInputElementForIOS ();
307- }
308- });
309-
310- /// When the virtual keyboard is closed on IOS, onBlur is triggered.
311- _subscriptions.add (domElement.onBlur.listen ((_) {
312- /// Cancel the timer since there is no need to set the location of the
313- /// input element anymore. It needs to be focused again to be editable
314- /// by the user.
315- _positionInputElementTimer? .cancel ();
316- }));
317- }));
296+ _preventShiftDuringFocus ();
318297 }
319-
320298 domElement.focus ();
321299
322300 if (_lastEditingState != null ) {
@@ -343,6 +321,7 @@ class TextEditingElement {
343321 }
344322 _subscriptions.clear ();
345323 _positionInputElementTimer? .cancel ();
324+ _positionInputElementTimer = null ;
346325 owner.inputPositioned = false ;
347326 _removeDomElement ();
348327 }
@@ -373,6 +352,32 @@ class TextEditingElement {
373352 domElement.focus ();
374353 }
375354
355+ void _preventShiftDuringFocus () {
356+ // Position the element outside of the page before focusing on it.
357+ //
358+ // See [_positionInputElementTimer].
359+ owner.setStyleOutsideOfScreen (domElement);
360+
361+ _subscriptions.add (domElement.onFocus.listen ((_) {
362+ // Cancel previous timer if exists.
363+ _positionInputElementTimer? .cancel ();
364+ _positionInputElementTimer = Timer (_delayBeforePositioning, () {
365+ if (textEditing.inputElementNeedsToBePositioned) {
366+ configureInputElementForIOS ();
367+ }
368+ });
369+
370+ // When the virtual keyboard is closed on iOS, onBlur is triggered.
371+ _subscriptions.add (domElement.onBlur.listen ((_) {
372+ // Cancel the timer since there is no need to set the location of the
373+ // input element anymore. It needs to be focused again to be editable
374+ // by the user.
375+ _positionInputElementTimer? .cancel ();
376+ _positionInputElementTimer = null ;
377+ }));
378+ }));
379+ }
380+
376381 void setEditingState (EditingState editingState) {
377382 _lastEditingState = editingState;
378383 if (! _enabled || ! editingState.isValid) {
@@ -406,6 +411,14 @@ class TextEditingElement {
406411 ..addRange (_createRange (editingState));
407412 break ;
408413 }
414+
415+
416+ if (owner.inputElementNeedsToBePositioned) {
417+ _preventShiftDuringFocus ();
418+ }
419+
420+ // Re-focuses when setting editing state.
421+ domElement.focus ();
409422 }
410423
411424 /// Swap out the current DOM element and replace it with a new one of type
@@ -624,9 +637,9 @@ class HybridTextEditing {
624637 /// Also used to define if a keyboard is needed.
625638 bool _isEditing = false ;
626639
627- /// Flag indicating the input element needs to be positioned.
640+ /// Indicates whether the input element needs to be positioned.
628641 ///
629- /// See [TextEditingElement._delayBeforePositining ] .
642+ /// See [TextEditingElement._delayBeforePositioning ] .
630643 bool get inputElementNeedsToBePositioned =>
631644 ! inputPositioned &&
632645 _isEditing &&
@@ -765,14 +778,14 @@ class HybridTextEditing {
765778 /// to be shifted by a virtual keyboard or if the input is already positioned.
766779 ///
767780 /// Otherwise positioning will be done after focusing on the input.
768- /// See [TextEditingElement._delayBeforePositining ] .
781+ /// See [TextEditingElement._delayBeforePositioning ] .
769782 bool get _canPositionInput => inputPositioned || ! doesKeyboardShiftInput;
770783
771- /// Flag indicating if virtual keyboard shifts the location of input element.
784+ /// Indicates whether virtual keyboard shifts the location of input element.
772785 ///
773786 /// Value decided using the operating system and the browser engine.
774787 ///
775- /// In IOS , the virtual keyboard might shifts the screen up to make input
788+ /// In iOS , the virtual keyboard might shifts the screen up to make input
776789 /// visible depending on the location of the focused input element.
777790 bool get doesKeyboardShiftInput =>
778791 browserEngine == BrowserEngine .webkit &&
@@ -807,15 +820,15 @@ class HybridTextEditing {
807820 ..transform = transformCss;
808821 }
809822
810- // TODO(flutter_web): When the browser closes and re-opens the virtual
811- // shifts the page in IOS . Call this method from visibility change listener
823+ // TODO(flutter_web): After the browser closes and re-opens the virtual
824+ // shifts the page in iOS . Call this method from visibility change listener
812825 // attached to body.
813- /// Set the dom elements location somewhere outside of the screen.
826+ /// Set the dom element's location somewhere outside of the screen.
814827 ///
815- /// This is useful for not triggering a scroll when IOS virtual keyboard is
828+ /// This is useful for not triggering a scroll when iOS virtual keyboard is
816829 /// coming up.
817830 ///
818- /// See [TextEditingElement._delayBeforePositining ] .
831+ /// See [TextEditingElement._delayBeforePositioning ] .
819832 void setStyleOutsideOfScreen (html.HtmlElement domElement) {
820833 domElement.style.transform = 'translate(-9999px, -9999px)' ;
821834 }
0 commit comments