Could not complete vertical scroll of Listview inside InteractiveViewer

Viewed 245

I have a requirement where I need to scroll through a list of images and also zoom and pan them. Very similar to a pdf document viewer. So I Used a ListView to show the pages and added the ListView as child to InteractiveViewer.

After zooming in I could not scroll to the top or bottom end of the ListView.

Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: InteractiveViewer(
        child: ListView.builder(
          padding: EdgeInsets.zero,
          itemCount: 10,
          itemBuilder: (context, _index) {
            print(_index);
            return Container(
              color: Colors.grey,
              height: MediaQuery.of(context).size.width * 1.1,
              width: MediaQuery.of(context).size.width,
              padding: EdgeInsets.all(2),
              child: Container(
                padding: EdgeInsets.all(2),
                color: Colors.white,
                child: Center(
                  child: Text('Page index: $_index'),
                ),
              ),
            );
          },
        ),
        scaleEnabled: true,
        panEnabled: true,
      ),
    );
  }

Screen recording of the issue faced

I guess it might be due to the InteractiveViewer handling the scroll gesture of ListView.

Is there a way to avoid vertical gesture to be handled by InteractiveViewer?

1 Answers

I don't think there is a way to make the two element have their scroll behavior working together, as InteractiveViewer allows you to move after zooming in your image.

Would it fulfill your requirement to set the image to fullscreen when taping on the image to zoom ?

That way you keep the scroll handled by the ScrollView and separate the InteractiveViewer to another view.

Something like that, you wrap all of your images with the ImageDetails widget and remove your InteractiveViewer from the Scaffold:

class ImageDetails extends StatelessWidget {
  final String url;

  const ImageDetails({Key key, this.url}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return GestureDetector(
        child: Hero(
          tag: 'tag$url',
          child: NetworkImage(
            imageUrl: url,
            fit: BoxFit.cover,
          ),
        ),
        onTap: () {
          Navigator.push(context, MaterialPageRoute(builder: (_) {
            return FullScreenImage(
              url: url,
            );
          }));
        });
  }
}

class FullScreenImage extends StatelessWidget {
  final String url;

  const FullScreenImage({Key key, this.url})
      : super(key: key);
  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      child: InteractiveViewer(
        maxScale: 2.0,
        minScale: 1.0,
        child: Scaffold(
          backgroundColor: Colors.black,
          body: Center(
            child: Hero(
              tag: 'tag$url',
              child: SizedBox(
                width: MediaQuery.of(context).size.width,
                child:
                    NetworkImage(imageUrl: url, fit: BoxFit.fitWidth),
              ),
            ),
          ),
        ),
      ),
      onTap: () {
        Navigator.pop(context);
      },
    );
  }
}

Related