简体   繁体   中英

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(),
        )
    );
  }

I had a similar problem that's when I found "extended_image" package( https://pub.dev/packages/extended_image ) that lets the user zoom and will slide to the next page only if the image boundary reaches its end.

The vital parameter here is GestureConfig, which has many properties inside it but the one we need is inPageView. If it is set to true, we get the output we want. You can learn more about it on its official page.

Full Code: -

import 'package:extended_image/extended_image.dart';
import 'package:flutter/material.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Image',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      debugShowCheckedModeBanner: false,
      home: const Image(),
    );
  }
}

class Image extends StatefulWidget {
  const Image({Key? key}) : super(key: key);
  @override
  _CubeState createState() => _CubeState();
}

class _CubeState extends State<Image> {
  List images = [
    "https://img.freepik.com/free-vector/space-game-background-neon-night-alien-landscape_107791-1624.jpg?w=1060&t=st=1673067224~exp=1673067824~hmac=f4f13bff7718874c4b643212bf53455221893a3796885adffd501d231286f651",
    "https://img.freepik.com/free-vector/abstract-splashed-watercolor-textured-background_53876-8725.jpg?w=1060&t=st=1673067234~exp=1673067834~hmac=dbe96266a3b906deb91e91abe19eee18d9e8d6591e25bdbc7ba8264198d6df4b"
  ];
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: ExtendedImageGesturePageView.builder(
          itemBuilder: (BuildContext context, int index) {
            return ExtendedImage.network(
              images[index],
              fit: BoxFit.contain,
              mode: ExtendedImageMode.gesture,
              initGestureConfigHandler: (ExtendedImageState state) {
                return GestureConfig(
                  minScale: 0.9,
                  animationMinScale: 0.7,
                  maxScale: 4.0,
                  animationMaxScale: 4.5,
                  speed: 1.0,
                  inertialSpeed: 100.0,
                  initialScale: 1.0,
                  inPageView: true,
                  initialAlignment: InitialAlignment.center,
                  reverseMousePointerScrollDirection: true,
                  gestureDetailsIsChanged: (GestureDetails? details) {},
                );
              },
            );
          },
          itemCount: images.length,
          onPageChanged: (int index) {},
          scrollDirection: Axis.horizontal,
        ),
      ),
    );
  }
}

Output: -

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]);
    }
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM