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
0e72f992
Unverified
Commit
0e72f992
authored
Oct 01, 2021
by
LongCatIsLooong
Committed by
GitHub
Oct 01, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Restart input connection after `EditableText.onSubmitted` (#84307)
parent
7fbfb1fa
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
127 additions
and
1 deletion
+127
-1
editable_text.dart
packages/flutter/lib/src/widgets/editable_text.dart
+62
-1
editable_text_test.dart
packages/flutter/test/widgets/editable_text_test.dart
+65
-0
No files found.
packages/flutter/lib/src/widgets/editable_text.dart
View file @
0e72f992
...
@@ -2006,9 +2006,14 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
...
@@ -2006,9 +2006,14 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
}
}
}
}
final
ValueChanged
<
String
>?
onSubmitted
=
widget
.
onSubmitted
;
if
(
onSubmitted
==
null
)
{
return
;
}
// Invoke optional callback with the user's submitted content.
// Invoke optional callback with the user's submitted content.
try
{
try
{
widget
.
onSubmitted
?.
call
(
_value
.
text
);
onSubmitted
(
_value
.
text
);
}
catch
(
exception
,
stack
)
{
}
catch
(
exception
,
stack
)
{
FlutterError
.
reportError
(
FlutterErrorDetails
(
FlutterError
.
reportError
(
FlutterErrorDetails
(
exception:
exception
,
exception:
exception
,
...
@@ -2017,6 +2022,20 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
...
@@ -2017,6 +2022,20 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
context:
ErrorDescription
(
'while calling onSubmitted for
$action
'
),
context:
ErrorDescription
(
'while calling onSubmitted for
$action
'
),
));
));
}
}
// If `shouldUnfocus` is true, the text field should no longer be focused
// after the microtask queue is drained. But in case the developer cancelled
// the focus change in the `onSubmitted` callback by focusing this input
// field again, reset the soft keyboard.
// See https://github.com/flutter/flutter/issues/84240.
//
// `_restartConnectionIfNeeded` creates a new TextInputConnection to replace
// the current one. This on iOS switches to a new input view and on Android
// restarts the input method, and in both cases the soft keyboard will be
// reset.
if
(
shouldUnfocus
)
{
_scheduleRestartConnection
();
}
}
}
int
_batchEditDepth
=
0
;
int
_batchEditDepth
=
0
;
...
@@ -2159,6 +2178,7 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
...
@@ -2159,6 +2178,7 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
textAlign:
widget
.
textAlign
,
textAlign:
widget
.
textAlign
,
)
)
..
setEditingState
(
localValue
);
..
setEditingState
(
localValue
);
_lastKnownRemoteTextEditingValue
=
localValue
;
}
else
{
}
else
{
_textInputConnection
!.
show
();
_textInputConnection
!.
show
();
}
}
...
@@ -2181,6 +2201,47 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
...
@@ -2181,6 +2201,47 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
}
}
}
}
bool
_restartConnectionScheduled
=
false
;
void
_scheduleRestartConnection
()
{
if
(
_restartConnectionScheduled
)
{
return
;
}
_restartConnectionScheduled
=
true
;
scheduleMicrotask
(
_restartConnectionIfNeeded
);
}
// Discards the current [TextInputConnection] and establishes a new one.
//
// This method is rarely needed. This is currently used to reset the input
// type when the "submit" text input action is triggered and the developer
// puts the focus back to this input field..
void
_restartConnectionIfNeeded
()
{
_restartConnectionScheduled
=
false
;
if
(!
_hasInputConnection
||
!
_shouldCreateInputConnection
)
{
return
;
}
_textInputConnection
!.
close
();
_textInputConnection
=
null
;
_lastKnownRemoteTextEditingValue
=
null
;
final
AutofillScope
?
currentAutofillScope
=
_needsAutofill
?
this
.
currentAutofillScope
:
null
;
final
TextInputConnection
newConnection
=
currentAutofillScope
?.
attach
(
this
,
textInputConfiguration
)
??
TextInput
.
attach
(
this
,
_effectiveAutofillClient
.
textInputConfiguration
);
_textInputConnection
=
newConnection
;
final
TextStyle
style
=
widget
.
style
;
newConnection
..
setStyle
(
fontFamily:
style
.
fontFamily
,
fontSize:
style
.
fontSize
,
fontWeight:
style
.
fontWeight
,
textDirection:
_textDirection
,
textAlign:
widget
.
textAlign
,
)
..
setEditingState
(
_value
);
_lastKnownRemoteTextEditingValue
=
_value
;
}
@override
@override
void
connectionClosed
()
{
void
connectionClosed
()
{
if
(
_hasInputConnection
)
{
if
(
_hasInputConnection
)
{
...
...
packages/flutter/test/widgets/editable_text_test.dart
View file @
0e72f992
...
@@ -2032,6 +2032,71 @@ void main() {
...
@@ -2032,6 +2032,71 @@ void main() {
assert
(!
onEditingCompleteCalled
);
assert
(!
onEditingCompleteCalled
);
});
});
testWidgets
(
'finalizeEditing should reset the input connection when shouldUnfocus is true but the unfocus is cancelled'
,
(
WidgetTester
tester
)
async
{
// Regression test for https://github.com/flutter/flutter/issues/84240 .
Widget
widget
=
MaterialApp
(
home:
EditableText
(
backgroundCursorColor:
Colors
.
grey
,
style:
Typography
.
material2018
(
platform:
TargetPlatform
.
android
).
black
.
subtitle1
!,
cursorColor:
Colors
.
blue
,
focusNode:
focusNode
,
controller:
controller
,
onSubmitted:
(
String
value
)
{},
),
);
await
tester
.
pumpWidget
(
widget
);
focusNode
.
requestFocus
();
await
tester
.
pump
();
assert
(
focusNode
.
hasFocus
);
tester
.
testTextInput
.
log
.
clear
();
// This should unfocus the field. Don't restart the input.
await
tester
.
testTextInput
.
receiveAction
(
TextInputAction
.
done
);
expect
(
tester
.
testTextInput
.
log
,
isNot
(
containsAllInOrder
(<
Matcher
>[
matchesMethodCall
(
'TextInput.clearClient'
),
matchesMethodCall
(
'TextInput.setClient'
),
])));
widget
=
MaterialApp
(
home:
EditableText
(
backgroundCursorColor:
Colors
.
grey
,
style:
Typography
.
material2018
(
platform:
TargetPlatform
.
android
).
black
.
subtitle1
!,
cursorColor:
Colors
.
blue
,
focusNode:
focusNode
,
controller:
controller
,
onSubmitted:
(
String
value
)
{
focusNode
.
requestFocus
();
},
),
);
await
tester
.
pumpWidget
(
widget
);
focusNode
.
requestFocus
();
await
tester
.
pump
();
assert
(
focusNode
.
hasFocus
);
tester
.
testTextInput
.
log
.
clear
();
// This will attempt to unfocus the field but the onSubmitted callback
// will cancel that. Restart the input connection in this case.
await
tester
.
testTextInput
.
receiveAction
(
TextInputAction
.
done
);
expect
(
tester
.
testTextInput
.
log
,
containsAllInOrder
(<
Matcher
>[
matchesMethodCall
(
'TextInput.clearClient'
),
matchesMethodCall
(
'TextInput.setClient'
),
]));
tester
.
testTextInput
.
log
.
clear
();
// TextInputAction.unspecified does not unfocus the input field by default.
await
tester
.
testTextInput
.
receiveAction
(
TextInputAction
.
unspecified
);
expect
(
tester
.
testTextInput
.
log
,
isNot
(
containsAllInOrder
(<
Matcher
>[
matchesMethodCall
(
'TextInput.clearClient'
),
matchesMethodCall
(
'TextInput.setClient'
),
])));
});
testWidgets
(
testWidgets
(
'iOS autocorrection rectangle should appear on demand and dismiss when the text changes or when focus is lost'
,
'iOS autocorrection rectangle should appear on demand and dismiss when the text changes or when focus is lost'
,
(
WidgetTester
tester
)
async
{
(
WidgetTester
tester
)
async
{
...
...
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