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
2c163e6e
Unverified
Commit
2c163e6e
authored
Sep 19, 2020
by
Justin McCandless
Committed by
GitHub
Sep 19, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
InteractiveViewer onInteractionUpdate focalPoint (#66065)
parent
a19f5bac
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
122 additions
and
45 deletions
+122
-45
interactive_viewer.dart
packages/flutter/lib/src/widgets/interactive_viewer.dart
+53
-42
interactive_viewer_test.dart
packages/flutter/test/widgets/interactive_viewer_test.dart
+69
-3
No files found.
packages/flutter/lib/src/widgets/interactive_viewer.dart
View file @
2c163e6e
...
...
@@ -220,6 +220,9 @@ class InteractiveViewer extends StatefulWidget {
/// Called when the user ends a pan or scale gesture on the widget.
///
/// At the time this is called, the [TransformationController] will have
/// already been updated to reflect the change caused by the interaction.
///
/// {@template flutter.widgets.interactiveViewer.onInteraction}
/// Will be called even if the interaction is disabled with
/// [panEnabled] or [scaleEnabled].
...
...
@@ -229,10 +232,6 @@ class InteractiveViewer extends StatefulWidget {
/// [GestureDetector.onScaleEnd]. Use [onInteractionStart],
/// [onInteractionUpdate], and [onInteractionEnd] to respond to those
/// gestures.
///
/// The coordinates returned in the details are viewport coordinates relative
/// to the parent. See [TransformationController.toScene] for how to
/// convert the coordinates to scene coordinates relative to the child.
/// {@endtemplate}
///
/// See also:
...
...
@@ -243,8 +242,17 @@ class InteractiveViewer extends StatefulWidget {
/// Called when the user begins a pan or scale gesture on the widget.
///
/// At the time this is called, the [TransformationController] will not have
/// changed due to this interaction.
///
/// {@macro flutter.widgets.interactiveViewer.onInteraction}
///
/// The coordinates provided in the details' `focalPoint` and
/// `localFocalPoint` are normal Flutter event coordinates, not
/// InteractiveViewer scene coordinates. See
/// [TransformationController.toScene] for how to convert these coordinates to
/// scene coordinates relative to the child.
///
/// See also:
///
/// * [onInteractionUpdate], which handles an update to the same interaction.
...
...
@@ -253,8 +261,17 @@ class InteractiveViewer extends StatefulWidget {
/// Called when the user updates a pan or scale gesture on the widget.
///
/// At the time this is called, the [TransformationController] will have
/// already been updated to reflect the change caused by the interaction.
///
/// {@macro flutter.widgets.interactiveViewer.onInteraction}
///
/// The coordinates provided in the details' `focalPoint` and
/// `localFocalPoint` are normal Flutter event coordinates, not
/// InteractiveViewer scene coordinates. See
/// [TransformationController.toScene] for how to convert these coordinates to
/// scene coordinates relative to the child.
///
/// See also:
///
/// * [onInteractionStart], which handles the start of the same interaction.
...
...
@@ -711,9 +728,7 @@ class _InteractiveViewerState extends State<InteractiveViewer> with TickerProvid
// Handle the start of a gesture. All of pan, scale, and rotate are handled
// with GestureDetector's scale gesture.
void
_onScaleStart
(
ScaleStartDetails
details
)
{
if
(
widget
.
onInteractionStart
!=
null
)
{
widget
.
onInteractionStart
!(
details
);
}
widget
.
onInteractionStart
?.
call
(
details
);
if
(
_controller
.
isAnimating
)
{
_controller
.
stop
();
...
...
@@ -735,16 +750,6 @@ class _InteractiveViewerState extends State<InteractiveViewer> with TickerProvid
// handled with GestureDetector's scale gesture.
void
_onScaleUpdate
(
ScaleUpdateDetails
details
)
{
final
double
scale
=
_transformationController
!.
value
.
getMaxScaleOnAxis
();
if
(
widget
.
onInteractionUpdate
!=
null
)
{
widget
.
onInteractionUpdate
!(
ScaleUpdateDetails
(
focalPoint:
_transformationController
!.
toScene
(
details
.
localFocalPoint
,
),
scale:
details
.
scale
,
rotation:
details
.
rotation
,
));
}
final
Offset
focalPointScene
=
_transformationController
!.
toScene
(
details
.
localFocalPoint
,
);
...
...
@@ -798,7 +803,7 @@ class _InteractiveViewerState extends State<InteractiveViewer> with TickerProvid
if
(
_round
(
_referenceFocalPoint
!)
!=
_round
(
focalPointSceneCheck
))
{
_referenceFocalPoint
=
focalPointSceneCheck
;
}
return
;
break
;
case
_GestureType
.
rotate
:
if
(
details
.
rotation
==
0.0
)
{
...
...
@@ -811,7 +816,7 @@ class _InteractiveViewerState extends State<InteractiveViewer> with TickerProvid
details
.
localFocalPoint
,
);
_currentRotation
=
desiredRotation
;
return
;
break
;
case
_GestureType
.
pan
:
assert
(
_referenceFocalPoint
!=
null
);
...
...
@@ -832,16 +837,20 @@ class _InteractiveViewerState extends State<InteractiveViewer> with TickerProvid
_referenceFocalPoint
=
_transformationController
!.
toScene
(
details
.
localFocalPoint
,
);
return
;
break
;
}
widget
.
onInteractionUpdate
?.
call
(
ScaleUpdateDetails
(
focalPoint:
details
.
focalPoint
,
localFocalPoint:
details
.
localFocalPoint
,
scale:
details
.
scale
,
rotation:
details
.
rotation
,
));
}
// Handle the end of a gesture of _GestureType. All of pan, scale, and rotate
// are handled with GestureDetector's scale gesture.
void
_onScaleEnd
(
ScaleEndDetails
details
)
{
if
(
widget
.
onInteractionEnd
!=
null
)
{
widget
.
onInteractionEnd
!(
details
);
}
widget
.
onInteractionEnd
?.
call
(
details
);
_scaleStart
=
null
;
_rotationStart
=
null
;
_referenceFocalPoint
=
null
;
...
...
@@ -890,10 +899,17 @@ class _InteractiveViewerState extends State<InteractiveViewer> with TickerProvid
// Handle mousewheel scroll events.
void
_receivedPointerSignal
(
PointerSignalEvent
event
)
{
if
(!
_gestureIsSupported
(
_GestureType
.
scale
))
{
return
;
}
if
(
event
is
PointerScrollEvent
)
{
widget
.
onInteractionStart
?.
call
(
ScaleStartDetails
(
focalPoint:
event
.
position
,
localFocalPoint:
event
.
localPosition
,
),
);
if
(!
_gestureIsSupported
(
_GestureType
.
scale
))
{
widget
.
onInteractionEnd
?.
call
(
ScaleEndDetails
());
return
;
}
final
RenderBox
childRenderBox
=
_childKey
.
currentContext
!.
findRenderObject
()
as
RenderBox
;
final
Size
childSize
=
childRenderBox
.
size
;
final
double
scaleChange
=
1.0
-
event
.
scrollDelta
.
dy
/
childSize
.
height
;
...
...
@@ -903,6 +919,7 @@ class _InteractiveViewerState extends State<InteractiveViewer> with TickerProvid
final
Offset
focalPointScene
=
_transformationController
!.
toScene
(
event
.
localPosition
,
);
_transformationController
!.
value
=
_matrixScale
(
_transformationController
!.
value
,
scaleChange
,
...
...
@@ -917,22 +934,16 @@ class _InteractiveViewerState extends State<InteractiveViewer> with TickerProvid
_transformationController
!.
value
,
focalPointSceneScaled
-
focalPointScene
,
);
if
(
widget
.
onInteractionStart
!=
null
)
{
widget
.
onInteractionStart
!(
ScaleStartDetails
(
focalPoint:
focalPointSceneScaled
)
);
}
if
(
widget
.
onInteractionUpdate
!=
null
)
{
widget
.
onInteractionUpdate
!(
ScaleUpdateDetails
(
rotation:
0.0
,
scale:
scaleChange
,
horizontalScale:
1.0
,
verticalScale:
1.0
,
));
}
if
(
widget
.
onInteractionEnd
!=
null
)
{
widget
.
onInteractionEnd
!(
ScaleEndDetails
());
}
widget
.
onInteractionUpdate
?.
call
(
ScaleUpdateDetails
(
focalPoint:
event
.
position
,
localFocalPoint:
event
.
localPosition
,
rotation:
0.0
,
scale:
scaleChange
,
horizontalScale:
1.0
,
verticalScale:
1.0
,
));
widget
.
onInteractionEnd
?.
call
(
ScaleEndDetails
());
}
}
...
...
packages/flutter/test/widgets/interactive_viewer_test.dart
View file @
2c163e6e
...
...
@@ -625,6 +625,8 @@ void main() {
testWidgets
(
'Scale with mouse returns onInteraction properties'
,
(
WidgetTester
tester
)
async
{
final
TransformationController
transformationController
=
TransformationController
();
Offset
focalPoint
;
Offset
localFocalPoint
;
double
scaleChange
;
Velocity
currentVelocity
;
bool
calledStart
;
...
...
@@ -639,6 +641,8 @@ void main() {
},
onInteractionUpdate:
(
ScaleUpdateDetails
details
){
scaleChange
=
details
.
scale
;
focalPoint
=
details
.
focalPoint
;
localFocalPoint
=
details
.
localFocalPoint
;
},
onInteractionEnd:
(
ScaleEndDetails
details
){
currentVelocity
=
details
.
velocity
;
...
...
@@ -656,11 +660,73 @@ void main() {
const
Velocity
noMovement
=
Velocity
(
pixelsPerSecond:
Offset
(
0
,
0
));
final
double
afterScaling
=
transformationController
.
value
.
getMaxScaleOnAxis
();
expect
(
scaleChange
,
greaterThan
(
1.0
));
expect
(
afterScaling
,
isNot
(
equals
(
null
)));
expect
(
afterScaling
,
isNot
(
equals
(
1.0
)));
expect
(
scaleChange
,
greaterThan
(
1.0
));
expect
(
afterScaling
,
scaleChange
);
expect
(
currentVelocity
,
equals
(
noMovement
));
expect
(
calledStart
,
equals
(
true
));
// Focal points are given in coordinates outside of InteractiveViewer,
// with local being in relation to the viewport.
expect
(
focalPoint
,
center
);
expect
(
localFocalPoint
,
const
Offset
(
100
,
100
));
// The scene point is the same as localFocalPoint because the center of
// the scene is at the center of the viewport.
final
Offset
scenePoint
=
transformationController
.
toScene
(
localFocalPoint
);
expect
(
scenePoint
,
const
Offset
(
100
,
100
));
});
testWidgets
(
'onInteraction can be used to get scene point'
,
(
WidgetTester
tester
)
async
{
final
TransformationController
transformationController
=
TransformationController
();
Offset
focalPoint
;
Offset
localFocalPoint
;
double
scaleChange
;
Velocity
currentVelocity
;
bool
calledStart
;
await
tester
.
pumpWidget
(
MaterialApp
(
home:
Scaffold
(
body:
Center
(
child:
InteractiveViewer
(
transformationController:
transformationController
,
onInteractionStart:
(
ScaleStartDetails
details
){
calledStart
=
true
;
},
onInteractionUpdate:
(
ScaleUpdateDetails
details
){
scaleChange
=
details
.
scale
;
focalPoint
=
details
.
focalPoint
;
localFocalPoint
=
details
.
localFocalPoint
;
},
onInteractionEnd:
(
ScaleEndDetails
details
){
currentVelocity
=
details
.
velocity
;
},
child:
Container
(
width:
200.0
,
height:
200.0
),
),
),
),
),
);
final
Offset
center
=
tester
.
getCenter
(
find
.
byType
(
InteractiveViewer
));
final
Offset
offCenter
=
Offset
(
center
.
dx
-
20.0
,
center
.
dy
-
20.0
);
await
scrollAt
(
offCenter
,
tester
,
const
Offset
(
0.0
,
-
20.0
));
await
tester
.
pumpAndSettle
();
const
Velocity
noMovement
=
Velocity
(
pixelsPerSecond:
Offset
(
0
,
0
));
final
double
afterScaling
=
transformationController
.
value
.
getMaxScaleOnAxis
();
expect
(
scaleChange
,
greaterThan
(
1.0
));
expect
(
afterScaling
,
scaleChange
);
expect
(
currentVelocity
,
equals
(
noMovement
));
expect
(
calledStart
,
equals
(
true
));
// Focal points are given in coordinates outside of InteractiveViewer,
// with local being in relation to the viewport.
expect
(
focalPoint
,
offCenter
);
expect
(
localFocalPoint
,
const
Offset
(
80
,
80
));
// The top left corner of the viewport is not at the top left corner of
// the scene.
final
Offset
scenePoint
=
transformationController
.
toScene
(
Offset
.
zero
);
expect
(
scenePoint
.
dx
,
greaterThan
(
0.0
));
expect
(
scenePoint
.
dy
,
greaterThan
(
0.0
));
});
testWidgets
(
'viewport changes size'
,
(
WidgetTester
tester
)
async
{
...
...
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