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
c0e748fb
Unverified
Commit
c0e748fb
authored
Mar 09, 2023
by
xubaolin
Committed by
GitHub
Mar 09, 2023
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fix a scroll bar stutter bug (#121786)
Fix a scrolling stutter caused by dragging scrollbar
parent
a5061bf9
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
85 additions
and
9 deletions
+85
-9
scrollbar.dart
packages/flutter/lib/src/widgets/scrollbar.dart
+21
-8
scrollbar_test.dart
packages/flutter/test/widgets/scrollbar_test.dart
+64
-1
No files found.
packages/flutter/lib/src/widgets/scrollbar.dart
View file @
c0e748fb
...
...
@@ -1676,29 +1676,41 @@ class RawScrollbarState<T extends RawScrollbar> extends State<T> with TickerProv
void
_updateScrollPosition
(
Offset
updatedOffset
)
{
assert
(
_cachedController
!=
null
);
assert
(
_startDragScrollbarAxisOffset
!=
null
);
assert
(
_lastDragUpdateOffset
!=
null
);
assert
(
_startDragThumbOffset
!=
null
);
final
ScrollPosition
position
=
_cachedController
!.
position
;
late
double
primaryDelta
;
late
double
primaryDeltaFromDragStart
;
late
double
primaryDeltaFromLastDragUpdate
;
switch
(
position
.
axisDirection
)
{
case
AxisDirection
.
up
:
primaryDelta
=
_startDragScrollbarAxisOffset
!.
dy
-
updatedOffset
.
dy
;
primaryDeltaFromDragStart
=
_startDragScrollbarAxisOffset
!.
dy
-
updatedOffset
.
dy
;
primaryDeltaFromLastDragUpdate
=
_lastDragUpdateOffset
!.
dy
-
updatedOffset
.
dy
;
break
;
case
AxisDirection
.
right
:
primaryDelta
=
updatedOffset
.
dx
-
_startDragScrollbarAxisOffset
!.
dx
;
primaryDeltaFromDragStart
=
updatedOffset
.
dx
-
_startDragScrollbarAxisOffset
!.
dx
;
primaryDeltaFromLastDragUpdate
=
updatedOffset
.
dx
-
_lastDragUpdateOffset
!.
dx
;
break
;
case
AxisDirection
.
down
:
primaryDelta
=
updatedOffset
.
dy
-
_startDragScrollbarAxisOffset
!.
dy
;
primaryDeltaFromDragStart
=
updatedOffset
.
dy
-
_startDragScrollbarAxisOffset
!.
dy
;
primaryDeltaFromLastDragUpdate
=
updatedOffset
.
dy
-
_lastDragUpdateOffset
!.
dy
;
break
;
case
AxisDirection
.
left
:
primaryDelta
=
_startDragScrollbarAxisOffset
!.
dx
-
updatedOffset
.
dx
;
primaryDeltaFromDragStart
=
_startDragScrollbarAxisOffset
!.
dx
-
updatedOffset
.
dx
;
primaryDeltaFromLastDragUpdate
=
_lastDragUpdateOffset
!.
dx
-
updatedOffset
.
dx
;
break
;
}
// Convert primaryDelta, the amount that the scrollbar moved since the last
// time when drag started, into the coordinate space of the scroll
// time when drag started
or last updated
, into the coordinate space of the scroll
// position, and jump to that position.
final
double
scrollOffsetGlobal
=
scrollbarPainter
.
getTrackToScroll
(
primaryDelta
+
_startDragThumbOffset
!);
double
scrollOffsetGlobal
=
scrollbarPainter
.
getTrackToScroll
(
primaryDeltaFromDragStart
+
_startDragThumbOffset
!);
if
(
primaryDeltaFromDragStart
>
0
&&
scrollOffsetGlobal
<
position
.
pixels
||
primaryDeltaFromDragStart
<
0
&&
scrollOffsetGlobal
>
position
.
pixels
)
{
// Adjust the position value if the scrolling direction conflicts with
// the dragging direction due to scroll metrics shrink.
scrollOffsetGlobal
=
position
.
pixels
+
scrollbarPainter
.
getTrackToScroll
(
primaryDeltaFromLastDragUpdate
);
}
if
(
scrollOffsetGlobal
!=
position
.
pixels
)
{
// Ensure we don't drag into overscroll if the physics do not allow it.
final
double
physicsAdjustment
=
position
.
physics
.
applyBoundaryConditions
(
position
,
scrollOffsetGlobal
);
...
...
@@ -1772,6 +1784,7 @@ class RawScrollbarState<T extends RawScrollbar> extends State<T> with TickerProv
_fadeoutTimer
?.
cancel
();
_fadeoutAnimationController
.
forward
();
_startDragScrollbarAxisOffset
=
localPosition
;
_lastDragUpdateOffset
=
localPosition
;
_startDragThumbOffset
=
scrollbarPainter
.
getThumbScrollOffset
();
_thumbDragging
=
true
;
}
...
...
@@ -1786,7 +1799,6 @@ class RawScrollbarState<T extends RawScrollbar> extends State<T> with TickerProv
if
(
_lastDragUpdateOffset
==
localPosition
)
{
return
;
}
_lastDragUpdateOffset
=
localPosition
;
final
ScrollPosition
position
=
_cachedController
!.
position
;
if
(!
position
.
physics
.
shouldAcceptUserOffset
(
position
))
{
return
;
...
...
@@ -1796,6 +1808,7 @@ class RawScrollbarState<T extends RawScrollbar> extends State<T> with TickerProv
return
;
}
_updateScrollPosition
(
localPosition
);
_lastDragUpdateOffset
=
localPosition
;
}
/// Handler called when a long press has ended.
...
...
packages/flutter/test/widgets/scrollbar_test.dart
View file @
c0e748fb
...
...
@@ -2740,7 +2740,6 @@ void main() {
controller:
scrollController
,
child:
CustomScrollView
(
controller:
scrollController
,
// cacheExtent: double.maxFinite,
slivers:
<
Widget
>[
SliverList
(
delegate:
SliverChildBuilderDelegate
(
...
...
@@ -2796,6 +2795,70 @@ void main() {
);
});
testWidgets
(
'The scrollable should not stutter when the scroll metrics shrink during dragging'
,
(
WidgetTester
tester
)
async
{
// Regressing test for https://github.com/flutter/flutter/issues/121574
final
ScrollController
scrollController
=
ScrollController
();
await
tester
.
pumpWidget
(
Directionality
(
textDirection:
TextDirection
.
ltr
,
child:
MediaQuery
(
data:
const
MediaQueryData
(),
child:
PrimaryScrollController
(
controller:
scrollController
,
child:
RawScrollbar
(
isAlwaysShown:
true
,
controller:
scrollController
,
child:
CustomScrollView
(
controller:
scrollController
,
slivers:
<
Widget
>[
SliverList
(
delegate:
SliverChildBuilderDelegate
(
(
BuildContext
context
,
int
index
)
{
final
double
height
;
if
(
index
<
10
)
{
height
=
500
;
}
else
{
height
=
100
;
}
return
SizedBox
(
height:
height
,
child:
Text
(
'
$index
'
),
);
},
childCount:
100
,
),
),
],
),
),
),
),
),
);
await
tester
.
pumpAndSettle
();
expect
(
scrollController
.
offset
,
0.0
);
// Drag the thumb down to scroll down.
const
double
scrollAmount
=
100
;
final
TestGesture
dragScrollbarGesture
=
await
tester
.
startGesture
(
const
Offset
(
797.0
,
5.0
));
await
tester
.
pumpAndSettle
();
await
dragScrollbarGesture
.
moveBy
(
const
Offset
(
0.0
,
scrollAmount
));
await
tester
.
pumpAndSettle
();
final
double
lastPosition
=
scrollController
.
offset
;
// The view has scrolled more than it would have by a swipe gesture of the
// same distance.
expect
(
lastPosition
,
greaterThan
((
100.0
*
10
+
500.0
*
90
)
/
6
));
await
dragScrollbarGesture
.
moveBy
(
const
Offset
(
0.0
,
scrollAmount
));
await
tester
.
pumpAndSettle
();
await
dragScrollbarGesture
.
up
();
await
tester
.
pumpAndSettle
();
expect
(
scrollController
.
offset
,
greaterThan
(
lastPosition
));
});
testWidgets
(
'The bar support mouse wheel event'
,
(
WidgetTester
tester
)
async
{
// Regression test for https://github.com/flutter/flutter/pull/109659
final
ScrollController
scrollController
=
ScrollController
();
...
...
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