颤动|如何知道小部件是否位于导航堆栈顶部(可见)

2024-04-27

在我的 Flutter 应用程序中,如果将新页面推送到导航堆栈,我希望暂停动画。

问题:从小部件的角度来看,有什么方法可以知道小部件是否位于导航堆栈的顶部?

Example:

while (isTopOfNavigationStack) {
    // Do the animation
}

编辑1:更多细节

我正在使用图书馆小部件选框 https://pub.dev/packages/widget_marquee用于创建水平行情自动收录器。在将新页面推送到导航堆栈之前,该库一直运行良好。当这种情况发生时,while-loop变得无限并且应用程序冻结。

library widget_marquee;

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

/// Rotates the [child] widget indefinitely along the horizontal axis if the
/// content extends pass the edge of the render area.
///
/// [delayDuration] - One time delay to wait before starting the text rotation
/// [gap] - Spacing to add between widget end and start
/// [loopDuration] - Time for one full rotation of the child
/// [onLoopFinish] - Function to run upon finishing each loop
/// [onScrollingTap]
/// [pixelsPerSecond] - Alternate to loop duration
class Marquee extends StatelessWidget {
  const Marquee({
    Key? key,
    required this.child,
    this.delayDuration = const Duration(milliseconds: 1500),
    this.gap = 50,
    this.loopDuration = const Duration(milliseconds: 8000),
    this.onLoopFinish = _onLoopFinish,
    this.onScrollingTap = _onScrollingTap,
    this.pixelsPerSecond = 0,
  }) : super(key: key);

  final Widget child;
  final Duration delayDuration;
  final double gap;
  final Duration loopDuration;
  final Future<void> Function() onLoopFinish;
  final Future<void> Function() onScrollingTap;
  final int pixelsPerSecond;

  @override
  Widget build(BuildContext context) {
    return _Marquee(
      key: UniqueKey(),
      child: child,
      delay: delayDuration,
      gap: gap,
      loopDuration: loopDuration,
      onLoopFinish: onLoopFinish,
      onScrollingTap: onScrollingTap,
      pps: pixelsPerSecond,
    );
  }
}

class _Marquee extends StatefulWidget {
  const _Marquee({
    required Key key,
    required this.child,
    required this.delay,
    required this.gap,
    required this.loopDuration,
    required this.onLoopFinish,
    required this.onScrollingTap,
    required this.pps,
  }) : super(key: key);

  final Widget child;
  final Duration delay;
  final double gap;
  final Duration loopDuration;
  final Future<void> Function() onLoopFinish;
  final Future<void> Function() onScrollingTap;
  final int pps;

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

class _MarqueeState extends State<_Marquee> with TickerProviderStateMixin {
  late double contentArea;
  bool isScrolling = false;
  late ScrollController scrollController;
  List<Widget> widgets = <Widget>[];


  @override
  void initState() {
    super.initState();
  }

  @override
  void didChangeDependencies() {
    scrollController = ScrollController(
      initialScrollOffset: 0.0,
      keepScrollOffset: false,
    );

    widgets = <Widget>[widget.child];

    // Initialize the scroll controller

    WidgetsBinding.instance?.addPostFrameCallback(scroll);
    super.didChangeDependencies();
  }

  void scroll(_) async {
    if (scrollController.position.maxScrollExtent > 0) {
      late Duration duration;
      final double initMax = scrollController.position.maxScrollExtent;

      // Add a sized box and duplicate widget to the row
      setState(() {
        widgets.add(SizedBox(width: widget.gap));
        widgets.add(widget.child);
      });

      await Future<dynamic>.delayed(widget.delay);

      try {
        setState(() {
          isScrolling = true;
        });

        while (scrollController.hasClients) {

          // Calculate the position where the duplicate widget lines up with the original
          final scrollExtent =
              (initMax * 2) - (initMax - contentArea) + widget.gap;

          // Set the duration of the animation
          if (widget.pps <= 0) {
            duration = widget.loopDuration;
          } else {
            duration = Duration(
              // Calculate the duration based on the pixels per second
              milliseconds: ((scrollExtent / widget.pps) * 1000).toInt(),
            );
          }

          await scrollController.animateTo(
            scrollExtent,
            duration: duration,
            curve: Curves.linear,
          );

          // Jump to the beginning of the view to imitate loop
          scrollController.jumpTo(0);
          await widget.onLoopFinish();
        }
      } catch (e) {
        log('Marquee element has been disposed');
      }
    }
  }

  @override
  Widget build(BuildContext context) {
    return LayoutBuilder(
      builder: (BuildContext context, BoxConstraints constraints) {
        contentArea = constraints.maxWidth;

        // Thanks to how widgets work, the gesture detector is only triggered
        // if there's nothing clickable in the child
        return GestureDetector(
          onTap: () async {
            if (isScrolling) {
              await widget.onScrollingTap();
            }
          },
          child: Container(
            alignment: Alignment.center,
            child: SingleChildScrollView(
              physics: const NeverScrollableScrollPhysics(),
              child: Row(
                children: widgets,
              ),
              scrollDirection: Axis.horizontal,
              controller: scrollController,
            ),
          ),
        );
      },
    );
  }

  @override
  void dispose() {
    scrollController.dispose();
    super.dispose();
  }
}

Future<void> _onLoopFinish() async {}

Future<void> _onScrollingTap() async {
  log('Marquee onScrollingTap function triggered');
}

您可以通过以下方式了解当前路线是否是导航中的首要路线ModalRoute.of(context)?.isCurrent。在你的例子中应该是这样的

final _isTopOfNavigationStack = ModalRoute.of(context)?.isCurrent ?? false;

while (_isTopOfNavigationStack) {
    // Do the animation
}

Check 这个答案 https://stackoverflow.com/questions/54311407/how-to-check-if-a-widget-page-is-rendered如果您需要更多详细信息。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

颤动|如何知道小部件是否位于导航堆栈顶部(可见) 的相关文章

随机推荐

  • 如何在 r 中没有警告消息的情况下知道 lme4 中模型是否收敛或未能收敛?

    重复的 例如 我可以通过以下方式评估这个多级模型是否是单一拟合 使用isSingular 功能 同样 有什么方法可以知道这个模型是收敛还是失败 我的顾问说 如果模型无法收敛 则不会估计标准误差 然而 尽管以下未能收敛 但似乎估计了标准误差
  • 根据当前配置,没有映射 Doctrine ORM 实体

    我有一个可疑的问题 我有一组现有的带注释的 Doctrine 实体 它们已在 Symfony2 Doctrine2 项目中成功使用 然而 我目前正在将该项目的一些核心功能隔离到它自己的 Web 框架独立库中 但我似乎无法让这些实体正常运行
  • 如何从 Swift NSURLSession 获取数据?

    例如 我有以下代码 let task NSURLSession sharedSession dataTaskWithURL url completionHandler data response error gt Void in var d
  • 如何像 urllib 这样的模拟/存根 python 模块

    我需要测试一个需要使用 urllib urlopen 它也使用 urllib urlencode 查询外部服务器上的页面的函数 服务器可能宕机 页面可能发生变化 我不能依赖它进行测试 控制 urllib urlopen 返回内容的最佳方法是
  • 限制 SFTP 用户只能访问主目录

    我正在尝试在 EC2 ubuntu 服务器上设置客户端 SFTP 空间 访问权限仅限于该用户的主目录 关于此的其他主题只有大约六千个 而且我在其他选项卡中打开了其中的大多数主题 这看起来很简单 我已经搞定了 sudo groupadd lo
  • 如何将 MNIST 图像下载为 PNG

    我想将 MNIST 图像作为 PNG 文件下载到我的计算机上 我找到了这个页面 http yann lecun com exdb mnist http yann lecun com exdb mnist 我按下后 train images
  • 安装插件时出错:“无法获取框架操纵器服务”

    在我的 Windows XP 计算机上使用 Eclipse Helios 的 RCP 版本 我尝试从标准更新站点安装一些相当基本的插件 例如 PyDev 和 EPIC 不幸的是 我不断收到以下错误消息 An error occurred w
  • 在 Laravel 5 中创建“设置”模型的最佳实践是什么?

    这是我使用 Laravel 的第一个项目 我从 5 2 开始 我正在建立一个自我管理的网站 有一个管理员应该保存网站设置以供以后在网站中使用 例如 背景颜色 社交网络 图片轮播 产品等 我的第一次尝试是创建一个模型 设置 id key un
  • MATLAB 黑洞变量

    MATLAB 是否有 黑洞 或丢弃变量 假设我正在做类似的事情 rows cols size A 但我不想存储行 是否有一个 黑洞 变量可以让我发送值去死 所以任务就像 BLACKHOLE cols size A 其中 BLACKHOLE
  • Eclipse 中的预构建事件

    我有一个使用 jaxb 进行一些 xml 处理的项目 如何在 eclipse 中设置预构建事件以在构建项目之前执行 xjc 转到项目 gt 属性 gt 构建器 创建您自己的构建器并启用它 并在构建器的配置中启用 自动构建期间 等 如下所示
  • SQL部署自动化

    我正在尝试使用 Jenkins 自动化现有的 sql server 数据库部署自动化 自动化的方法之一是使用 Visual Studio 将 SQL 脚本 存储过程 视图 表创建 包含在 SQL Server 数据库项目中 使用 MSBui
  • 使用 Github for Windows 通过 SSH 处理自己的私有 Git

    现在 我正在使用 msysgit 来使用 SSH 来处理存储在 ec2 Amazon 云服务器上的我自己的私有存储库 到目前为止 我已经能够通过 Git Bash 成功连接到这些存储库 使用 ssh keygen 创建 ssh rsa 公钥
  • 当对象创建或修改 JavaScript 中的键/值时,有没有办法触发回调? [复制]

    这个问题在这里已经有答案了 我试图弄清楚如何在 JavaScript 中创建一个对象 该对象将在创建和更改任意键 值时触发事件 这是一些伪代码 var User function var user function keyAdded tri
  • DT::datatable 的背景颜色闪亮

    如何在闪亮的应用程序中更改数据表中选定行的背景颜色 我的 ui R 有以下代码 library shinydashboard header lt dashboardHeader title title sidebar lt dashboar
  • 如何使用 Twitter Bootstrap API 检测您正在使用哪个设备视图?

    我刚刚开始为我即将开展的项目使用 Twitter Bootstrap API 主导航包含 3 个主要元素 site nav 社交链接导航 搜索网站表格 在移动设备上查看网站时 我使用折叠插件折叠网站导航和搜索表单 移动视图有 2 个按钮 单
  • 静态、非成员或静态非成员函数?

    每当我有一些 实用 方向的功能时 我最终都会想知道哪个选项是最好的 例如 在我正在工作的上下文中打印消息结构 自己的或外部的 一些编码 解码代码或一些有用的转换函数 我想到的选项是 1 辅助类 结构中的静态函数 struct helper
  • 在 Google Play 中更新 APK 而不更改扩展文件

    我的 Google Play 控制台中有一个 草稿 APK 它已连接到 APK 扩展文件 版本号为9 扩展文件为 main 9 com something something obb 现在 我正在尝试在发布之前更新 APK 我增加了版本代码
  • Kubernetes 仪表板 - ServiceUnavailable(503 错误)

    我是 Kubernetes 新手 我正在尝试使用 kops 在 AWS 上设置 Kubernetes 集群 我成功地设置了集群 但是 我无法访问仪表板 UI https kubernetes io docs tasks access app
  • 如何低延迟地使用 Android 音频

    Problem 您可能听说过 Android 不提供低延迟音频 API 我所说的低延迟音频是指您应该能够从麦克风获取音频信号并播放声音 中间没有太多时间间隔 例如 5 7 毫秒 我尝试过旧的java 带有AudioRecord和AudioT
  • 颤动|如何知道小部件是否位于导航堆栈顶部(可见)

    在我的 Flutter 应用程序中 如果将新页面推送到导航堆栈 我希望暂停动画 问题 从小部件的角度来看 有什么方法可以知道小部件是否位于导航堆栈的顶部 Example while isTopOfNavigationStack Do the