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
63e328f7
Unverified
Commit
63e328f7
authored
Nov 21, 2020
by
Kate Lovett
Committed by
GitHub
Nov 21, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fix pointer scroll for nested NeverScrollables (#70953)
parent
97466192
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
78 additions
and
12 deletions
+78
-12
scrollable.dart
packages/flutter/lib/src/widgets/scrollable.dart
+20
-12
scrollable_test.dart
packages/flutter/test/widgets/scrollable_test.dart
+58
-0
No files found.
packages/flutter/lib/src/widgets/scrollable.dart
View file @
63e328f7
...
@@ -3,6 +3,7 @@
...
@@ -3,6 +3,7 @@
// found in the LICENSE file.
// found in the LICENSE file.
import
'dart:async'
;
import
'dart:async'
;
import
'dart:math'
as
math
;
import
'dart:ui'
;
import
'dart:ui'
;
import
'package:flutter/gestures.dart'
;
import
'package:flutter/gestures.dart'
;
...
@@ -628,25 +629,35 @@ class ScrollableState extends State<Scrollable> with TickerProviderStateMixin, R
...
@@ -628,25 +629,35 @@ class ScrollableState extends State<Scrollable> with TickerProviderStateMixin, R
// SCROLL WHEEL
// SCROLL WHEEL
// Returns the offset that should result from applying [event] to the current
// position, taking min/max scroll extent into account.
double
_targetScrollOffsetForPointerScroll
(
PointerScrollEvent
event
)
{
final
double
delta
=
_pointerSignalEventDelta
(
event
);
return
math
.
min
(
math
.
max
(
position
.
pixels
+
delta
,
position
.
minScrollExtent
),
position
.
maxScrollExtent
);
}
// Returns the delta that should result from applying [event] with axis and
// Returns the delta that should result from applying [event] with axis and
// direction taken into account.
// direction taken into account.
double
_
targetScrollDeltaForPointerScroll
(
PointerScrollEvent
event
)
{
double
_
pointerSignalEventDelta
(
PointerScrollEvent
event
)
{
double
delta
=
widget
.
axis
==
Axis
.
horizontal
double
delta
=
widget
.
axis
==
Axis
.
horizontal
?
event
.
scrollDelta
.
dx
?
event
.
scrollDelta
.
dx
:
event
.
scrollDelta
.
dy
;
:
event
.
scrollDelta
.
dy
;
if
(
axisDirectionIsReversed
(
widget
.
axisDirection
))
{
if
(
axisDirectionIsReversed
(
widget
.
axisDirection
))
{
delta
*=
-
1
;
delta
*=
-
1
;
}
}
return
delta
;
return
delta
;
}
}
void
_receivedPointerSignal
(
PointerSignalEvent
event
)
{
void
_receivedPointerSignal
(
PointerSignalEvent
event
)
{
if
(
event
is
PointerScrollEvent
&&
_position
!=
null
)
{
if
(
event
is
PointerScrollEvent
&&
_position
!=
null
)
{
final
double
targetScrollOffset
=
_targetScrollDeltaForPointerScroll
(
event
);
if
(
_physics
!=
null
&&
!
_physics
!.
shouldAcceptUserOffset
(
position
))
{
return
;
}
final
double
targetScrollOffset
=
_targetScrollOffsetForPointerScroll
(
event
);
// Only express interest in the event if it would actually result in a scroll.
// Only express interest in the event if it would actually result in a scroll.
if
(
targetScrollOffset
!=
0
)
{
if
(
targetScrollOffset
!=
position
.
pixels
)
{
GestureBinding
.
instance
!.
pointerSignalResolver
.
register
(
event
,
_handlePointerScroll
);
GestureBinding
.
instance
!.
pointerSignalResolver
.
register
(
event
,
_handlePointerScroll
);
}
}
}
}
...
@@ -654,12 +665,9 @@ class ScrollableState extends State<Scrollable> with TickerProviderStateMixin, R
...
@@ -654,12 +665,9 @@ class ScrollableState extends State<Scrollable> with TickerProviderStateMixin, R
void
_handlePointerScroll
(
PointerEvent
event
)
{
void
_handlePointerScroll
(
PointerEvent
event
)
{
assert
(
event
is
PointerScrollEvent
);
assert
(
event
is
PointerScrollEvent
);
if
(
_physics
!=
null
&&
!
_physics
!.
shouldAcceptUserOffset
(
position
))
{
final
double
targetScrollOffset
=
_targetScrollOffsetForPointerScroll
(
event
as
PointerScrollEvent
);
return
;
if
(
targetScrollOffset
!=
position
.
pixels
)
{
}
position
.
pointerScroll
(
_pointerSignalEventDelta
(
event
));
final
double
targetScrollOffset
=
_targetScrollDeltaForPointerScroll
(
event
as
PointerScrollEvent
);
if
(
targetScrollOffset
!=
0
)
{
position
.
pointerScroll
(
targetScrollOffset
);
}
}
}
}
...
...
packages/flutter/test/widgets/scrollable_test.dart
View file @
63e328f7
...
@@ -1148,6 +1148,64 @@ void main() {
...
@@ -1148,6 +1148,64 @@ void main() {
expect
(
targetMidRightPage1
,
findsOneWidget
);
expect
(
targetMidRightPage1
,
findsOneWidget
);
expect
(
targetMidLeftPage1
,
findsOneWidget
);
expect
(
targetMidLeftPage1
,
findsOneWidget
);
});
});
testWidgets
(
'PointerScroll on nested NeverScrollable ListView goes to outer Scrollable.'
,
(
WidgetTester
tester
)
async
{
// Regression test for https://github.com/flutter/flutter/issues/70948
final
ScrollController
outerController
=
ScrollController
();
final
ScrollController
innerController
=
ScrollController
();
await
tester
.
pumpWidget
(
MaterialApp
(
home:
Scaffold
(
body:
SingleChildScrollView
(
controller:
outerController
,
child:
Container
(
child:
Row
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
mainAxisAlignment:
MainAxisAlignment
.
start
,
children:
<
Widget
>[
Column
(
children:
<
Widget
>[
for
(
int
i
=
0
;
i
<
100
;
i
++)
Text
(
'SingleChildScrollView
$i
'
),
]
),
Container
(
height:
3000
,
width:
400
,
child:
ListView
.
builder
(
controller:
innerController
,
physics:
const
NeverScrollableScrollPhysics
(),
itemCount:
100
,
itemBuilder:
(
BuildContext
context
,
int
index
)
{
return
Text
(
'Nested NeverScrollable ListView
$index
'
);
},
)
),
]
)
)
)
),
));
expect
(
outerController
.
position
.
pixels
,
0.0
);
expect
(
innerController
.
position
.
pixels
,
0.0
);
final
Offset
outerScrollable
=
tester
.
getCenter
(
find
.
text
(
'SingleChildScrollView 3'
));
final
TestPointer
testPointer
=
TestPointer
(
1
,
ui
.
PointerDeviceKind
.
mouse
);
// Hover over the outer scroll view and create a pointer scroll.
testPointer
.
hover
(
outerScrollable
);
await
tester
.
sendEventToBinding
(
testPointer
.
scroll
(
const
Offset
(
0.0
,
20.0
)));
await
tester
.
pump
(
const
Duration
(
milliseconds:
250
));
expect
(
outerController
.
position
.
pixels
,
20.0
);
expect
(
innerController
.
position
.
pixels
,
0.0
);
final
Offset
innerScrollable
=
tester
.
getCenter
(
find
.
text
(
'Nested NeverScrollable ListView 20'
));
// Hover over the inner scroll view and create a pointer scroll.
// This inner scroll view is not scrollable, and so the outer should scroll.
testPointer
.
hover
(
innerScrollable
);
await
tester
.
sendEventToBinding
(
testPointer
.
scroll
(
const
Offset
(
0.0
,
-
20.0
)));
await
tester
.
pump
(
const
Duration
(
milliseconds:
250
));
expect
(
outerController
.
position
.
pixels
,
0.0
);
expect
(
innerController
.
position
.
pixels
,
0.0
);
});
}
}
// ignore: must_be_immutable
// ignore: must_be_immutable
...
...
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