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
d211f3ff
Unverified
Commit
d211f3ff
authored
Mar 02, 2022
by
Kate Lovett
Committed by
GitHub
Mar 02, 2022
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Limit overscroll stretching (#99364)
parent
4df1c0cf
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
133 additions
and
2 deletions
+133
-2
overscroll_indicator.dart
packages/flutter/lib/src/widgets/overscroll_indicator.dart
+12
-2
overscroll_stretch_indicator_test.dart
...utter/test/widgets/overscroll_stretch_indicator_test.dart
+121
-0
No files found.
packages/flutter/lib/src/widgets/overscroll_indicator.dart
View file @
d211f3ff
...
@@ -707,7 +707,15 @@ class _StretchingOverscrollIndicatorState extends State<StretchingOverscrollIndi
...
@@ -707,7 +707,15 @@ class _StretchingOverscrollIndicatorState extends State<StretchingOverscrollIndi
}
else
{
}
else
{
assert
(
notification
.
overscroll
!=
0.0
);
assert
(
notification
.
overscroll
!=
0.0
);
if
(
notification
.
dragDetails
!=
null
)
{
if
(
notification
.
dragDetails
!=
null
)
{
_stretchController
.
pull
(
notification
.
overscroll
.
abs
()
/
notification
.
metrics
.
viewportDimension
);
// We clamp the overscroll amount relative to the length of the viewport,
// which is the furthest distance a single pointer could pull on the
// screen. This is because more than one pointer will multiply the
// amount of overscroll - https://github.com/flutter/flutter/issues/11884
final
double
viewportDimension
=
notification
.
metrics
.
viewportDimension
;
final
double
distanceForPull
=
(
notification
.
overscroll
.
abs
()
/
viewportDimension
)
+
_stretchController
.
pullDistance
;
final
double
clampedOverscroll
=
distanceForPull
.
clamp
(
0
,
1.0
);
_stretchController
.
pull
(
clampedOverscroll
);
}
}
}
}
}
}
...
@@ -818,6 +826,8 @@ class _StretchController extends ChangeNotifier {
...
@@ -818,6 +826,8 @@ class _StretchController extends ChangeNotifier {
late
final
Animation
<
double
>
_stretchSize
;
late
final
Animation
<
double
>
_stretchSize
;
final
Tween
<
double
>
_stretchSizeTween
=
Tween
<
double
>(
begin:
0.0
,
end:
0.0
);
final
Tween
<
double
>
_stretchSizeTween
=
Tween
<
double
>(
begin:
0.0
,
end:
0.0
);
_StretchState
_state
=
_StretchState
.
idle
;
_StretchState
_state
=
_StretchState
.
idle
;
double
get
pullDistance
=>
_pullDistance
;
double
_pullDistance
=
0.0
;
double
_pullDistance
=
0.0
;
// Constants from Android.
// Constants from Android.
...
@@ -848,7 +858,7 @@ class _StretchController extends ChangeNotifier {
...
@@ -848,7 +858,7 @@ class _StretchController extends ChangeNotifier {
/// in the main axis.
/// in the main axis.
void
pull
(
double
normalizedOverscroll
)
{
void
pull
(
double
normalizedOverscroll
)
{
assert
(
normalizedOverscroll
>=
0.0
);
assert
(
normalizedOverscroll
>=
0.0
);
_pullDistance
=
normalizedOverscroll
+
_pullDistance
;
_pullDistance
=
normalizedOverscroll
;
_stretchSizeTween
.
begin
=
_stretchSize
.
value
;
_stretchSizeTween
.
begin
=
_stretchSize
.
value
;
final
double
linearIntensity
=
_stretchIntensity
*
_pullDistance
;
final
double
linearIntensity
=
_stretchIntensity
*
_pullDistance
;
final
double
exponentialIntensity
=
_stretchIntensity
*
(
1
-
math
.
exp
(-
_pullDistance
*
_exponentialScalar
));
final
double
exponentialIntensity
=
_stretchIntensity
*
(
1
-
math
.
exp
(-
_pullDistance
*
_exponentialScalar
));
...
...
packages/flutter/test/widgets/overscroll_stretch_indicator_test.dart
View file @
d211f3ff
...
@@ -451,4 +451,125 @@ void main() {
...
@@ -451,4 +451,125 @@ void main() {
await
gesture
.
up
();
await
gesture
.
up
();
await
tester
.
pumpAndSettle
();
await
tester
.
pumpAndSettle
();
});
});
testWidgets
(
'Stretch limit'
,
(
WidgetTester
tester
)
async
{
// Regression test for https://github.com/flutter/flutter/issues/99264
await
tester
.
pumpWidget
(
Directionality
(
textDirection:
TextDirection
.
ltr
,
child:
MediaQuery
(
data:
const
MediaQueryData
(),
child:
ScrollConfiguration
(
behavior:
const
ScrollBehavior
().
copyWith
(
overscroll:
false
),
child:
StretchingOverscrollIndicator
(
axisDirection:
AxisDirection
.
down
,
child:
SizedBox
(
height:
300
,
child:
ListView
.
builder
(
itemCount:
20
,
itemBuilder:
(
BuildContext
context
,
int
index
){
return
Padding
(
padding:
const
EdgeInsets
.
all
(
10.0
),
child:
Text
(
'Index
$index
'
),
);
},
),
),
),
),
)
)
);
const
double
maxStretchLocation
=
52.63178407049861
;
expect
(
find
.
text
(
'Index 1'
),
findsOneWidget
);
expect
(
tester
.
getCenter
(
find
.
text
(
'Index 1'
)).
dy
,
51.0
);
TestGesture
pointer
=
await
tester
.
startGesture
(
tester
.
getCenter
(
find
.
text
(
'Index 1'
)));
// Overscroll beyond the limit (the viewport is 600.0).
await
pointer
.
moveBy
(
const
Offset
(
0.0
,
610.0
));
await
tester
.
pumpAndSettle
();
expect
(
find
.
text
(
'Index 1'
),
findsOneWidget
);
expect
(
tester
.
getCenter
(
find
.
text
(
'Index 1'
)).
dy
,
maxStretchLocation
);
pointer
=
await
tester
.
startGesture
(
tester
.
getCenter
(
find
.
text
(
'Index 1'
)));
// Overscroll way way beyond the limit
await
pointer
.
moveBy
(
const
Offset
(
0.0
,
1000.0
));
await
tester
.
pumpAndSettle
();
expect
(
find
.
text
(
'Index 1'
),
findsOneWidget
);
expect
(
tester
.
getCenter
(
find
.
text
(
'Index 1'
)).
dy
,
maxStretchLocation
);
await
pointer
.
up
();
await
tester
.
pumpAndSettle
();
});
testWidgets
(
'Multiple pointers wll not exceed stretch limit'
,
(
WidgetTester
tester
)
async
{
// Regression test for https://github.com/flutter/flutter/issues/99264
await
tester
.
pumpWidget
(
Directionality
(
textDirection:
TextDirection
.
ltr
,
child:
MediaQuery
(
data:
const
MediaQueryData
(),
child:
ScrollConfiguration
(
behavior:
const
ScrollBehavior
().
copyWith
(
overscroll:
false
),
child:
StretchingOverscrollIndicator
(
axisDirection:
AxisDirection
.
down
,
child:
SizedBox
(
height:
300
,
child:
ListView
.
builder
(
itemCount:
20
,
itemBuilder:
(
BuildContext
context
,
int
index
){
return
Padding
(
padding:
const
EdgeInsets
.
all
(
10.0
),
child:
Text
(
'Index
$index
'
),
);
},
),
),
),
),
)
)
);
expect
(
find
.
text
(
'Index 1'
),
findsOneWidget
);
expect
(
tester
.
getCenter
(
find
.
text
(
'Index 1'
)).
dy
,
51.0
);
final
TestGesture
pointer1
=
await
tester
.
startGesture
(
tester
.
getCenter
(
find
.
text
(
'Index 1'
)));
// Overscroll the start.
await
pointer1
.
moveBy
(
const
Offset
(
0.0
,
210.0
));
await
tester
.
pumpAndSettle
();
expect
(
find
.
text
(
'Index 1'
),
findsOneWidget
);
double
lastStretchedLocation
=
tester
.
getCenter
(
find
.
text
(
'Index 1'
)).
dy
;
expect
(
lastStretchedLocation
,
greaterThan
(
51.0
));
final
TestGesture
pointer2
=
await
tester
.
startGesture
(
tester
.
getCenter
(
find
.
text
(
'Index 1'
)));
// Add overscroll from an additional pointer
await
pointer2
.
moveBy
(
const
Offset
(
0.0
,
210.0
));
await
tester
.
pumpAndSettle
();
expect
(
find
.
text
(
'Index 1'
),
findsOneWidget
);
expect
(
tester
.
getCenter
(
find
.
text
(
'Index 1'
)).
dy
,
greaterThan
(
lastStretchedLocation
));
lastStretchedLocation
=
tester
.
getCenter
(
find
.
text
(
'Index 1'
)).
dy
;
final
TestGesture
pointer3
=
await
tester
.
startGesture
(
tester
.
getCenter
(
find
.
text
(
'Index 1'
)));
// Add overscroll from an additional pointer, exceeding the max stretch (600)
await
pointer3
.
moveBy
(
const
Offset
(
0.0
,
210.0
));
await
tester
.
pumpAndSettle
();
expect
(
find
.
text
(
'Index 1'
),
findsOneWidget
);
expect
(
tester
.
getCenter
(
find
.
text
(
'Index 1'
)).
dy
,
greaterThan
(
lastStretchedLocation
));
lastStretchedLocation
=
tester
.
getCenter
(
find
.
text
(
'Index 1'
)).
dy
;
final
TestGesture
pointer4
=
await
tester
.
startGesture
(
tester
.
getCenter
(
find
.
text
(
'Index 1'
)));
// Since we have maxed out the overscroll, it should not have stretched
// further, regardless of the number of pointers.
await
pointer4
.
moveBy
(
const
Offset
(
0.0
,
210.0
));
await
tester
.
pumpAndSettle
();
expect
(
find
.
text
(
'Index 1'
),
findsOneWidget
);
expect
(
tester
.
getCenter
(
find
.
text
(
'Index 1'
)).
dy
,
lastStretchedLocation
);
await
pointer1
.
up
();
await
pointer2
.
up
();
await
pointer3
.
up
();
await
pointer4
.
up
();
await
tester
.
pumpAndSettle
();
});
}
}
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