3

我正在创建一个带有图像列表的 PageView,并且我想将 interactiveViewer 添加到每个图像,以便可以调整其大小以查看详细信息。

这是我写的:

PageView.builder(
              dragStartBehavior: DragStartBehavior.start,
              physics: _viewing ?  NeverScrollableScrollPhysics() : ClampingScrollPhysics(),
              controller: _pageController,
              itemBuilder: (context, index) {
                return Container(
                    child: Expanded(
                      child: Image.network(widget.snapshotList[index].imgUrl),
                    )
                );
              },
              onPageChanged: (index) {
                setState(() {
                  this.position = index;
                  _transformationController.value = Matrix4.identity();
                });
              },
              itemCount: widget.snapshotList.length,
          )

但是这两个滚动条似乎相互竞争,行为混乱。

例如,一旦图像被放大,滚动手势也会触发页面移动,这似乎是因为视口没有随图像本身放大。

有什么解决办法吗?谢谢楼上的任何人。

4

1 回答 1

3

在我的例子中,我想创建一个简单的可滑动图像库:水平滑动以从图像转到图像,并使用捏合和缩放来放大和缩小。问题是这样的:当我放大时,我无法平移放大的图像。相反,PageView接管并分页到下一个图像。

我能够通过使用 aTransformatinControlleronInteractionEndInteractiveViewer. 在该回调中,我检查图像是否放大。如果放大,我会在PageView.

这是一个完整的示例应用程序,展示了如何实现它:

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'InteractiveViewer inside PageView Demo',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  final String title;

  const MyHomePage({
    Key? key,
    required this.title,
  }) : super(key: key);

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

class _MyHomePageState extends State<MyHomePage> {
  final List<ImageProvider> _imageProviders = [
    Image.network("https://picsum.photos/id/1001/5616/3744").image,
    Image.network("https://picsum.photos/id/1003/1181/1772").image,
    Image.network("https://picsum.photos/id/1004/5616/3744").image,
    Image.network("https://picsum.photos/id/1005/5760/3840").image
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: EasyImageViewPager(imageProviders: _imageProviders)
      ),
    );
  }
}

/// PageView for swiping through a list of images
class EasyImageViewPager extends StatefulWidget {
  
  final List<ImageProvider> imageProviders;

  /// Create new instance, using the [imageProviders] to populate the [PageView]
  const EasyImageViewPager({ Key? key, required this.imageProviders }) : super(key: key);

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

class _EasyImageViewPagerState extends State<EasyImageViewPager> {

  final PageController _pageController = PageController();
  bool _pagingEnabled = true;
  
  @override
  void dispose() {
    _pageController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return PageView.builder(
      physics: _pagingEnabled ? const PageScrollPhysics() : const NeverScrollableScrollPhysics(),
      itemCount: widget.imageProviders.length,
      controller: _pageController,
      itemBuilder: (context, index) {
        final image = widget.imageProviders[index];
        return EasyImageView(
          imageProvider: image,
          onScaleChanged: (scale) {
            setState(() {
              // Disable paging when image is zoomed-in
              _pagingEnabled = scale <= 1.0;
            });
          },
        );
      }, 
    );
  }
}

/// A full-sized view that displays the given image, supporting pinch & zoom
class EasyImageView extends StatefulWidget {

  /// The image to display
  final ImageProvider imageProvider;
  /// Minimum scale factor
  final double minScale;
  /// Maximum scale factor
  final double maxScale;
  /// Callback for when the scale has changed, only invoked at the end of
  /// an interaction.
  final void Function(double)? onScaleChanged;
  /// Create a new instance
  const EasyImageView({
    Key? key,
    required this.imageProvider,
    this.minScale = 1.0,
    this.maxScale = 5.0,
    this.onScaleChanged,
  }) : super(key: key);

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

class _EasyImageViewState extends State<EasyImageView> {

  final TransformationController _transformationController = TransformationController();
  
  @override
  Widget build(BuildContext context) {
    return SizedBox(
      width: MediaQuery.of(context).size.width,
      height: MediaQuery.of(context).size.height, 
      child: InteractiveViewer(
        transformationController: _transformationController,
        minScale: widget.minScale,
        maxScale: widget.maxScale,
        child: Image(image: widget.imageProvider),
        onInteractionEnd: (scaleEndDetails) {
          double scale = _transformationController.value.getMaxScaleOnAxis();

          if (widget.onScaleChanged != null) {
            widget.onScaleChanged!(scale);
          }
        },
      )
    );
  }
}
于 2021-09-27T16:35:06.003 回答