首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >PageView内部的InteractiveViewer

PageView内部的InteractiveViewer
EN

Stack Overflow用户
提问于 2020-11-09 16:48:34
回答 1查看 213关注 0票数 2

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

下面是我写的内容:

代码语言:javascript
复制
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,
          )

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

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

有什么解决方案吗?感谢在座的每一个人。

EN

回答 1

Stack Overflow用户

发布于 2021-09-27 16:35:06

在我的例子中,我想创建一个简单的可滑动的图片库:水平滑动以在图像之间切换,并使用收缩和缩放来放大和缩小。问题是:当我放大时,我不能平移放大的图像。取而代之的是,PageView接管并翻到下一个图像。

我可以通过使用TransformatinController和侦听InteractiveViewer上的onInteractionEnd事件来解决这个问题。在该回调中,我检查图像是否被放大。如果它被放大了,我会停用PageView中的分页功能。

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

代码语言:javascript
复制
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);
          }
        },
      )
    );
  }
}
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64748389

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档