Flutter:缩放和平移小部件

4
我正在处理缩放/平移手势的问题。 我在这本书中找到了一个部分适用的例子: https://books.google.bg/books?id=ex-tDwAAQBAJ&pg=PA284&lpg=PA284&dq=flutter+_startLastOffset&source=bl&ots=YUQna09jIf&sig=ACfU3U0QrHwl2RdrVUv5EtpHaHFKx_cXhA&hl=en&sa=X&ved=2ahUKEwid9uPJ8abnAhVnlosKHTKQBn4Q6AEwAHoECAMQAQ#v=onepage&q=flutter%20_startLastOffset&f=false 我猜这是基于以下内容: https://chromium.googlesource.com/external/github.com/flutter/flutter/+/refs/heads/dev/examples/layers/widgets/gestures.dart 我的代码也是基于它的。
Offset _startLastOffset = Offset.zero;
Offset _lastOffset = Offset.zero;
Offset _currentOffset = Offset.zero;
double _lastScale = 1.0;
double _currentScale = 1.0;

void _onScaleStart(ScaleStartDetails details) {
  _startLastOffset = details.focalPoint;
  _lastOffset = _currentOffset;
  _lastScale = _currentScale;
}

void _onScaleUpdate(ScaleUpdateDetails details) {
  if (details.scale != 1.0) {
    // Scaling
    double currentScale = _lastScale * details.scale;
    if (currentScale < 0.5) {
      currentScale = 0.5;
    }
    _currentScale = currentScale;
    _bloc.setScale(_currentScale);
  } else if (details.scale == 1.0) {
    // We are not scaling but dragging around screen
    // Calculate offset depending on current Image scaling.
    Offset offsetAdjustedForScale = (_startLastOffset - _lastOffset) / _lastScale;
    Offset currentOffset = details.focalPoint - (offsetAdjustedForScale * _currentScale);
    _currentOffset = currentOffset;
    _bloc.setOffset(_currentOffset);
  }
}
---------------
child: StreamBuilder<Object>(
  stream: _bloc.scale,
  builder: (context, snapshot1) {
    double _cscale = snapshot1.hasData? snapshot1.data : _currentScale;
    return StreamBuilder<Object>(
      stream: _bloc.offset,
      builder: (context, snapshot2) {
        Offset _coffset = snapshot2.hasData? snapshot2.data : _currentOffset;
        return Transform(
          transform: Matrix4.identity()
            ..scale(_cscale, _cscale)
            ..translate(_coffset.dx, _coffset.dy),
          alignment: FractionalOffset.center,
          child: Stack(
            key: _imgStack,
            fit: StackFit.expand,
            children: <Widget>[
              Image(image: AssetImage('assets/images/image.png')),
              SvgPicture.asset(svgFile)
            ],
          ),
        );
      }
    );
  }
),

当小部件被缩放时,其中的平移行为会变得不自然 - 小部件在移动方向上移动的距离比手指大得多。

我通过更改以下内容成功解决了这个问题:

_currentOffset = currentOffset;
_bloc.setOffset(_currentOffset);

to:

_bloc.setOffset(currentOffset/_currentScale);
_currentOffset = currentOffset;

这个小部件在第一次缩放时表现正常,但是在第二次缩放后,它会在第一次触摸时发生偏移。 缩小时向右偏移,放大时向左偏移。

有什么想法吗?

1个回答

5
使用 InteractiveViewer 组件。以下是一个示例。
@override
Widget build(BuildContext context) {
  return Center(
    child: InteractiveViewer(
      boundaryMargin: EdgeInsets.all(100),
      minScale: 0.1,
      maxScale: 1.5,
      child: Container(width: 200, height: 200, color: Colors.blue),
    ),
  );
}

InteractiveViewer与CarouselSlider不兼容。如果我们想要查看图像的左侧或右侧部分,则滑块会显示上一个或下一个图像。您有什么建议吗?我们该如何解决它。非常感谢。 - Kamlesh
@Kamlesh 抱歉,我还没有使用过那个包。 - CopsOnRoad
好的,不用担心,您能否提供任何解决方案,以便如果子小部件的宽度/高度大于父小部件的宽度/高度,则子小部件不应显示/超出父小部件。请分享您的想法或以前的经验。谢谢。 - Kamlesh
1
@Kamlesh 我不确定你的小部件是什么,但你可以尝试将滚动方向设置为水平,并使用 SingleChildScrollView - CopsOnRoad

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接