Welcome toVigges Developer Community-Open, Learning,Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.5k views
in Technique[技术] by (71.8m points)

android - Flutter: keep image within the screen borders on scale and pan

I'm trying to implement zoom inout on image with both double tap and scale but I found out that whenever I scale on the image - the image is able to partially "go out" of the screen and the background fills the space left... (see screenshot of current app state below). I tried wrapping some other widgets and changing the fit attribute of the image but it yielded nothing.

I want the image to always fit to the screen boundaries, especially on scaling. What am I missing? How can I make the image to not "slide" outside of the screen boundaries when I scale or pan?

Screenshot of app's current state, where the empty space is marked with yellow

My Code:

  ///controllers and details variable for zoom on double tap
  final _transformationController = TransformationController();
  TapDownDetails _doubleTapDetails;

  ///dismiss thresholds for an image to be dimissed
  final Map<DismissDirection, double> _dismissThresholds = {
    DismissDirection.horizontal: 0.8,
    DismissDirection.vertical: 0.6
  };

  ///big circular progress indicator
  final Center _circularProgressIndicator = Center(
    child: SizedBox(
        width: 60,
        height: 60,
        child: CircularProgressIndicator(
          valueColor: new AlwaysStoppedAnimation<Color>(Colors.lightGreen[800]),
        )
    ),
  );

  void _handleDoubleTapDown(TapDownDetails details) {
    _doubleTapDetails = details;
  }

  void _handleDoubleTap() {
    if (_transformationController.value != Matrix4.identity()) {
      _transformationController.value = Matrix4.identity();
    } else {
      final position = _doubleTapDetails.localPosition;
      /// Fox a 2x zoom:
      _transformationController.value = Matrix4.identity()
      ..translate(-position.dx, -position.dy)
      ..scale(2.0);
    }
  }

@override
Widget build(BuildContext context) {
  return Center(
    child: Dismissible(
      key: const Key('key2'),
      dismissThresholds: _dismissThresholds,
      confirmDismiss: (direction) {
        return Future<bool>(() => _transformationController.value.isIdentity());
      },
      direction: DismissDirection.horizontal,
      onDismissed: (_) {print ('dismissed horiz.')},
      child: Dismissible(
        dismissThresholds: _dismissThresholds,
        key: const Key('key'),
        confirmDismiss: (direction) {
          return Future<bool>(() => _transformationController.value.isIdentity());
        },
        direction: DismissDirection.vertical,
        onDismissed: (_) {print ('dismissed vert.')},
        child: GestureDetector(
          onDoubleTapDown: _handleDoubleTapDown,
          onDoubleTap: _handleDoubleTap,
          child: InteractiveViewer(
            transformationController: _transformationController,
            minScale: 1.0,
            maxScale: 2.0,
            panEnabled: true,
            scaleEnabled: true,
            boundaryMargin: EdgeInsets.all(100.0),
            child: CachedNetworkImage(
              imageUrl: 'https://cdn.onlinewebfonts.com/svg/img_258083.png',
              placeholder: (context, url) => _circularProgressIndicator,
              fit: BoxFit.fitWidth,
              alignment: FractionalOffset.center,
            )
          ),
        ),
      ),
    )
  );
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

I fixed it by setting the boundaryMargin: to EdgeInsets.all(0.0), under InteractiveViewer


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to Vigges Developer Community for programmer and developer-Open, Learning and Share
...