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
b09e64e1
Unverified
Commit
b09e64e1
authored
Feb 26, 2019
by
xster
Committed by
GitHub
Feb 26, 2019
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Support iOS devices reporting pressure data of 0 (#28478)
parent
a49d93b9
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
182 additions
and
137 deletions
+182
-137
force_press.dart
packages/flutter/lib/src/gestures/force_press.dart
+4
-6
text_field_test.dart
packages/flutter/test/cupertino/text_field_test.dart
+74
-32
force_press_test.dart
packages/flutter/test/gestures/force_press_test.dart
+47
-89
text_field_test.dart
packages/flutter/test/material/text_field_test.dart
+57
-10
No files found.
packages/flutter/lib/src/gestures/force_press.dart
View file @
b09e64e1
...
...
@@ -206,12 +206,10 @@ class ForcePressGestureRecognizer extends OneSequenceGestureRecognizer {
@override
void
addPointer
(
PointerEvent
event
)
{
assert
(
event
.
pressureMax
>=
1.0
);
// If the device has a maximum pressure of less than or equal to 1,
// indicating a faux pressure sensor on this device or a device without a
// pressure sensor (ie. on a non iOS device) we want do not want any
// callbacks to be called.
if
(!(
event
is
PointerUpEvent
)
&&
event
.
pressureMax
==
1.0
)
{
// If the device has a maximum pressure of less than or equal to 1, it
// doesn't have touch pressure sensing capabilities. Do not participate
// in the gesture arena.
if
(!(
event
is
PointerUpEvent
)
&&
event
.
pressureMax
<=
1.0
)
{
resolve
(
GestureDisposition
.
rejected
);
}
else
{
startTrackingPointer
(
event
.
pointer
);
...
...
packages/flutter/test/cupertino/text_field_test.dart
View file @
b09e64e1
...
...
@@ -1537,6 +1537,7 @@ void main() {
controller
.
selection
,
const
TextSelection
(
baseOffset:
8
,
extentOffset:
12
),
);
// Shows toolbar.
expect
(
find
.
byType
(
CupertinoButton
),
findsNWidgets
(
3
));
},
);
...
...
@@ -1607,44 +1608,85 @@ void main() {
);
testWidgets
(
'force press selects word'
,
(
WidgetTester
tester
)
async
{
final
TextEditingController
controller
=
TextEditingController
(
text:
'Atwater Peel Sherbrooke Bonaventure'
,
);
await
tester
.
pumpWidget
(
CupertinoApp
(
home:
Center
(
child:
CupertinoTextField
(
controller:
controller
,
),
final
TextEditingController
controller
=
TextEditingController
(
text:
'Atwater Peel Sherbrooke Bonaventure'
,
);
await
tester
.
pumpWidget
(
CupertinoApp
(
home:
Center
(
child:
CupertinoTextField
(
controller:
controller
,
),
),
);
),
);
final
Offset
textfieldStart
=
tester
.
getTopLeft
(
find
.
byType
(
CupertinoTextField
));
final
Offset
textfieldStart
=
tester
.
getTopLeft
(
find
.
byType
(
CupertinoTextField
));
const
int
pointerValue
=
1
;
final
TestGesture
gesture
=
await
tester
.
createGesture
();
await
gesture
.
downWithCustomEvent
(
textfieldStart
+
const
Offset
(
150.0
,
5.0
),
PointerDownEvent
(
pointer:
pointerValue
,
position:
textfieldStart
+
const
Offset
(
150.0
,
5.0
),
pressure:
3.0
,
pressureMax:
6.0
,
pressureMin:
0.0
),
);
// We expect the force press to select a word at the given location.
expect
(
controller
.
selection
,
const
TextSelection
(
baseOffset:
8
,
extentOffset:
12
),
);
await
gesture
.
up
();
await
tester
.
pump
();
// Shows toolbar.
expect
(
find
.
byType
(
CupertinoButton
),
findsNWidgets
(
3
));
});
const
int
pointerValue
=
1
;
final
TestGesture
gesture
=
await
tester
.
createGesture
();
await
gesture
.
downWithCustomEvent
(
textfieldStart
+
const
Offset
(
150.0
,
5.0
),
PointerDownEven
t
(
pointer:
pointerValue
,
position:
textfieldStart
+
const
Offset
(
150.0
,
5.0
),
pressure:
3.0
,
pressureMax:
6.0
,
pressureMin:
0.0
testWidgets
(
'force press on unsupported devices falls back to tap'
,
(
WidgetTester
tester
)
async
{
final
TextEditingController
controller
=
TextEditingController
(
text:
'Atwater Peel Sherbrooke Bonaventure'
,
);
await
tester
.
pumpWidge
t
(
CupertinoApp
(
home:
Center
(
child:
CupertinoTextField
(
controller:
controller
,
),
),
);
// We expect the force press to select a word at the given location.
expect
(
controller
.
selection
,
const
TextSelection
(
baseOffset:
8
,
extentOffset:
12
),
);
),
);
await
gesture
.
up
();
await
tester
.
pumpAndSettle
();
expect
(
find
.
byType
(
CupertinoButton
),
findsNWidgets
(
3
));
},
);
final
Offset
textfieldStart
=
tester
.
getTopLeft
(
find
.
byType
(
CupertinoTextField
));
const
int
pointerValue
=
1
;
final
TestGesture
gesture
=
await
tester
.
createGesture
();
await
gesture
.
downWithCustomEvent
(
textfieldStart
+
const
Offset
(
150.0
,
5.0
),
PointerDownEvent
(
pointer:
pointerValue
,
position:
textfieldStart
+
const
Offset
(
150.0
,
5.0
),
// iPhone 6 and below report 0 across the board.
pressure:
0
,
pressureMax:
0
,
pressureMin:
0
,
),
);
await
gesture
.
up
();
// Fall back to a single tap which selects the edge of the word.
expect
(
controller
.
selection
,
const
TextSelection
.
collapsed
(
offset:
8
),
);
await
tester
.
pump
();
// Falling back to a single tap doesn't trigger a toolbar.
expect
(
find
.
byType
(
CupertinoButton
),
findsNothing
);
});
testWidgets
(
'text field respects theme'
,
...
...
packages/flutter/test/gestures/force_press_test.dart
View file @
b09e64e1
...
...
@@ -109,97 +109,55 @@ void main() {
expect
(
ended
,
1
);
});
testGesture
(
'Force presses are not recognized on devices with low maxmium pressure'
,
(
GestureTester
tester
)
{
// Device specific constants that represent those from the iPhone X
const
double
pressureMin
=
0
;
const
double
pressureMax
=
1.0
;
// Interpolated Flutter pressure values.
const
double
startPressure
=
0.4
;
// = Device pressure of 2.66.
const
double
peakPressure
=
0.85
;
// = Device pressure of 5.66.
int
started
=
0
;
int
peaked
=
0
;
int
updated
=
0
;
int
ended
=
0
;
void
onStart
(
ForcePressDetails
details
)
{
started
+=
1
;
testGesture
(
'Invalid pressure ranges capabilities are not recognized'
,
(
GestureTester
tester
)
{
void
testGestureWithMaxPressure
(
double
pressureMax
)
{
int
started
=
0
;
int
peaked
=
0
;
int
updated
=
0
;
int
ended
=
0
;
final
ForcePressGestureRecognizer
force
=
ForcePressGestureRecognizer
();
force
.
onStart
=
(
ForcePressDetails
details
)
=>
started
+=
1
;
force
.
onPeak
=
(
ForcePressDetails
details
)
=>
peaked
+=
1
;
force
.
onUpdate
=
(
ForcePressDetails
details
)
=>
updated
+=
1
;
force
.
onEnd
=
(
ForcePressDetails
details
)
=>
ended
+=
1
;
const
int
pointerValue
=
1
;
final
TestPointer
pointer
=
TestPointer
(
pointerValue
);
final
PointerDownEvent
down
=
PointerDownEvent
(
pointer:
pointerValue
,
position:
const
Offset
(
10.0
,
10.0
),
pressure:
0
,
pressureMin:
0
,
pressureMax:
pressureMax
);
pointer
.
setDownInfo
(
down
,
const
Offset
(
10.0
,
10.0
));
force
.
addPointer
(
down
);
tester
.
closeArena
(
pointerValue
);
expect
(
started
,
0
);
expect
(
peaked
,
0
);
expect
(
updated
,
0
);
expect
(
ended
,
0
);
// Pressure fed into the test environment simulates the values received directly from the device.
tester
.
route
(
PointerMoveEvent
(
pointer:
pointerValue
,
position:
const
Offset
(
10.0
,
10.0
),
pressure:
10
,
pressureMin:
0
,
pressureMax:
pressureMax
));
// Regardless of current pressure, this recognizer shouldn't participate or
// trigger any callbacks.
expect
(
started
,
0
);
expect
(
peaked
,
0
);
expect
(
updated
,
0
);
expect
(
ended
,
0
);
tester
.
route
(
pointer
.
up
());
// There should still be no callbacks.
expect
(
started
,
0
);
expect
(
updated
,
0
);
expect
(
peaked
,
0
);
expect
(
ended
,
0
);
}
final
ForcePressGestureRecognizer
force
=
ForcePressGestureRecognizer
(
startPressure:
startPressure
,
peakPressure:
peakPressure
);
force
.
onStart
=
onStart
;
force
.
onPeak
=
(
ForcePressDetails
details
)
=>
peaked
+=
1
;
force
.
onUpdate
=
(
ForcePressDetails
details
)
=>
updated
+=
1
;
force
.
onEnd
=
(
ForcePressDetails
details
)
=>
ended
+=
1
;
const
int
pointerValue
=
1
;
final
TestPointer
pointer
=
TestPointer
(
pointerValue
);
const
PointerDownEvent
down
=
PointerDownEvent
(
pointer:
pointerValue
,
position:
Offset
(
10.0
,
10.0
),
pressure:
0
,
pressureMin:
pressureMin
,
pressureMax:
pressureMax
);
pointer
.
setDownInfo
(
down
,
const
Offset
(
10.0
,
10.0
));
force
.
addPointer
(
down
);
tester
.
closeArena
(
pointerValue
);
expect
(
started
,
0
);
expect
(
peaked
,
0
);
expect
(
updated
,
0
);
expect
(
ended
,
0
);
// Pressure fed into the test environment simulates the values received directly from the device.
tester
.
route
(
const
PointerMoveEvent
(
pointer:
pointerValue
,
position:
Offset
(
10.0
,
10.0
),
pressure:
2.5
,
pressureMin:
pressureMin
,
pressureMax:
pressureMax
));
// We have not hit the start pressure, so no events should be true.
expect
(
started
,
0
);
expect
(
peaked
,
0
);
expect
(
updated
,
0
);
expect
(
ended
,
0
);
tester
.
route
(
const
PointerMoveEvent
(
pointer:
pointerValue
,
position:
Offset
(
10.0
,
10.0
),
pressure:
2.8
,
pressureMin:
pressureMin
,
pressureMax:
pressureMax
));
// We have just hit the start pressure so just the start event should be triggered and one update call should have occurred.
expect
(
started
,
0
);
expect
(
peaked
,
0
);
expect
(
updated
,
0
);
expect
(
ended
,
0
);
tester
.
route
(
const
PointerMoveEvent
(
pointer:
pointerValue
,
position:
Offset
(
10.0
,
10.0
),
pressure:
3.3
,
pressureMin:
pressureMin
,
pressureMax:
pressureMax
));
tester
.
route
(
const
PointerMoveEvent
(
pointer:
pointerValue
,
position:
Offset
(
10.0
,
10.0
),
pressure:
4.0
,
pressureMin:
pressureMin
,
pressureMax:
pressureMax
));
tester
.
route
(
const
PointerMoveEvent
(
pointer:
pointerValue
,
position:
Offset
(
10.0
,
10.0
),
pressure:
5.0
,
pressureMin:
pressureMin
,
pressureMax:
pressureMax
));
tester
.
route
(
const
PointerMoveEvent
(
pointer:
pointerValue
,
position:
Offset
(
10.0
,
10.0
),
pressure:
1.0
,
pressureMin:
pressureMin
,
pressureMax:
pressureMax
));
// We have exceeded the start pressure so update should be greater than 0.
expect
(
started
,
0
);
expect
(
updated
,
0
);
expect
(
peaked
,
0
);
expect
(
ended
,
0
);
tester
.
route
(
const
PointerMoveEvent
(
pointer:
pointerValue
,
position:
Offset
(
10.0
,
10.0
),
pressure:
6.0
,
pressureMin:
pressureMin
,
pressureMax:
pressureMax
));
// We have exceeded the peak pressure so peak pressure should be true.
expect
(
started
,
0
);
expect
(
updated
,
0
);
expect
(
peaked
,
0
);
expect
(
ended
,
0
);
tester
.
route
(
const
PointerMoveEvent
(
pointer:
pointerValue
,
position:
Offset
(
10.0
,
10.0
),
pressure:
3.3
,
pressureMin:
pressureMin
,
pressureMax:
pressureMax
));
tester
.
route
(
const
PointerMoveEvent
(
pointer:
pointerValue
,
position:
Offset
(
10.0
,
10.0
),
pressure:
4.0
,
pressureMin:
pressureMin
,
pressureMax:
pressureMax
));
tester
.
route
(
const
PointerMoveEvent
(
pointer:
pointerValue
,
position:
Offset
(
10.0
,
10.0
),
pressure:
5.0
,
pressureMin:
pressureMin
,
pressureMax:
pressureMax
));
tester
.
route
(
const
PointerMoveEvent
(
pointer:
pointerValue
,
position:
Offset
(
10.0
,
10.0
),
pressure:
1.0
,
pressureMin:
pressureMin
,
pressureMax:
pressureMax
));
// Update is still called.
expect
(
started
,
0
);
expect
(
updated
,
0
);
expect
(
peaked
,
0
);
expect
(
ended
,
0
);
tester
.
route
(
pointer
.
up
());
// We have ended the gesture so ended should be true.
expect
(
started
,
0
);
expect
(
updated
,
0
);
expect
(
peaked
,
0
);
expect
(
ended
,
0
);
testGestureWithMaxPressure
(
0
);
testGestureWithMaxPressure
(
1
);
testGestureWithMaxPressure
(-
1
);
testGestureWithMaxPressure
(
0.5
);
});
testGesture
(
'If minimum pressure is not reached, start and end callbacks are not called'
,
(
GestureTester
tester
)
{
...
...
packages/flutter/test/material/text_field_test.dart
View file @
b09e64e1
...
...
@@ -4083,6 +4083,7 @@ void main() {
controller
.
selection
,
const
TextSelection
(
baseOffset:
8
,
extentOffset:
12
),
);
// The toolbar is still showing.
expect
(
find
.
byType
(
CupertinoButton
),
findsNWidgets
(
3
));
},
);
...
...
@@ -4272,6 +4273,7 @@ void main() {
controller
.
selection
,
const
TextSelection
.
collapsed
(
offset:
3
,
affinity:
TextAffinity
.
downstream
),
);
// Cursor move doesn't trigger a toolbar initially.
expect
(
find
.
byType
(
CupertinoButton
),
findsNothing
);
await
gesture
.
moveBy
(
const
Offset
(
50
,
0
));
...
...
@@ -4282,6 +4284,7 @@ void main() {
controller
.
selection
,
const
TextSelection
.
collapsed
(
offset:
6
,
affinity:
TextAffinity
.
downstream
),
);
// Still no toolbar.
expect
(
find
.
byType
(
CupertinoButton
),
findsNothing
);
await
gesture
.
moveBy
(
const
Offset
(
50
,
0
));
...
...
@@ -4292,6 +4295,7 @@ void main() {
controller
.
selection
,
const
TextSelection
.
collapsed
(
offset:
9
,
affinity:
TextAffinity
.
downstream
),
);
// Still no toolbar.
expect
(
find
.
byType
(
CupertinoButton
),
findsNothing
);
await
gesture
.
up
();
...
...
@@ -4554,7 +4558,6 @@ void main() {
);
testWidgets
(
'force press does not select a word on (android)'
,
(
WidgetTester
tester
)
async
{
debugDefaultTargetPlatformOverride
=
TargetPlatform
.
android
;
final
TextEditingController
controller
=
TextEditingController
(
text:
'Atwater Peel Sherbrooke Bonaventure'
,
);
...
...
@@ -4588,27 +4591,26 @@ void main() {
expect
(
controller
.
selection
,
const
TextSelection
.
collapsed
(
offset:
-
1
));
await
gesture
.
up
();
await
tester
.
pump
AndSettle
();
await
tester
.
pump
();
expect
(
find
.
byType
(
FlatButton
),
findsNothing
);
debugDefaultTargetPlatformOverride
=
null
;
});
testWidgets
(
'force press selects word (iOS)'
,
(
WidgetTester
tester
)
async
{
debugDefaultTargetPlatformOverride
=
TargetPlatform
.
iOS
;
final
TextEditingController
controller
=
TextEditingController
(
text:
'Atwater Peel Sherbrooke Bonaventure'
,
);
await
tester
.
pumpWidget
(
CupertinoApp
(
home:
Center
(
child:
CupertinoTextField
(
MaterialApp
(
theme:
ThemeData
(
platform:
TargetPlatform
.
iOS
),
home:
Material
(
child:
TextField
(
controller:
controller
,
),
),
),
);
final
Offset
textfieldStart
=
tester
.
getTopLeft
(
find
.
byType
(
Cupertino
TextField
));
final
Offset
textfieldStart
=
tester
.
getTopLeft
(
find
.
byType
(
TextField
));
const
int
pointerValue
=
1
;
final
Offset
offset
=
textfieldStart
+
const
Offset
(
150.0
,
5.0
);
...
...
@@ -4632,9 +4634,54 @@ void main() {
);
await
gesture
.
up
();
await
tester
.
pump
AndSettle
();
await
tester
.
pump
();
expect
(
find
.
byType
(
CupertinoButton
),
findsNWidgets
(
3
));
debugDefaultTargetPlatformOverride
=
null
;
});
testWidgets
(
'tap on non-force-press-supported devices work (iOS)'
,
(
WidgetTester
tester
)
async
{
final
TextEditingController
controller
=
TextEditingController
(
text:
'Atwater Peel Sherbrooke Bonaventure'
,
);
await
tester
.
pumpWidget
(
MaterialApp
(
theme:
ThemeData
(
platform:
TargetPlatform
.
iOS
),
home:
Material
(
child:
TextField
(
controller:
controller
,
),
),
),
);
final
Offset
textfieldStart
=
tester
.
getTopLeft
(
find
.
byType
(
TextField
));
const
int
pointerValue
=
1
;
final
Offset
offset
=
textfieldStart
+
const
Offset
(
150.0
,
5.0
);
final
TestGesture
gesture
=
await
tester
.
createGesture
();
await
gesture
.
downWithCustomEvent
(
offset
,
PointerDownEvent
(
pointer:
pointerValue
,
position:
offset
,
// iPhone 6 and below report 0 across the board.
pressure:
0
,
pressureMax:
0
,
pressureMin:
0
,
),
);
await
gesture
.
updateWithCustomEvent
(
PointerMoveEvent
(
pointer:
pointerValue
,
position:
textfieldStart
+
const
Offset
(
150.0
,
5.0
),
pressure:
0.5
,
pressureMin:
0
,
pressureMax:
1
));
await
gesture
.
up
();
// The event should fallback to a normal tap and move the cursor.
// Single taps selects the edge of the word.
expect
(
controller
.
selection
,
const
TextSelection
.
collapsed
(
offset:
8
),
);
await
tester
.
pump
();
// Single taps shouldn't trigger the toolbar.
expect
(
find
.
byType
(
CupertinoButton
),
findsNothing
);
});
testWidgets
(
'default TextField debugFillProperties'
,
(
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