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
46f160d5
Unverified
Commit
46f160d5
authored
Jul 30, 2021
by
xubaolin
Committed by
GitHub
Jul 30, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
update the scrollbar (#82687)
parent
bdca3391
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
149 additions
and
42 deletions
+149
-42
scrollbar.dart
packages/flutter/lib/src/widgets/scrollbar.dart
+77
-42
scrollbar_test.dart
packages/flutter/test/widgets/scrollbar_test.dart
+72
-0
No files found.
packages/flutter/lib/src/widgets/scrollbar.dart
View file @
46f160d5
...
@@ -334,16 +334,29 @@ class ScrollbarPainter extends ChangeNotifier implements CustomPainter {
...
@@ -334,16 +334,29 @@ class ScrollbarPainter extends ChangeNotifier implements CustomPainter {
Rect
?
_trackRect
;
Rect
?
_trackRect
;
late
double
_thumbOffset
;
late
double
_thumbOffset
;
/// Update with new [ScrollMetrics].
The scrollbar will show and redraw itself
/// Update with new [ScrollMetrics].
If the metrics change, the scrollbar will
/// based on these new metrics.
///
show and redraw itself
based on these new metrics.
///
///
/// The scrollbar will remain on screen.
/// The scrollbar will remain on screen.
void
update
(
void
update
(
ScrollMetrics
metrics
,
ScrollMetrics
metrics
,
AxisDirection
axisDirection
,
AxisDirection
axisDirection
,
)
{
)
{
if
(
_lastMetrics
!=
null
&&
_lastMetrics
!.
extentBefore
==
metrics
.
extentBefore
&&
_lastMetrics
!.
extentInside
==
metrics
.
extentInside
&&
_lastMetrics
!.
extentAfter
==
metrics
.
extentAfter
&&
_lastAxisDirection
==
axisDirection
)
return
;
final
ScrollMetrics
?
oldMetrics
=
_lastMetrics
;
_lastMetrics
=
metrics
;
_lastMetrics
=
metrics
;
_lastAxisDirection
=
axisDirection
;
_lastAxisDirection
=
axisDirection
;
bool
_needPaint
(
ScrollMetrics
?
metrics
)
=>
metrics
!=
null
&&
metrics
.
maxScrollExtent
>
metrics
.
minScrollExtent
;
if
(!
_needPaint
(
oldMetrics
)
&&
!
_needPaint
(
metrics
))
return
;
notifyListeners
();
notifyListeners
();
}
}
...
@@ -526,7 +539,8 @@ class ScrollbarPainter extends ChangeNotifier implements CustomPainter {
...
@@ -526,7 +539,8 @@ class ScrollbarPainter extends ChangeNotifier implements CustomPainter {
void
paint
(
Canvas
canvas
,
Size
size
)
{
void
paint
(
Canvas
canvas
,
Size
size
)
{
if
(
_lastAxisDirection
==
null
if
(
_lastAxisDirection
==
null
||
_lastMetrics
==
null
||
_lastMetrics
==
null
||
fadeoutOpacityAnimation
.
value
==
0.0
)
||
fadeoutOpacityAnimation
.
value
==
0.0
||
_lastMetrics
!.
maxScrollExtent
<=
_lastMetrics
!.
minScrollExtent
)
return
;
return
;
// Skip painting if there's not enough space.
// Skip painting if there's not enough space.
...
@@ -1519,18 +1533,37 @@ class RawScrollbarState<T extends RawScrollbar> extends State<T> with TickerProv
...
@@ -1519,18 +1533,37 @@ class RawScrollbarState<T extends RawScrollbar> extends State<T> with TickerProv
);
);
}
}
bool
_handleScrollMetricsNotification
(
ScrollMetricsNotification
notification
)
{
if
(!
widget
.
notificationPredicate
(
ScrollUpdateNotification
(
metrics:
notification
.
metrics
,
context:
notification
.
context
)))
return
false
;
if
(
showScrollbar
)
{
if
(
_fadeoutAnimationController
.
status
!=
AnimationStatus
.
forward
&&
_fadeoutAnimationController
.
status
!=
AnimationStatus
.
completed
)
_fadeoutAnimationController
.
forward
();
}
scrollbarPainter
.
update
(
notification
.
metrics
,
notification
.
metrics
.
axisDirection
);
return
false
;
}
bool
_handleScrollNotification
(
ScrollNotification
notification
)
{
bool
_handleScrollNotification
(
ScrollNotification
notification
)
{
if
(!
widget
.
notificationPredicate
(
notification
))
if
(!
widget
.
notificationPredicate
(
notification
))
return
false
;
return
false
;
final
ScrollMetrics
metrics
=
notification
.
metrics
;
final
ScrollMetrics
metrics
=
notification
.
metrics
;
if
(
metrics
.
maxScrollExtent
<=
metrics
.
minScrollExtent
)
if
(
metrics
.
maxScrollExtent
<=
metrics
.
minScrollExtent
)
{
// Hide the bar when the Scrollable widget has no space to scroll.
if
(
_fadeoutAnimationController
.
status
!=
AnimationStatus
.
dismissed
&&
_fadeoutAnimationController
.
status
!=
AnimationStatus
.
reverse
)
_fadeoutAnimationController
.
reverse
();
scrollbarPainter
.
update
(
metrics
,
metrics
.
axisDirection
);
return
false
;
return
false
;
}
if
(
notification
is
ScrollUpdateNotification
||
if
(
notification
is
ScrollUpdateNotification
||
notification
is
OverscrollNotification
)
{
notification
is
OverscrollNotification
)
{
// Any movements always makes the scrollbar start showing up.
// Any movements always makes the scrollbar start showing up.
if
(
_fadeoutAnimationController
.
status
!=
AnimationStatus
.
forward
)
if
(
_fadeoutAnimationController
.
status
!=
AnimationStatus
.
forward
&&
_fadeoutAnimationController
.
status
!=
AnimationStatus
.
completed
)
_fadeoutAnimationController
.
forward
();
_fadeoutAnimationController
.
forward
();
_fadeoutTimer
?.
cancel
();
_fadeoutTimer
?.
cancel
();
...
@@ -1658,47 +1691,49 @@ class RawScrollbarState<T extends RawScrollbar> extends State<T> with TickerProv
...
@@ -1658,47 +1691,49 @@ class RawScrollbarState<T extends RawScrollbar> extends State<T> with TickerProv
super
.
dispose
();
super
.
dispose
();
}
}
@override
@override
Widget
build
(
BuildContext
context
)
{
Widget
build
(
BuildContext
context
)
{
updateScrollbarPainter
();
updateScrollbarPainter
();
return
NotificationListener
<
ScrollNotification
>(
return
NotificationListener
<
ScrollMetricsNotification
>(
onNotification:
_handleScrollNotification
,
onNotification:
_handleScrollMetricsNotification
,
child:
RepaintBoundary
(
child:
NotificationListener
<
ScrollNotification
>(
child:
RawGestureDetector
(
onNotification:
_handleScrollNotification
,
gestures:
_gestures
,
child:
RepaintBoundary
(
child:
MouseRegion
(
child:
RawGestureDetector
(
onExit:
(
PointerExitEvent
event
)
{
gestures:
_gestures
,
switch
(
event
.
kind
)
{
child:
MouseRegion
(
case
PointerDeviceKind
.
mouse
:
onExit:
(
PointerExitEvent
event
)
{
if
(
enableGestures
)
switch
(
event
.
kind
)
{
handleHoverExit
(
event
);
case
PointerDeviceKind
.
mouse
:
break
;
if
(
enableGestures
)
case
PointerDeviceKind
.
stylus
:
handleHoverExit
(
event
);
case
PointerDeviceKind
.
invertedStylus
:
break
;
case
PointerDeviceKind
.
unknown
:
case
PointerDeviceKind
.
stylus
:
case
PointerDeviceKind
.
touch
:
case
PointerDeviceKind
.
invertedStylus
:
break
;
case
PointerDeviceKind
.
unknown
:
}
case
PointerDeviceKind
.
touch
:
},
break
;
onHover:
(
PointerHoverEvent
event
)
{
}
switch
(
event
.
kind
)
{
},
case
PointerDeviceKind
.
mouse
:
onHover:
(
PointerHoverEvent
event
)
{
if
(
enableGestures
)
switch
(
event
.
kind
)
{
handleHover
(
event
);
case
PointerDeviceKind
.
mouse
:
break
;
if
(
enableGestures
)
case
PointerDeviceKind
.
stylus
:
handleHover
(
event
);
case
PointerDeviceKind
.
invertedStylus
:
break
;
case
PointerDeviceKind
.
unknown
:
case
PointerDeviceKind
.
stylus
:
case
PointerDeviceKind
.
touch
:
case
PointerDeviceKind
.
invertedStylus
:
break
;
case
PointerDeviceKind
.
unknown
:
}
case
PointerDeviceKind
.
touch
:
},
break
;
child:
CustomPaint
(
}
key:
_scrollbarPainterKey
,
},
foregroundPainter:
scrollbarPainter
,
child:
CustomPaint
(
child:
RepaintBoundary
(
child:
widget
.
child
),
key:
_scrollbarPainterKey
,
foregroundPainter:
scrollbarPainter
,
child:
RepaintBoundary
(
child:
widget
.
child
),
),
),
),
),
),
),
),
...
...
packages/flutter/test/widgets/scrollbar_test.dart
View file @
46f160d5
...
@@ -1565,4 +1565,76 @@ void main() {
...
@@ -1565,4 +1565,76 @@ void main() {
..
rect
(
rect:
const
Rect
.
fromLTRB
(
794.0
,
0.0
,
800.0
,
8.0
)));
..
rect
(
rect:
const
Rect
.
fromLTRB
(
794.0
,
0.0
,
800.0
,
8.0
)));
});
});
testWidgets
(
'The bar can show or hide when the viewport size change'
,
(
WidgetTester
tester
)
async
{
final
ScrollController
scrollController
=
ScrollController
();
Widget
buildFrame
(
double
height
)
{
return
Directionality
(
textDirection:
TextDirection
.
ltr
,
child:
MediaQuery
(
data:
const
MediaQueryData
(),
child:
RawScrollbar
(
controller:
scrollController
,
isAlwaysShown:
true
,
child:
SingleChildScrollView
(
controller:
scrollController
,
child:
SizedBox
(
width:
double
.
infinity
,
height:
height
)
),
),
),
);
}
await
tester
.
pumpWidget
(
buildFrame
(
600.0
));
await
tester
.
pumpAndSettle
();
expect
(
find
.
byType
(
RawScrollbar
),
isNot
(
paints
..
rect
()));
// Not shown.
await
tester
.
pumpWidget
(
buildFrame
(
600.1
));
await
tester
.
pumpAndSettle
();
expect
(
find
.
byType
(
RawScrollbar
),
paints
..
rect
()..
rect
());
// Show the bar.
await
tester
.
pumpWidget
(
buildFrame
(
600.0
));
await
tester
.
pumpAndSettle
();
expect
(
find
.
byType
(
RawScrollbar
),
isNot
(
paints
..
rect
()));
// Hide the bar.
});
testWidgets
(
'The bar can show or hide when the window size change'
,
(
WidgetTester
tester
)
async
{
final
ScrollController
scrollController
=
ScrollController
();
Widget
buildFrame
()
{
return
Directionality
(
textDirection:
TextDirection
.
ltr
,
child:
MediaQuery
(
data:
const
MediaQueryData
(),
child:
PrimaryScrollController
(
controller:
scrollController
,
child:
RawScrollbar
(
isAlwaysShown:
true
,
controller:
scrollController
,
child:
const
SingleChildScrollView
(
child:
SizedBox
(
width:
double
.
infinity
,
height:
600.0
,
),
),
),
),
),
);
}
tester
.
binding
.
window
.
physicalSizeTestValue
=
const
Size
(
800.0
,
600.0
);
tester
.
binding
.
window
.
devicePixelRatioTestValue
=
1
;
addTearDown
(
tester
.
binding
.
window
.
clearPhysicalSizeTestValue
);
addTearDown
(
tester
.
binding
.
window
.
clearDevicePixelRatioTestValue
);
await
tester
.
pumpWidget
(
buildFrame
());
await
tester
.
pumpAndSettle
();
expect
(
scrollController
.
offset
,
0.0
);
expect
(
find
.
byType
(
RawScrollbar
),
isNot
(
paints
..
rect
()));
// Not shown.
tester
.
binding
.
window
.
physicalSizeTestValue
=
const
Size
(
800.0
,
599.0
);
await
tester
.
pumpAndSettle
();
expect
(
find
.
byType
(
RawScrollbar
),
paints
..
rect
()..
rect
());
// Show the bar.
tester
.
binding
.
window
.
physicalSizeTestValue
=
const
Size
(
800.0
,
600.0
);
await
tester
.
pumpAndSettle
();
expect
(
find
.
byType
(
RawScrollbar
),
isNot
(
paints
..
rect
()));
// Not shown.
});
}
}
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