Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
dbbaf68e
Unverified
Commit
dbbaf68e
authored
Mar 23, 2022
by
WenJingRui
Committed by
GitHub
Mar 23, 2022
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fix: fix the delay of showOnScreen animation when keyboard comes up. (#99546)
parent
f1d8e30c
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
91 additions
and
16 deletions
+91
-16
editable_text.dart
packages/flutter/lib/src/widgets/editable_text.dart
+24
-16
editable_text_test.dart
packages/flutter/test/widgets/editable_text_test.dart
+67
-0
No files found.
packages/flutter/lib/src/widgets/editable_text.dart
View file @
dbbaf68e
...
@@ -1965,7 +1965,7 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
...
@@ -1965,7 +1965,7 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
// to make sure the user can see the changes they just made. Programmatical
// to make sure the user can see the changes they just made. Programmatical
// changes to `textEditingValue` do not trigger the behavior even if the
// changes to `textEditingValue` do not trigger the behavior even if the
// text field is focused.
// text field is focused.
_scheduleShowCaretOnScreen
();
_scheduleShowCaretOnScreen
(
withAnimation:
true
);
if
(
_hasInputConnection
)
{
if
(
_hasInputConnection
)
{
// To keep the cursor from blinking while typing, we want to restart the
// To keep the cursor from blinking while typing, we want to restart the
// cursor timer every time a new character is typed.
// cursor timer every time a new character is typed.
...
@@ -2498,7 +2498,7 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
...
@@ -2498,7 +2498,7 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
bool
_showCaretOnScreenScheduled
=
false
;
bool
_showCaretOnScreenScheduled
=
false
;
void
_scheduleShowCaretOnScreen
()
{
void
_scheduleShowCaretOnScreen
(
{
required
bool
withAnimation
}
)
{
if
(
_showCaretOnScreenScheduled
)
{
if
(
_showCaretOnScreenScheduled
)
{
return
;
return
;
}
}
...
@@ -2538,17 +2538,23 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
...
@@ -2538,17 +2538,23 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
final
RevealedOffset
targetOffset
=
_getOffsetToRevealCaret
(
_currentCaretRect
!);
final
RevealedOffset
targetOffset
=
_getOffsetToRevealCaret
(
_currentCaretRect
!);
_scrollController
.
animateTo
(
if
(
withAnimation
)
{
targetOffset
.
offset
,
_scrollController
.
animateTo
(
duration:
_caretAnimationDuration
,
targetOffset
.
offset
,
curve:
_caretAnimationCurve
,
duration:
_caretAnimationDuration
,
);
curve:
_caretAnimationCurve
,
);
renderEditable
.
showOnScreen
(
renderEditable
.
showOnScreen
(
rect:
caretPadding
.
inflateRect
(
targetOffset
.
rect
),
rect:
caretPadding
.
inflateRect
(
targetOffset
.
rect
),
duration:
_caretAnimationDuration
,
duration:
_caretAnimationDuration
,
curve:
_caretAnimationCurve
,
curve:
_caretAnimationCurve
,
);
);
}
else
{
_scrollController
.
jumpTo
(
targetOffset
.
offset
);
renderEditable
.
showOnScreen
(
rect:
caretPadding
.
inflateRect
(
targetOffset
.
rect
),
);
}
});
});
}
}
...
@@ -2561,7 +2567,9 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
...
@@ -2561,7 +2567,9 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
_selectionOverlay
?.
updateForScroll
();
_selectionOverlay
?.
updateForScroll
();
});
});
if
(
_lastBottomViewInset
<
WidgetsBinding
.
instance
.
window
.
viewInsets
.
bottom
)
{
if
(
_lastBottomViewInset
<
WidgetsBinding
.
instance
.
window
.
viewInsets
.
bottom
)
{
_scheduleShowCaretOnScreen
();
// Because the metrics change signal from engine will come here every frame
// (on both iOS and Android). So we don't need to show caret with animation.
_scheduleShowCaretOnScreen
(
withAnimation:
false
);
}
}
}
}
_lastBottomViewInset
=
WidgetsBinding
.
instance
.
window
.
viewInsets
.
bottom
;
_lastBottomViewInset
=
WidgetsBinding
.
instance
.
window
.
viewInsets
.
bottom
;
...
@@ -2745,7 +2753,7 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
...
@@ -2745,7 +2753,7 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
WidgetsBinding
.
instance
.
addObserver
(
this
);
WidgetsBinding
.
instance
.
addObserver
(
this
);
_lastBottomViewInset
=
WidgetsBinding
.
instance
.
window
.
viewInsets
.
bottom
;
_lastBottomViewInset
=
WidgetsBinding
.
instance
.
window
.
viewInsets
.
bottom
;
if
(!
widget
.
readOnly
)
{
if
(!
widget
.
readOnly
)
{
_scheduleShowCaretOnScreen
();
_scheduleShowCaretOnScreen
(
withAnimation:
true
);
}
}
if
(!
_value
.
selection
.
isValid
)
{
if
(!
_value
.
selection
.
isValid
)
{
// Place cursor at the end if the selection is invalid when we receive focus.
// Place cursor at the end if the selection is invalid when we receive focus.
...
@@ -2900,7 +2908,7 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
...
@@ -2900,7 +2908,7 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
?
_value
.
selection
!=
value
.
selection
?
_value
.
selection
!=
value
.
selection
:
_value
!=
value
;
:
_value
!=
value
;
if
(
shouldShowCaret
)
{
if
(
shouldShowCaret
)
{
_scheduleShowCaretOnScreen
();
_scheduleShowCaretOnScreen
(
withAnimation:
true
);
}
}
_formatAndSetValue
(
value
,
cause
,
userInteraction:
true
);
_formatAndSetValue
(
value
,
cause
,
userInteraction:
true
);
}
}
...
...
packages/flutter/test/widgets/editable_text_test.dart
View file @
dbbaf68e
...
@@ -2,6 +2,8 @@
...
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// found in the LICENSE file.
import
'dart:ui'
as
ui
;
import
'package:flutter/cupertino.dart'
;
import
'package:flutter/cupertino.dart'
;
import
'package:flutter/foundation.dart'
;
import
'package:flutter/foundation.dart'
;
import
'package:flutter/gestures.dart'
;
import
'package:flutter/gestures.dart'
;
...
@@ -39,6 +41,26 @@ class _MatchesMethodCall extends Matcher {
...
@@ -39,6 +41,26 @@ class _MatchesMethodCall extends Matcher {
}
}
}
}
// Used to set window.viewInsets since the real ui.WindowPadding has only a
// private constructor.
class
_TestWindowPadding
implements
ui
.
WindowPadding
{
const
_TestWindowPadding
({
required
this
.
bottom
,
});
@override
final
double
bottom
;
@override
double
get
top
=>
0.0
;
@override
double
get
left
=>
0.0
;
@override
double
get
right
=>
0.0
;
}
late
TextEditingController
controller
;
late
TextEditingController
controller
;
final
FocusNode
focusNode
=
FocusNode
(
debugLabel:
'EditableText Node'
);
final
FocusNode
focusNode
=
FocusNode
(
debugLabel:
'EditableText Node'
);
final
FocusScopeNode
focusScopeNode
=
FocusScopeNode
(
debugLabel:
'EditableText Scope Node'
);
final
FocusScopeNode
focusScopeNode
=
FocusScopeNode
(
debugLabel:
'EditableText Scope Node'
);
...
@@ -107,6 +129,51 @@ void main() {
...
@@ -107,6 +129,51 @@ void main() {
expect
(
tester
.
testTextInput
.
setClientArgs
![
'inputAction'
],
equals
(
serializedActionName
));
expect
(
tester
.
testTextInput
.
setClientArgs
![
'inputAction'
],
equals
(
serializedActionName
));
}
}
// Related issue: https://github.com/flutter/flutter/issues/98115
testWidgets
(
'ScheduleShowCaretOnScreen with no animation when the window changes metrics'
,
(
WidgetTester
tester
)
async
{
final
ScrollController
scrollController
=
ScrollController
();
final
Widget
widget
=
MaterialApp
(
home:
Scaffold
(
body:
SingleChildScrollView
(
controller:
scrollController
,
child:
Column
(
children:
<
Widget
>[
Column
(
children:
List
<
Widget
>.
generate
(
5
,
(
_
)
{
return
Container
(
height:
1200.0
,
color:
Colors
.
black12
,
);
},
),
),
SizedBox
(
height:
20
,
child:
EditableText
(
controller:
TextEditingController
(),
backgroundCursorColor:
Colors
.
grey
,
focusNode:
focusNode
,
style:
const
TextStyle
(),
cursorColor:
Colors
.
red
,
),
),
],
),
),
),
);
await
tester
.
pumpWidget
(
widget
);
await
tester
.
showKeyboard
(
find
.
byType
(
EditableText
));
TestWidgetsFlutterBinding
.
instance
.
window
.
viewInsetsTestValue
=
const
_TestWindowPadding
(
bottom:
500
);
await
tester
.
pump
();
// The offset of the scrollController should change immediately after window changes its metrics.
final
double
offsetAfter
=
scrollController
.
offset
;
expect
(
offsetAfter
,
isNot
(
0.0
));
});
// Regression test for https://github.com/flutter/flutter/issues/34538.
// Regression test for https://github.com/flutter/flutter/issues/34538.
testWidgets
(
'RTL arabic correct caret placement after trailing whitespace'
,
(
WidgetTester
tester
)
async
{
testWidgets
(
'RTL arabic correct caret placement after trailing whitespace'
,
(
WidgetTester
tester
)
async
{
final
TextEditingController
controller
=
TextEditingController
();
final
TextEditingController
controller
=
TextEditingController
();
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment