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
b86fa132
Unverified
Commit
b86fa132
authored
Oct 27, 2020
by
Kate Lovett
Committed by
GitHub
Oct 27, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add horizontal gesture support for CupertinoScrollbar (#69063)
parent
d3a8b035
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
140 additions
and
30 deletions
+140
-30
scrollbar.dart
packages/flutter/lib/src/cupertino/scrollbar.dart
+67
-30
scrollbar_test.dart
packages/flutter/test/cupertino/scrollbar_test.dart
+73
-0
No files found.
packages/flutter/lib/src/cupertino/scrollbar.dart
View file @
b86fa132
...
...
@@ -241,7 +241,7 @@ class _CupertinoScrollbarState extends State<CupertinoScrollbar> with TickerProv
late
Animation
<
double
>
_fadeoutOpacityAnimation
;
late
AnimationController
_thicknessAnimationController
;
Timer
?
_fadeoutTimer
;
double
?
_dragScrollbar
PositionY
;
double
?
_dragScrollbar
AxisPosition
;
Drag
?
_drag
;
double
get
_thickness
{
...
...
@@ -342,18 +342,25 @@ class _CupertinoScrollbarState extends State<CupertinoScrollbar> with TickerProv
// position, and create/update the drag event with that position.
final
double
scrollOffsetLocal
=
_painter
!.
getTrackToScroll
(
primaryDelta
);
final
double
scrollOffsetGlobal
=
scrollOffsetLocal
+
_currentController
!.
position
.
pixels
;
final
Axis
direction
=
_currentController
!.
position
.
axis
;
if
(
_drag
==
null
)
{
_drag
=
_currentController
!.
position
.
drag
(
DragStartDetails
(
globalPosition:
Offset
(
0.0
,
scrollOffsetGlobal
),
globalPosition:
direction
==
Axis
.
vertical
?
Offset
(
0.0
,
scrollOffsetGlobal
)
:
Offset
(
scrollOffsetGlobal
,
0.0
),
),
()
{},
);
}
else
{
_drag
!.
update
(
DragUpdateDetails
(
globalPosition:
Offset
(
0.0
,
scrollOffsetGlobal
),
delta:
Offset
(
0.0
,
-
scrollOffsetLocal
),
globalPosition:
direction
==
Axis
.
vertical
?
Offset
(
0.0
,
scrollOffsetGlobal
)
:
Offset
(
scrollOffsetGlobal
,
0.0
),
delta:
direction
==
Axis
.
vertical
?
Offset
(
0.0
,
-
scrollOffsetLocal
)
:
Offset
(-
scrollOffsetLocal
,
0.0
),
primaryDelta:
-
scrollOffsetLocal
,
));
}
...
...
@@ -369,33 +376,43 @@ class _CupertinoScrollbarState extends State<CupertinoScrollbar> with TickerProv
}
}
bool
_checkVertical
()
{
Axis
?
_getDirection
()
{
try
{
return
_currentController
!.
position
.
axis
==
Axis
.
vertical
;
return
_currentController
!.
position
.
axis
;
}
catch
(
_
)
{
// Ignore the gesture if we cannot determine the direction.
return
false
;
return
null
;
}
}
double
_pressStart
Y
=
0.0
;
double
_pressStart
AxisPosition
=
0.0
;
// Long press event callbacks handle the gesture where the user long presses
// on the scrollbar thumb and then drags the scrollbar without releasing.
void
_handleLongPressStart
(
LongPressStartDetails
details
)
{
_currentController
=
_controller
;
if
(!
_checkVertical
())
{
final
Axis
?
direction
=
_getDirection
();
if
(
direction
==
null
)
{
return
;
}
_pressStartY
=
details
.
localPosition
.
dy
;
_fadeoutTimer
?.
cancel
();
_fadeoutAnimationController
.
forward
();
_dragScrollbar
(
details
.
localPosition
.
dy
);
_dragScrollbarPositionY
=
details
.
localPosition
.
dy
;
switch
(
direction
)
{
case
Axis
.
vertical
:
_pressStartAxisPosition
=
details
.
localPosition
.
dy
;
_dragScrollbar
(
details
.
localPosition
.
dy
);
_dragScrollbarAxisPosition
=
details
.
localPosition
.
dy
;
break
;
case
Axis
.
horizontal
:
_pressStartAxisPosition
=
details
.
localPosition
.
dx
;
_dragScrollbar
(
details
.
localPosition
.
dx
);
_dragScrollbarAxisPosition
=
details
.
localPosition
.
dx
;
break
;
}
}
void
_handleLongPress
()
{
if
(
!
_checkVertical
()
)
{
if
(
_getDirection
()
==
null
)
{
return
;
}
_fadeoutTimer
?.
cancel
();
...
...
@@ -405,37 +422,57 @@ class _CupertinoScrollbarState extends State<CupertinoScrollbar> with TickerProv
}
void
_handleLongPressMoveUpdate
(
LongPressMoveUpdateDetails
details
)
{
if
(!
_checkVertical
())
{
final
Axis
?
direction
=
_getDirection
();
if
(
direction
==
null
)
{
return
;
}
_dragScrollbar
(
details
.
localPosition
.
dy
-
_dragScrollbarPositionY
!);
_dragScrollbarPositionY
=
details
.
localPosition
.
dy
;
switch
(
direction
)
{
case
Axis
.
vertical
:
_dragScrollbar
(
details
.
localPosition
.
dy
-
_dragScrollbarAxisPosition
!);
_dragScrollbarAxisPosition
=
details
.
localPosition
.
dy
;
break
;
case
Axis
.
horizontal
:
_dragScrollbar
(
details
.
localPosition
.
dx
-
_dragScrollbarAxisPosition
!);
_dragScrollbarAxisPosition
=
details
.
localPosition
.
dx
;
break
;
}
}
void
_handleLongPressEnd
(
LongPressEndDetails
details
)
{
if
(!
_checkVertical
())
{
final
Axis
?
direction
=
_getDirection
();
if
(
direction
==
null
)
{
return
;
}
_handleDragScrollEnd
(
details
.
velocity
.
pixelsPerSecond
.
dy
);
if
(
details
.
velocity
.
pixelsPerSecond
.
dy
.
abs
()
<
10
&&
(
details
.
localPosition
.
dy
-
_pressStartY
).
abs
()
>
0
)
{
HapticFeedback
.
mediumImpact
();
switch
(
direction
)
{
case
Axis
.
vertical
:
_handleDragScrollEnd
(
details
.
velocity
.
pixelsPerSecond
.
dy
,
direction
);
if
(
details
.
velocity
.
pixelsPerSecond
.
dy
.
abs
()
<
10
&&
(
details
.
localPosition
.
dy
-
_pressStartAxisPosition
).
abs
()
>
0
)
{
HapticFeedback
.
mediumImpact
();
}
break
;
case
Axis
.
horizontal
:
_handleDragScrollEnd
(
details
.
velocity
.
pixelsPerSecond
.
dx
,
direction
);
if
(
details
.
velocity
.
pixelsPerSecond
.
dx
.
abs
()
<
10
&&
(
details
.
localPosition
.
dx
-
_pressStartAxisPosition
).
abs
()
>
0
)
{
HapticFeedback
.
mediumImpact
();
}
break
;
}
_currentController
=
null
;
}
void
_handleDragScrollEnd
(
double
trackVelocity
Y
)
{
void
_handleDragScrollEnd
(
double
trackVelocity
,
Axis
direction
)
{
_startFadeoutTimer
();
_thicknessAnimationController
.
reverse
();
_dragScrollbar
PositionY
=
null
;
final
double
scrollVelocity
Y
=
_painter
!.
getTrackToScroll
(
trackVelocityY
);
_dragScrollbar
AxisPosition
=
null
;
final
double
scrollVelocity
=
_painter
!.
getTrackToScroll
(
trackVelocity
);
_drag
?.
end
(
DragEndDetails
(
primaryVelocity:
-
scrollVelocity
Y
,
primaryVelocity:
-
scrollVelocity
,
velocity:
Velocity
(
pixelsPerSecond:
Offset
(
0.0
,
-
scrollVelocityY
,
),
pixelsPerSecond:
direction
==
Axis
.
vertical
?
Offset
(
0.0
,
-
scrollVelocity
)
:
Offset
(-
scrollVelocity
,
0.0
),
),
));
_drag
=
null
;
...
...
@@ -458,7 +495,7 @@ class _CupertinoScrollbarState extends State<CupertinoScrollbar> with TickerProv
_painter
!.
update
(
notification
.
metrics
,
notification
.
metrics
.
axisDirection
);
}
else
if
(
notification
is
ScrollEndNotification
)
{
// On iOS, the scrollbar can only go away once the user lifted the finger.
if
(
_dragScrollbar
PositionY
==
null
)
{
if
(
_dragScrollbar
AxisPosition
==
null
)
{
_startFadeoutTimer
();
}
}
...
...
packages/flutter/test/cupertino/scrollbar_test.dart
View file @
b86fa132
...
...
@@ -607,4 +607,77 @@ void main() {
await
tester
.
pumpAndSettle
();
expect
(
find
.
byType
(
CupertinoScrollbar
),
isNot
(
paints
..
rrect
()));
});
testWidgets
(
'Scrollbar thumb can be dragged with long press - horizontal axis'
,
(
WidgetTester
tester
)
async
{
final
ScrollController
scrollController
=
ScrollController
();
await
tester
.
pumpWidget
(
Directionality
(
textDirection:
TextDirection
.
ltr
,
child:
MediaQuery
(
data:
const
MediaQueryData
(),
child:
CupertinoScrollbar
(
controller:
scrollController
,
child:
SingleChildScrollView
(
controller:
scrollController
,
scrollDirection:
Axis
.
horizontal
,
child:
const
SizedBox
(
width:
4000.0
,
height:
4000.0
),
),
),
),
),
);
expect
(
scrollController
.
offset
,
0.0
);
// Scroll a bit.
const
double
scrollAmount
=
10.0
;
final
TestGesture
scrollGesture
=
await
tester
.
startGesture
(
tester
.
getCenter
(
find
.
byType
(
SingleChildScrollView
)));
// Scroll right by swiping left.
await
scrollGesture
.
moveBy
(
const
Offset
(-
scrollAmount
,
0.0
));
await
tester
.
pump
();
await
tester
.
pump
(
const
Duration
(
milliseconds:
500
));
// Scrollbar thumb is fully showing and scroll offset has moved by
// scrollAmount.
expect
(
find
.
byType
(
CupertinoScrollbar
),
paints
..
rrect
(
color:
_kScrollbarColor
.
color
,
));
expect
(
scrollController
.
offset
,
scrollAmount
);
await
scrollGesture
.
up
();
await
tester
.
pump
();
int
hapticFeedbackCalls
=
0
;
SystemChannels
.
platform
.
setMockMethodCallHandler
((
MethodCall
methodCall
)
async
{
if
(
methodCall
.
method
==
'HapticFeedback.vibrate'
)
{
hapticFeedbackCalls
++;
}
});
// Long press on the scrollbar thumb and expect a vibration after it resizes.
expect
(
hapticFeedbackCalls
,
0
);
final
TestGesture
dragScrollbarGesture
=
await
tester
.
startGesture
(
const
Offset
(
50.0
,
596.0
));
await
tester
.
pump
(
_kLongPressDuration
);
expect
(
hapticFeedbackCalls
,
0
);
await
tester
.
pump
(
_kScrollbarResizeDuration
);
// Allow the haptic feedback some slack.
await
tester
.
pump
(
const
Duration
(
milliseconds:
1
));
expect
(
hapticFeedbackCalls
,
1
);
// Drag the thumb down to scroll back to the left.
await
dragScrollbarGesture
.
moveBy
(
const
Offset
(
scrollAmount
,
0.0
));
await
tester
.
pump
(
const
Duration
(
milliseconds:
100
));
await
dragScrollbarGesture
.
up
();
await
tester
.
pumpAndSettle
();
// The view has scrolled more than it would have by a swipe gesture of the
// same distance.
expect
(
scrollController
.
offset
,
greaterThan
(
scrollAmount
*
2
));
// The scrollbar thumb is still fully visible.
expect
(
find
.
byType
(
CupertinoScrollbar
),
paints
..
rrect
(
color:
_kScrollbarColor
.
color
,
));
// Let the thumb fade out so all timers have resolved.
await
tester
.
pump
(
_kScrollbarTimeToFade
);
await
tester
.
pump
(
_kScrollbarFadeDuration
);
});
}
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