Anwar
Anwar

Reputation: 59

Gesture Detector problem when i am using Interactive viewer (FLUTTER)

WORK : I am Creating App for book and I am linking images and swipe to next page I am using Gesture Detector for swipe next page and I am using InteractiveViewer for zoom page

PROBLEM : The problem is when I use pinch to zoom-in its successfully work but when Drag the page for seeing more words . It detect gesture Detector and It goes to other page ..

WHAT I WANT : I want to disable the gestureDetector when I am using InteractiveViewer, Like when I am in Zoom-in mode so the gestureDetector Disable and when I Zoom out the GestureDetector enable.

import 'package:flutter/material.dart';

class Screen2 extends StatefulWidget {
  const Screen2({ Key key }) : super(key: key);

  @override
  _Screen2State createState() => _Screen2State();
}

class _Screen2State extends State<Screen2> {
  @override
  Widget build(BuildContext context) {
    return  Scaffold(
           appBar: appbarr(),
        body: GestureDetector(
          onHorizontalDragUpdate: (details) {  
        // Note: Sensitivity is integer used when you don't want to mess up vertical drag
        int sensitivity = 8;
        int senElse = -8;
        if (details.delta.dx > sensitivity) {
            Navigator.pop(context);
        } 
        else if (details.delta.dx < senElse )
        {
             Navigator.push(context, MaterialPageRoute(builder: (context) => Screen3()));
         }
        },
          child: InteractiveViewer(
            panEnabled: true,
            minScale: 0.5,
            maxScale: 5,
            child: Container(
              width: MediaQuery.of(context).size.width,
              height: MediaQuery.of(context).size.height,
              decoration: BoxDecoration(
              image: DecorationImage(
                image: AssetImage("assets/2.jpg"),
                fit: BoxFit.fill,
              ),
              ),
            ),
          ),
        )
    );
  }
}

Upvotes: 4

Views: 2053

Answers (1)

DarkMath
DarkMath

Reputation: 1419

You need to check if the is the user has zoomed in or not. If the user has zoomed in we not render a GestureDetector. We only make use of the GestureDetector is the user hasn't zoomed. To check whether the user has zoomed in or not, we use a TranformationController and compare it's current value with the identity matrix.

Here is the working code:

class Screen2 extends StatefulWidget {
  const Screen2({ Key? key }) : super(key: key);

  @override
  _Screen2State createState() => _Screen2State();
}

class _Screen2State extends State<Screen2> {
  final transformationController = TransformationController();

  bool get userHasZoomedIn => (Matrix4.identity() - transformationController.value).infinityNorm() > 0.000001;
  
  @override
  Widget build(BuildContext context) {
    final interactiveImage = InteractiveViewer(
      panEnabled: true,
      minScale: 0.5,
      maxScale: 5,
      transformationController: transformationController,
      onInteractionEnd: (details) => setState((){}),
      child: Container(
        width: MediaQuery.of(context).size.width,
        height: MediaQuery.of(context).size.height,
        decoration: BoxDecoration(
          image: DecorationImage(
            image: AssetImage("assets/2.jpg"),
            fit: BoxFit.fill,
          ),
        ),
      ),
    );
    final appBar = AppBar(title: Text('Title'));

    if(userHasZoomedIn){
      return Scaffold(
        appBar: appBar,
        body: interactiveImage,
      );
    }
    
    return Scaffold(
      appBar: appBar,
      body: GestureDetector(
        onHorizontalDragUpdate: (details) {
          // Note: Sensitivity is integer used when you don't want to mess up vertical drag
          int sensitivity = 8;
          int senElse = -8;
          if (details.delta.dx > sensitivity) {
            Navigator.pop(context);
          }
          else if (details.delta.dx < senElse )
          {
            Navigator.push(context, MaterialPageRoute(builder: (context) => Screen3()));
          }
        },
        child: interactiveImage,
      )
    );
  }
}

Note that we call setState in the InteractionViewer.onInteractionEnd. Another approach would be to add a listener to the TransformationController:

transformationController.addListener(() {
  setState(() {});
});

You should not do that because that will fire setState() way too often which causes a bad user experience and high CPU and GPU load.

Upvotes: 1

Related Questions