PageView 内的 InteractiveViewer

2024-04-11

我正在创建一个包含图像列表的 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,
          )

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

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

有什么解决办法吗?谢谢大家。


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

我能够通过使用来解决这个问题TransformationController并聆听onInteractionEnd事件于InteractiveViewer。在该回调中,我检查图像是否放大。如果它被放大,我会禁用分页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
  void dispose() {
    _transformationController.dispose();
    super.dispose();
  }
  
  @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);
          }
        },
      )
    );
  }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

PageView 内的 InteractiveViewer 的相关文章

随机推荐

  • 为什么 std::string 不是 std::vector 的特化? [复制]

    这个问题在这里已经有答案了 将字符串视为字符向量似乎是显而易见的 那么为什么 string 有它自己的特殊实现 它看起来与向量类有很大不同呢 只是为了说明这一点 这里有两个课程的一些片段 以表明所需的工作非常相似 例如两者都使用分配器来管理
  • 页面刷新期间的 selenium.common.exceptions.StaleElementReferenceException

    页面包含一些数据 行数很少的表 有 刷新 按钮 可以重新加载和重新绘制页面上的某些元素 而无需重新加载静态数据 ajax 我正在尝试为该页面创建适当的测试 但有时会出现 StaleElementReferenceException 我的代码
  • 多元二分法

    我需要一种算法来执行二维二分法来解决 2x2 非线性问题 示例 两个方程f x y 0 and g x y 0我想同时解决这个问题 我非常熟悉一维二分 以及其他数值方法 假设我已经知道解决方案位于界限之间x1 lt x lt x2 and
  • 在 Android 上的活动之间保持蓝牙连接 [重复]

    这个问题在这里已经有答案了 可能的重复 Android 如何将蓝牙连接传递给另一个活动 https stackoverflow com questions 6872970 android how to pass a bluetooth co
  • 默认情况下,PHPUnit 模拟对象从未期望过

    如果没有正式定义的期望 有没有办法告诉 phpunit 模拟对象永远不要期望方法调用 在我看来 不要对每种方法都抱有期望是没有道理的 所以 phpunit 没有任何功能 仅当您想完全确保某些方法不会被调用时 才应使用 从不 期望 无论如何
  • 查找每个逗号后的第二个空格

    This is a follow up to this question Concatenate previous and latter words to a word that match a condition in R https s
  • 如何更新猫鼬中的特定字段?

    我有一个数据集是 var JobSchema Schema candidates user type Schema Types ObjectId ref User status type String default In Progress
  • 如何使用私钥对字符串进行签名

    如何使用以下方式获取字符串的签名SHA1withRSA如果我已经拥有私钥byte or String 我想你所说的是你事先知道密钥对并且想用它来签名 验证 请看下面的代码 import java security KeyPair impor
  • 针对 SSE2 之前的处理器的 Java 运行时如何实现浮点基本运算?

    针对没有 SSE2 的 Intel 处理器的 Java 运行时如何处理浮点非规格化 当strictfp is set 即使 387 FPU 设置为 53 位精度 它也会保持超大的指数范围 强制检测每个中间结果的下溢 溢出 以及 使得很难避免
  • Python JSON AttributeError:“str”对象没有属性“read”

    我是 Python 初学者 Python 3 7 6 import json fil numbers json num with open fil r as file for obj in file num append json load
  • 如何用一个命令停止 mongo DB

    我需要能够在 cli 上启动 停止 MongoDB 开始非常简单 mongod 但要停止 mongo DB 我需要先运行 open mongo shell 然后键入两个命令 蒙戈 使用管理员 db shutdownServer 所以我不知道
  • shark不显示源代码

    我们正在尝试在 iPhone 应用程序上运行 shark 然而 在分析的样本中 它没有列出我们的任何应用程序功能 所有列出的都是库 当我们单击其中任何一个时 汇编代码都是可见的 大多数网站在构建应用程序时都会提到 生成调试符号 选项 我也找
  • 包括使用 Lambda 表达式

    在基于字符串的重载中Include我们指定包含一个集合 然后简单地通过以正确的顺序指定相关导航属性来包含下一层的引用 query Include Level1Collection Level2Reference 但是为什么当使用重载时Inc
  • Android 的自定义类加载器?

    我正在编写一个仪器库 我想在桌面和移动设备 Android 上使用它 它的功能是 公开一个带有单个参数的 main 即目标类的 main 安装一个类加载器 在加载所有类时拦截它们并对其进行检测 Like so Expects args 0
  • Electron打包后不支持ES6

    我正在使用各种ES6语法 http es6 features org 例如importETC React https reactjs org code JSX https reactjs org docs introducing jsx h
  • NEHotspotConfigurationManager 收到此警报:“无法加入网络<网络名称>”,而错误为零

    所以我试图通过关闭器监视连接状态 func reconnect success escaping gt Void failure escaping gt Void let manager NEHotspotConfigurationMana
  • 有没有办法摆脱 git status 中的帮助消息?

    Changes not staged for commit use git add
  • 如何从 Instagram API 获取访问令牌

    我一直在关注 Instagram 的基本指南https developers facebook com docs instagram basic display api guides getting access tokens and pe
  • 删除 t-sql 中所有大表的最佳方法是什么?

    我们遇到了一个有点奇怪的情况 基本上 我们的一个数据库中有两个表 其中包含大量我们不需要或不关心的日志信息 部分原因是我们的磁盘空间不足 我正在尝试清理表 但这需要很长时间 在周末运行后仍然有 57 000 000 多条记录 而这只是第一个
  • PageView 内的 InteractiveViewer

    我正在创建一个包含图像列表的 PageView 并且我想向每个图像添加 InteractiveViewer 以便可以调整其大小以查看详细信息 这是我写的 PageView builder dragStartBehavior DragStar