Flutter:使用 InteractiveViewer 双击启用图像缩放 in/out
Flutter: enable image zoom in/out on double tap using InteractiveViewer
我想在双击图像时启用放大和缩小功能,同时在捏合时缩放 in/out。
我在 YouTube 上看到一些教程,他们使用 GestureDetector
实现此功能,例如 this one,但出于某种原因,它对我没有用。
为了在捏合时实现缩放 in/out,我依靠 ,它确实很好用,但我还想在双击图像时启用缩放 in/out。不幸的是,在互联网上寻找这样做的方法,没有任何结果。
有什么方法可以使用 InteractiveViewer
来启用缩放 in/out 并同时使用捏合和双击吗?
这是我的代码:
@override
Widget build(BuildContext context) {
return Center(
child: InteractiveViewer(
boundaryMargin: EdgeInsets.all(80),
panEnabled: false,
scaleEnabled: true,
minScale: 1.0,
maxScale: 2.2,
child: Image.network("https://pngimg.com/uploads/muffin/muffin_PNG123.png",
fit: BoxFit.fitWidth,
)
),
);
}
您可以使用 GestureDetector
,它为您提供点击的位置,然后您可以在点击位置使用 TransformationController
进行缩放:
final _transformationController = TransformationController();
TapDownDetails _doubleTapDetails;
@override
Widget build(BuildContext context) {
return GestureDetector(
onDoubleTapDown: _handleDoubleTapDown,
onDoubleTap: _handleDoubleTap,
child: Center(
child: InteractiveViewer(
transformationController: _transformationController,
/* ... */
),
),
);
}
void _handleDoubleTapDown(TapDownDetails details) {
_doubleTapDetails = details;
}
void _handleDoubleTap() {
if (_transformationController.value != Matrix4.identity()) {
_transformationController.value = Matrix4.identity();
} else {
final position = _doubleTapDetails.localPosition;
// For a 3x zoom
_transformationController.value = Matrix4.identity()
..translate(-position.dx * 2, -position.dy * 2)
..scale(3.0);
// Fox a 2x zoom
// ..translate(-position.dx, -position.dy)
// ..scale(2.0);
}
}
要在双击时设置动画过渡,您必须在 之上创建一个明确的动画。
class _WidgetState extends State<Widget> with SingleTickerProviderStateMixin {
.
.
.
AnimationController _animationController;
Animation<Matrix4> _animation;
@override
void initState() {
super.initState();
_animationController = AnimationController(
vsync: this,
duration: Duration(milliseconds: 400),
)..addListener(() {
_transformationController.value = _animation.value;
});
}
@override
void dispose() {
_animationController.dispose();
super.dispose();
}
.
.
.
void _handleDoubleTap() {
Matrix4 _endMatrix;
Offset _position = _doubleTapDetails.localPosition;
if (_transformationController.value != Matrix4.identity()) {
_endMatrix = Matrix4.identity();
} else {
_endMatrix = Matrix4.identity()
..translate(-_position.dx * 2, -_position.dy * 2)
..scale(3.0);
}
_animation = Matrix4Tween(
begin: _transformationController.value,
end: _endMatrix,
).animate(
CurveTween(curve: Curves.easeOut).animate(_animationController),
);
_animationController.forward(from: 0);
}
.
.
.
}
我想在双击图像时启用放大和缩小功能,同时在捏合时缩放 in/out。
我在 YouTube 上看到一些教程,他们使用 GestureDetector
实现此功能,例如 this one,但出于某种原因,它对我没有用。
为了在捏合时实现缩放 in/out,我依靠
有什么方法可以使用 InteractiveViewer
来启用缩放 in/out 并同时使用捏合和双击吗?
这是我的代码:
@override
Widget build(BuildContext context) {
return Center(
child: InteractiveViewer(
boundaryMargin: EdgeInsets.all(80),
panEnabled: false,
scaleEnabled: true,
minScale: 1.0,
maxScale: 2.2,
child: Image.network("https://pngimg.com/uploads/muffin/muffin_PNG123.png",
fit: BoxFit.fitWidth,
)
),
);
}
您可以使用 GestureDetector
,它为您提供点击的位置,然后您可以在点击位置使用 TransformationController
进行缩放:
final _transformationController = TransformationController();
TapDownDetails _doubleTapDetails;
@override
Widget build(BuildContext context) {
return GestureDetector(
onDoubleTapDown: _handleDoubleTapDown,
onDoubleTap: _handleDoubleTap,
child: Center(
child: InteractiveViewer(
transformationController: _transformationController,
/* ... */
),
),
);
}
void _handleDoubleTapDown(TapDownDetails details) {
_doubleTapDetails = details;
}
void _handleDoubleTap() {
if (_transformationController.value != Matrix4.identity()) {
_transformationController.value = Matrix4.identity();
} else {
final position = _doubleTapDetails.localPosition;
// For a 3x zoom
_transformationController.value = Matrix4.identity()
..translate(-position.dx * 2, -position.dy * 2)
..scale(3.0);
// Fox a 2x zoom
// ..translate(-position.dx, -position.dy)
// ..scale(2.0);
}
}
要在双击时设置动画过渡,您必须在
class _WidgetState extends State<Widget> with SingleTickerProviderStateMixin {
.
.
.
AnimationController _animationController;
Animation<Matrix4> _animation;
@override
void initState() {
super.initState();
_animationController = AnimationController(
vsync: this,
duration: Duration(milliseconds: 400),
)..addListener(() {
_transformationController.value = _animation.value;
});
}
@override
void dispose() {
_animationController.dispose();
super.dispose();
}
.
.
.
void _handleDoubleTap() {
Matrix4 _endMatrix;
Offset _position = _doubleTapDetails.localPosition;
if (_transformationController.value != Matrix4.identity()) {
_endMatrix = Matrix4.identity();
} else {
_endMatrix = Matrix4.identity()
..translate(-_position.dx * 2, -_position.dy * 2)
..scale(3.0);
}
_animation = Matrix4Tween(
begin: _transformationController.value,
end: _endMatrix,
).animate(
CurveTween(curve: Curves.easeOut).animate(_animationController),
);
_animationController.forward(from: 0);
}
.
.
.
}