Flutter:使用 InteractiveViewer 在双击时启用图像放大/缩小

问题描述

我想在双击图像时启用放大和缩小,同时在捏合时放大/缩小。 我在 YouTube 上看到了一些教程,他们使用 GestureDetector 实现了此功能,例如 this one,但由于某种原因,它对我不起作用。 为了在捏合时实现缩放,我依赖于 this answer,它确实很好用,但我也想在双击图像时启用放大/缩小。不幸的是,在互联网上寻找这样做的方法,但一无所获。

有什么方法可以使用 InteractiveViewer 通过双指捏合和双击来启用放大/缩小吗?

这是我的代码

@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);
  }
}
,

要在双击时设置过渡动画,您必须在 Till's code 之上创建显式动画。

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);
    }

    _animation = Matrix4Tween(
      begin: _transformationController.value,end: _endMatrix,).animate(
      CurveTween(curve: Curves.easeOut).animate(_animationController),);
    _animationController.forward(from: 0);
  }
  .
  .
  .
}
,

请使用 photo_view 插件来执行此操作, https://pub.dev/packages/photo_view

一切顺利!