Search code examples
flutterflutter-dependenciescarousel-slider

Flutter stop CarouselSlider scrolling when image is zoomed


in this reader widget i want to change the scrolling behavior so that if i'm zoomed in on an image and move arround the CarouselSlider dosen't slide to the next image unless i'm at the current image boundary.

I tried to change the scrollPhysics with every one I could find, without sucess.

There a similar questions around here, but none answered this problem.

how zoom in carouselslider in flutter?

flutter InteractiveViewer with CarouselSlider very difficult to pinch zoom

Here's the method handling the carousel:

  CarouselSlider buildCarouselSlider() {
    final double height = MediaQuery.of(context).size.height;
    return CarouselSlider.builder(
        itemCount: widget.file.pagesCount,
        itemBuilder: (context, index, pageViewIndex) => Center(
          child: PhotoView(
            imageProvider: CachedNetworkImageProvider(widget.file.pagesUrl[index]),
            onTapDown: (context, details, controllerValue) {
              // Hide app bar on scroll down
              setState(() {_showAppBar = !_showAppBar;});
            },
            backgroundDecoration: const BoxDecoration(color: Colors.black),
          ),
        ),
        options: CarouselOptions(
          autoPlay: false,
          enableInfiniteScroll: false,
          viewportFraction: 1.0,
          enlargeCenterPage: false,
          height: height,
          clipBehavior: Clip.hardEdge,
          pageSnapping: true,
          scrollDirection: _axis,
          initialPage: widget.file.currentPage,
          scrollPhysics: const PageScrollPhysics(),
        )
    );
  }

Solution

  • I ended up finding this tutorial and using the PhotoViewGallery with the PhotoViewGalleryPageOption did the trick.

    It's even better as the page border are better defined and don't just start scrolling to the next one as soon as you're on the border.

    https://resocoder.com/2019/05/04/flutter-photo-view-gallery-resize-rotate-image-carousel/

    Here's my full code for anyone with the same problem:

    import 'package:cached_network_image/cached_network_image.dart';
    import 'package:flutter/material.dart';
    import 'package:flutter_cache_manager/flutter_cache_manager.dart';
    import 'package:photo_view/photo_view.dart';
    import 'package:photo_view/photo_view_gallery.dart';
    
    import '../../../model/file.dart';
    import '../../../services/service_file.dart';
    
    class ReaderGallery extends StatelessWidget {
      final File file;
      final Function? onTap;
      final Axis axis;
    
      const ReaderGallery({
        super.key,
        required this.file,
        required this.axis,
        this.onTap,
      });
    
      @override
      Widget build(BuildContext context) {
        PageController controller = PageController(initialPage: file.currentPage, keepPage: false);
        return PhotoViewGallery.builder(
          itemCount: file.pagesCount,
          builder: (context, index) {
            return PhotoViewGalleryPageOptions(
              imageProvider: CachedNetworkImageProvider(file.pagesUrl[index]),
              minScale: PhotoViewComputedScale.contained * 1,
              maxScale: PhotoViewComputedScale.contained * 4,
              onTapDown: (context, details, controllerValue) {
                // Set parent state and execute whatever the parent needs to do
                onTap != null ? onTap!() : null;
              },
            );
          },
          scrollDirection: axis,
          pageController: controller,
          onPageChanged: onPageChange,
          scrollPhysics: const BouncingScrollPhysics(),
          backgroundDecoration: BoxDecoration(
            color: Theme.of(context).canvasColor,
          ),
        );
      }
    
      void onPageChange(int index) {
        file.currentPage = index;
        prefetchNextImage(index);
        ServiceFile.setCurrentPage(file, index);
      }
    
      void prefetchNextImage(int index){
        if (index < file.pagesCount - 1) {
          DefaultCacheManager().downloadFile(file.pagesUrl[index+1]);
        }
      }
    }