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
40b4bc99
Unverified
Commit
40b4bc99
authored
Jun 20, 2023
by
Justin McCandless
Committed by
GitHub
Jun 20, 2023
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fix: Magnifier appears and won't dismiss (#128545)
Fixes a bug when tapping near certain TextFields.
parent
541fdd60
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
98 additions
and
8 deletions
+98
-8
text_selection.dart
packages/flutter/lib/src/widgets/text_selection.dart
+45
-3
text_field_test.dart
packages/flutter/test/material/text_field_test.dart
+53
-5
No files found.
packages/flutter/lib/src/widgets/text_selection.dart
View file @
40b4bc99
...
@@ -1088,10 +1088,26 @@ class SelectionOverlay {
...
@@ -1088,10 +1088,26 @@ class SelectionOverlay {
void
_handleStartHandleDragStart
(
DragStartDetails
details
)
{
void
_handleStartHandleDragStart
(
DragStartDetails
details
)
{
assert
(!
_isDraggingStartHandle
);
assert
(!
_isDraggingStartHandle
);
// Calling OverlayEntry.remove may not happen until the following frame, so
// it's possible for the handles to receive a gesture after calling remove.
if
(
_handles
==
null
)
{
_isDraggingStartHandle
=
false
;
return
;
}
_isDraggingStartHandle
=
details
.
kind
==
PointerDeviceKind
.
touch
;
_isDraggingStartHandle
=
details
.
kind
==
PointerDeviceKind
.
touch
;
onStartHandleDragStart
?.
call
(
details
);
onStartHandleDragStart
?.
call
(
details
);
}
}
void
_handleStartHandleDragUpdate
(
DragUpdateDetails
details
)
{
// Calling OverlayEntry.remove may not happen until the following frame, so
// it's possible for the handles to receive a gesture after calling remove.
if
(
_handles
==
null
)
{
_isDraggingStartHandle
=
false
;
return
;
}
onStartHandleDragUpdate
?.
call
(
details
);
}
/// Called when the users drag the start selection handles to new locations.
/// Called when the users drag the start selection handles to new locations.
final
ValueChanged
<
DragUpdateDetails
>?
onStartHandleDragUpdate
;
final
ValueChanged
<
DragUpdateDetails
>?
onStartHandleDragUpdate
;
...
@@ -1101,6 +1117,11 @@ class SelectionOverlay {
...
@@ -1101,6 +1117,11 @@ class SelectionOverlay {
void
_handleStartHandleDragEnd
(
DragEndDetails
details
)
{
void
_handleStartHandleDragEnd
(
DragEndDetails
details
)
{
_isDraggingStartHandle
=
false
;
_isDraggingStartHandle
=
false
;
// Calling OverlayEntry.remove may not happen until the following frame, so
// it's possible for the handles to receive a gesture after calling remove.
if
(
_handles
==
null
)
{
return
;
}
onStartHandleDragEnd
?.
call
(
details
);
onStartHandleDragEnd
?.
call
(
details
);
}
}
...
@@ -1147,10 +1168,26 @@ class SelectionOverlay {
...
@@ -1147,10 +1168,26 @@ class SelectionOverlay {
void
_handleEndHandleDragStart
(
DragStartDetails
details
)
{
void
_handleEndHandleDragStart
(
DragStartDetails
details
)
{
assert
(!
_isDraggingEndHandle
);
assert
(!
_isDraggingEndHandle
);
// Calling OverlayEntry.remove may not happen until the following frame, so
// it's possible for the handles to receive a gesture after calling remove.
if
(
_handles
==
null
)
{
_isDraggingEndHandle
=
false
;
return
;
}
_isDraggingEndHandle
=
details
.
kind
==
PointerDeviceKind
.
touch
;
_isDraggingEndHandle
=
details
.
kind
==
PointerDeviceKind
.
touch
;
onEndHandleDragStart
?.
call
(
details
);
onEndHandleDragStart
?.
call
(
details
);
}
}
void
_handleEndHandleDragUpdate
(
DragUpdateDetails
details
)
{
// Calling OverlayEntry.remove may not happen until the following frame, so
// it's possible for the handles to receive a gesture after calling remove.
if
(
_handles
==
null
)
{
_isDraggingEndHandle
=
false
;
return
;
}
onEndHandleDragUpdate
?.
call
(
details
);
}
/// Called when the users drag the end selection handles to new locations.
/// Called when the users drag the end selection handles to new locations.
final
ValueChanged
<
DragUpdateDetails
>?
onEndHandleDragUpdate
;
final
ValueChanged
<
DragUpdateDetails
>?
onEndHandleDragUpdate
;
...
@@ -1160,6 +1197,11 @@ class SelectionOverlay {
...
@@ -1160,6 +1197,11 @@ class SelectionOverlay {
void
_handleEndHandleDragEnd
(
DragEndDetails
details
)
{
void
_handleEndHandleDragEnd
(
DragEndDetails
details
)
{
_isDraggingEndHandle
=
false
;
_isDraggingEndHandle
=
false
;
// Calling OverlayEntry.remove may not happen until the following frame, so
// it's possible for the handles to receive a gesture after calling remove.
if
(
_handles
==
null
)
{
return
;
}
onEndHandleDragEnd
?.
call
(
details
);
onEndHandleDragEnd
?.
call
(
details
);
}
}
...
@@ -1472,7 +1514,7 @@ class SelectionOverlay {
...
@@ -1472,7 +1514,7 @@ class SelectionOverlay {
handleLayerLink:
startHandleLayerLink
,
handleLayerLink:
startHandleLayerLink
,
onSelectionHandleTapped:
onSelectionHandleTapped
,
onSelectionHandleTapped:
onSelectionHandleTapped
,
onSelectionHandleDragStart:
_handleStartHandleDragStart
,
onSelectionHandleDragStart:
_handleStartHandleDragStart
,
onSelectionHandleDragUpdate:
on
StartHandleDragUpdate
,
onSelectionHandleDragUpdate:
_handle
StartHandleDragUpdate
,
onSelectionHandleDragEnd:
_handleStartHandleDragEnd
,
onSelectionHandleDragEnd:
_handleStartHandleDragEnd
,
selectionControls:
selectionControls
,
selectionControls:
selectionControls
,
visibility:
startHandlesVisible
,
visibility:
startHandlesVisible
,
...
@@ -1499,7 +1541,7 @@ class SelectionOverlay {
...
@@ -1499,7 +1541,7 @@ class SelectionOverlay {
handleLayerLink:
endHandleLayerLink
,
handleLayerLink:
endHandleLayerLink
,
onSelectionHandleTapped:
onSelectionHandleTapped
,
onSelectionHandleTapped:
onSelectionHandleTapped
,
onSelectionHandleDragStart:
_handleEndHandleDragStart
,
onSelectionHandleDragStart:
_handleEndHandleDragStart
,
onSelectionHandleDragUpdate:
on
EndHandleDragUpdate
,
onSelectionHandleDragUpdate:
_handle
EndHandleDragUpdate
,
onSelectionHandleDragEnd:
_handleEndHandleDragEnd
,
onSelectionHandleDragEnd:
_handleEndHandleDragEnd
,
selectionControls:
selectionControls
,
selectionControls:
selectionControls
,
visibility:
endHandlesVisible
,
visibility:
endHandlesVisible
,
...
@@ -1752,7 +1794,7 @@ class _SelectionHandleOverlayState extends State<_SelectionHandleOverlay> with S
...
@@ -1752,7 +1794,7 @@ class _SelectionHandleOverlayState extends State<_SelectionHandleOverlay> with S
// Make sure the GestureDetector is big enough to be easily interactive.
// Make sure the GestureDetector is big enough to be easily interactive.
final
Rect
interactiveRect
=
handleRect
.
expandToInclude
(
final
Rect
interactiveRect
=
handleRect
.
expandToInclude
(
Rect
.
fromCircle
(
center:
handleRect
.
center
,
radius:
kMinInteractiveDimension
/
2
),
Rect
.
fromCircle
(
center:
handleRect
.
center
,
radius:
kMinInteractiveDimension
/
2
),
);
);
final
RelativeRect
padding
=
RelativeRect
.
fromLTRB
(
final
RelativeRect
padding
=
RelativeRect
.
fromLTRB
(
math
.
max
((
interactiveRect
.
width
-
handleRect
.
width
)
/
2
,
0
),
math
.
max
((
interactiveRect
.
width
-
handleRect
.
width
)
/
2
,
0
),
...
...
packages/flutter/test/material/text_field_test.dart
View file @
40b4bc99
...
@@ -15803,7 +15803,7 @@ void main() {
...
@@ -15803,7 +15803,7 @@ void main() {
);
);
final
TextField
textField
=
TextField
(
final
TextField
textField
=
TextField
(
magnifierConfiguration:
TextMagnifierConfiguration
(
magnifierConfiguration:
TextMagnifierConfiguration
(
magnifierBuilder:
(
_
,
__
,
___
)
=>
customMagnifier
,
magnifierBuilder:
(
BuildContext
context
,
MagnifierController
controller
,
ValueNotifier
<
MagnifierInfo
>?
info
)
=>
customMagnifier
,
),
),
);
);
...
@@ -15901,7 +15901,7 @@ void main() {
...
@@ -15901,7 +15901,7 @@ void main() {
controller:
controller
,
controller:
controller
,
magnifierConfiguration:
TextMagnifierConfiguration
(
magnifierConfiguration:
TextMagnifierConfiguration
(
magnifierBuilder:
(
magnifierBuilder:
(
_
,
BuildContext
context
,
MagnifierController
controller
,
MagnifierController
controller
,
ValueNotifier
<
MagnifierInfo
>
localMagnifierInfo
ValueNotifier
<
MagnifierInfo
>
localMagnifierInfo
)
{
)
{
...
@@ -15965,7 +15965,7 @@ void main() {
...
@@ -15965,7 +15965,7 @@ void main() {
controller:
controller
,
controller:
controller
,
magnifierConfiguration:
TextMagnifierConfiguration
(
magnifierConfiguration:
TextMagnifierConfiguration
(
magnifierBuilder:
(
magnifierBuilder:
(
_
,
BuildContext
context
,
MagnifierController
controller
,
MagnifierController
controller
,
ValueNotifier
<
MagnifierInfo
>
localMagnifierInfo
ValueNotifier
<
MagnifierInfo
>
localMagnifierInfo
)
{
)
{
...
@@ -16067,7 +16067,7 @@ void main() {
...
@@ -16067,7 +16067,7 @@ void main() {
controller:
controller
,
controller:
controller
,
magnifierConfiguration:
TextMagnifierConfiguration
(
magnifierConfiguration:
TextMagnifierConfiguration
(
magnifierBuilder:
(
magnifierBuilder:
(
_
,
BuildContext
context
,
MagnifierController
controller
,
MagnifierController
controller
,
ValueNotifier
<
MagnifierInfo
>
localMagnifierInfo
ValueNotifier
<
MagnifierInfo
>
localMagnifierInfo
)
{
)
{
...
@@ -16118,6 +16118,54 @@ void main() {
...
@@ -16118,6 +16118,54 @@ void main() {
await
tester
.
pumpAndSettle
();
await
tester
.
pumpAndSettle
();
expect
(
find
.
byKey
(
fakeMagnifier
.
key
!),
findsNothing
);
expect
(
find
.
byKey
(
fakeMagnifier
.
key
!),
findsNothing
);
},
variant:
const
TargetPlatformVariant
(<
TargetPlatform
>{
TargetPlatform
.
android
,
TargetPlatform
.
iOS
}));
},
variant:
const
TargetPlatformVariant
(<
TargetPlatform
>{
TargetPlatform
.
android
,
TargetPlatform
.
iOS
}));
testWidgets
(
'magnifier does not show when tapping outside field'
,
(
WidgetTester
tester
)
async
{
// Regression test for https://github.com/flutter/flutter/issues/128321
await
tester
.
pumpWidget
(
MaterialApp
(
home:
Scaffold
(
body:
Padding
(
padding:
const
EdgeInsets
.
all
(
20
),
child:
TextField
(
magnifierConfiguration:
TextMagnifierConfiguration
(
magnifierBuilder:
(
BuildContext
context
,
MagnifierController
controller
,
ValueNotifier
<
MagnifierInfo
>
localMagnifierInfo
)
{
magnifierInfo
=
localMagnifierInfo
;
return
fakeMagnifier
;
},
),
onTapOutside:
(
PointerDownEvent
event
)
{
FocusManager
.
instance
.
primaryFocus
?.
unfocus
();
}
),
),
),
),
);
await
tester
.
tapAt
(
tester
.
getCenter
(
find
.
byType
(
TextField
)),
);
await
tester
.
pump
();
expect
(
find
.
byKey
(
fakeMagnifier
.
key
!),
findsNothing
);
final
TestGesture
gesture
=
await
tester
.
startGesture
(
tester
.
getBottomLeft
(
find
.
byType
(
TextField
))
-
const
Offset
(
10.0
,
20.0
),
);
await
tester
.
pump
();
expect
(
find
.
byKey
(
fakeMagnifier
.
key
!),
findsNothing
);
await
gesture
.
up
();
await
tester
.
pump
();
expect
(
find
.
byKey
(
fakeMagnifier
.
key
!),
findsNothing
);
},
skip:
isContextMenuProvidedByPlatform
,
// [intended] only applies to platforms where we supply the context menu.
variant:
const
TargetPlatformVariant
(<
TargetPlatform
>{
TargetPlatform
.
android
}),
);
});
});
group
(
'TapRegion integration'
,
()
{
group
(
'TapRegion integration'
,
()
{
...
@@ -16513,7 +16561,7 @@ class _ObscureTextTestWidgetState extends State<_ObscureTextTestWidget> {
...
@@ -16513,7 +16561,7 @@ class _ObscureTextTestWidgetState extends State<_ObscureTextTestWidget> {
return
MaterialApp
(
return
MaterialApp
(
home:
Scaffold
(
home:
Scaffold
(
body:
Builder
(
body:
Builder
(
builder:
(
_
)
{
builder:
(
BuildContext
context
)
{
return
Column
(
return
Column
(
children:
<
Widget
>[
children:
<
Widget
>[
TextField
(
TextField
(
...
...
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