Anas-Qasem
Anas-Qasem

Reputation: 428

How to handle zooming with page view builder in flutter?

I'm working on an app that I need to implement zoom functionality with page swiping, in my case I need to make the zoom above the entire page view builder rather than on individual pages, similar to how the photo_view package works.

I am putting an Interactive widget above the page view builder like in the code below, I managed to prevent swiping while the user is zooming, but I'm struggling with re-enabling the swipe when the user reaches the edge of the screen while zoomed in and wants to navigate to the next page.

The issue is the dx value which am I getting from the matrix is always negative even if the user reaches the right or the left edge of the screen.

(note: dx value changed based on the zooming value but it is still negative).

How to detect that the user reaches the edge of the screen and needs to swipe to the next screen in the zooming case?

class ZoomWidget extends StatefulWidget {
  const ZoomWidget({
    super.key,

  });

  @override
  State<ZoomWidget> createState() => _ZoomWidgetState();
}

class _ZoomWidgetState extends State<ZoomWidget> {
  //  _controller = StreamController<bool>();
  late final ValueNotifier<bool> _isScaling;
  // this is for removing scaling because first two pages contains zoom widget

  bool _isAtEdge = false;

  late final TransformationController _transformationController;
  static const double _minScale = 1.0;
  late final double width;
  @override
  void initState() {
    _isScaling = ValueNotifier(false);
    _transformationController = TransformationController();
    width = MediaQuery.sizeOf(context).width;
    super.initState();
  }

  @override
  void dispose() {
    _isScaling.dispose();
    _transformationController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return InteractiveViewer(
      panAxis: PanAxis.aligned,
      transformationController: _transformationController,
      maxScale: 3,
      minScale: _minScale,
      onInteractionUpdate: (details) {
        // get the matrix
        final Matrix4 matrix = _transformationController.value;
        // get the scale
        final double scale = matrix.getMaxScaleOnAxis();
        // to update the physics
        _isScaling.value = scale > _minScale;
      },
      onInteractionStart: (details) {
        // get the matrix
        final Matrix4 matrix = _transformationController.value;
        // get the dx
        final double dx = matrix.getTranslation().x;
        // get the scale
        final double scale = matrix.getMaxScaleOnAxis();
        _isAtEdge = (dx < 0 && scale > _minScale);
        //|| (dx < -width && scale > _minScale)
        // log(_isAtEdge.toString());
      },
      child: GestureDetector(
        child: ValueListenableBuilder(
          valueListenable: _isScaling,
          builder: (context, isScaling, child) {
            return PageView.builder(
              itemCount: 6,
              physics: isScaling ? const NeverScrollableScrollPhysics() : const ClampingScrollPhysics(),
              onPageChanged: (int index) {},
              scrollDirection: Axis.horizontal,
              itemBuilder: (context, index) {
                return SomeWidget();
              },
            );
          },
        ),
      ),
    );
  }
}

Upvotes: 0

Views: 105

Answers (0)

Related Questions