Flutter:gsy_flutter_demo项目学习——布局切换动画、列表滑动监听、列表滑动到指定位置、高斯模糊

前言

gsy_flutter_demo是一个关于各种小案例和小问题的方案解决。项目是由flutter大佬恋猫de小郭维护的

项目地址:https://github.com/CarGuo/gsy_flutter_demo

感兴趣的可以看一下大佬的文章:Flutter完整开发实战详解系列,GSY Flutter 系列专栏整合
在这里插入图片描述

关于该项目的学习呢,不会都学习,只会学习自己比较感兴趣的东西。

布局切换动画

动画效果

在这里插入图片描述
在这里插入图片描述

原文地址

Flutter 小技巧之有趣的动画技巧

代码

class YcHomeBody extends StatefulWidget {
  const YcHomeBody({Key? key, required this.width, required this.height})
      : super(key: key);
  // 容器的宽高
  final double width;
  final double height;
  
  State<YcHomeBody> createState() => _YcHomeBodyState();
}

class _YcHomeBodyState extends State<YcHomeBody>
    with SingleTickerProviderStateMixin {
  int currentIndex = 0;

  
  initState() {
    super.initState();

    //  创建吗一个定时器
    Timer.periodic(const Duration(seconds: 2), (timer) {
      setState(() {
        currentIndex += 1;
        if (currentIndex == 100) {
          currentIndex = 0;
        }
        // print("当前值:$currentIndex");
      });
    });
  }

  PositionedItemData getIndexPosition(int index, Size size) {
    switch (index) {
      case 0:
        return PositionedItemData(
          width: size.width / 2 - 5,
          height: size.height,
          left: 0,
          top: 0,
        );

      case 1:
        return PositionedItemData(
          width: size.width / 2 - 5,
          height: size.height / 2 - 5,
          left: size.width / 2 + 5,
          top: 0,
        );

      case 2:
        return PositionedItemData(
          width: size.width / 2 - 5,
          height: size.height,
          left: size.width / 2 + 5,
          top: size.height / 2 + 5,
        );
    }
    return PositionedItemData(
      width: size.width / 2 - 5,
      height: size.height,
      left: 0,
      top: 0,
    );
  }

  
  Widget build(BuildContext context) {
    return Center(
        child: Container(
      height: widget.height,
      width: widget.width,
      margin: const EdgeInsets.symmetric(horizontal: 20),
      // 根据父widget的约束条件来构建自身的布局,适合在需要根据父widget的约束条件来动态调整布局的场景中使用
      child: LayoutBuilder(
        builder: (BuildContext context, BoxConstraints constraints) {
          var f = getIndexPosition(currentIndex % 3, constraints.biggest);
          var s = getIndexPosition((currentIndex + 1) % 3, constraints.biggest);
          var t = getIndexPosition((currentIndex + 2) % 3, constraints.biggest);
          return Stack(
            fit: StackFit.expand,
            children: [
              // InkWell为其子widget提供水波纹效果和触摸事件处理
              PositionItem(f,
                  child: InkWell(
                    onTap: () {
                      // print("red");
                    },
                    child: Container(color: Colors.redAccent),
                  )),
              PositionItem(s,
                  child: InkWell(
                    onTap: () {
                      //print("green");
                    },
                    child: Container(color: Colors.greenAccent),
                  )),
              PositionItem(t,
                  child: InkWell(
                    onTap: () {
                      // print("yello");
                    },
                    child: Container(color: Colors.yellowAccent),
                  )),
            ],
          );
        },
      ),
    ));
  }
}

class PositionItem extends StatelessWidget {
  final PositionedItemData data;
  final Widget child;

  const PositionItem(this.data, {Key? key, required this.child})
      : super(key: key);

  
  Widget build(BuildContext context) {
    // AnimatedPositioned 用于动画定位位置的widget
    return AnimatedPositioned(
      duration: const Duration(seconds: 1), // 动画持续时间
      curve: Curves.fastOutSlowIn, // 动画曲线
      left: data.left,
      top: data.top,
      // AnimatedContainer,根据指定的时间段自动过渡其属性,用于实现大小的过渡
      child: AnimatedContainer(
        duration: const Duration(seconds: 1),
        curve: Curves.fastOutSlowIn,
        width: data.width,
        height: data.height,
        child: child,
      ),
    );
  }
}

// 用于规范元素的宽高和位置
class PositionedItemData {
  final double left;
  final double top;
  final double width;
  final double height;

  PositionedItemData({
    required this.left,
    required this.top,
    required this.width,
    required this.height,
  });
}

使用

YcHomeBody(width: 240, height: 300,)

列表滑动监听

class _MyHomePageState extends State<MyHomePage> {
  // 是否到底
  bool isEnd = false;
  // 偏移量
  int offset = 0;
  // 通知
  String notify = '';
  // 列表container
  final ScrollController _controller = ScrollController();

  
  void initState() {
    super.initState();

    _controller.addListener(() {
      setState(() {
        // 这里进行取整,不然小数位数太多
        offset = _controller.offset.floor();
        // 判断当前滚动位置的像素值是否等于可滚动区域最大值
        isEnd =
            _controller.position.pixels == _controller.position.maxScrollExtent;
      });
    });
  }

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: Text(widget.title),
      ),
      body: NotificationListener(
          onNotification: (dynamic notification) {
            // 在这里处理滚动通知
            if (notification is ScrollStartNotification) {
              // 滚动开始
              notify = "滚动开始";
            } else if (notification is ScrollUpdateNotification) {
              // 滚动更新
              notify = "滚动更新";
            } else if (notification is ScrollEndNotification) {
              // 滚动结束
              notify = "滚动结束";
            }
            setState(() {});
            // 返回true表示阻止通知冒泡,返回false则继续向上传递通知
            return false;
          },
          child: ListView.builder(
              itemCount: 100,
              controller: _controller,
              itemBuilder: (context, index) {
                return Card(
                    child: Container(
                  height: 60,
                  alignment: Alignment.centerLeft,
                  child: Text("Item $index"),
                ));
              })),
      // 页脚按钮
      persistentFooterButtons: [
        Align(
          alignment: Alignment.center,
          child: Text("通知:$notify,偏移量:$offset,到达底部:${isEnd ? '是' : '否'}"),
        )
      ], // This trailing comma makes auto-formatting nicer for build methods.
    );
  }
}

在这里插入图片描述
NotificationListener是一个widget,用于监听并处理各种通知。它可以将通知分发给子widget,并根据需要执行相应的操作

列表滑动到指定位置

作者提供了两种实现方式,一种是使用第三库,另一种是需要自己进行计算。本着能使用第三方库就使用第三库的原则,我们使用第三库来实现。

官方地址
https://pub-web.flutter-io.cn/packages/scroll_to_index

安装

flutter pub add scroll_to_index
class _MyHomePageState extends State<MyHomePage> {
  // 列表container
  late final AutoScrollController _controller;

  // 列表项高度,100~300间的整数
  List<int> items =
      List.generate(50, (index) => 100 + math.Random().nextInt(300 - 100));

  
  void initState() {
    super.initState();
    //  初始化
    _controller = AutoScrollController(
        viewportBoundaryGetter: () => Rect.fromLTRB(0, 0, 0,
            MediaQuery.of(context).padding.bottom), // 获取底部边界值,保证滚动到底部时,内容不会被遮挡
        axis: Axis.vertical);
  }

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: Text(widget.title),
      ),
      body: ListView.builder(
          itemCount: 50,
          controller: _controller,
          itemBuilder: (context, index) {
            return AutoScrollTag(
                key: ValueKey(index),
                controller: _controller,
                index: index,
                highlightColor: Colors.black.withOpacity(0.1),
                child: Container(
                  height: items[index] + 0.0,
                  alignment: Alignment.topCenter,
                  margin: const EdgeInsets.all(10),
                  decoration: BoxDecoration(
                      border: Border.all(color: Colors.blue, width: 1),
                      borderRadius: BorderRadius.circular(10)),
                  child: Text("items ${index + 1},height:${items[index]}"),
                ));
          }),
      // 页脚按钮
      persistentFooterButtons: [
        ElevatedButton(
            onPressed: () async {
              // 滚动
              await _controller.scrollToIndex(0,
                  preferPosition: AutoScrollPosition.begin); // 以列表的上边框为准
              //   高亮
              _controller.highlight(0);
            },
            child: const Text("第1个")),
        ElevatedButton(
            onPressed: () async {
              // 滚动
              await _controller.scrollToIndex(19,
                  preferPosition: AutoScrollPosition.begin);
              //   高亮
              _controller.highlight(19);
            },
            child: const Text("第20个"))
      ], // This trailing comma makes auto-formatting nicer for build methods.
    );
  }
}

在这里插入图片描述

高斯模糊

Stack(
        children: [
          Positioned(
              child: Image.network(
            'https://scpic2.chinaz.net/files/default/imgs/2023-07-24/f81ebfa03646059a_s.jpg',
            fit: BoxFit.fill,
            width: MediaQuery.of(context).size.width,
            height: MediaQuery.of(context).size.height,
          ),
          ),
        //  高斯模糊
          Center(
            child: SizedBox(
              width: 300,
              height: 300,
              child: ClipRRect(
              borderRadius: BorderRadius.circular(15.0),
                child: BackdropFilter(
                  // 设置视频和垂直方向的模糊程度
                  filter: ImageFilter.blur(sigmaX: 8.0,sigmaY: 8.0),
                  child: const Text("高斯模糊"),
                ),
              ),
            ),
          )
        ],
      )

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/58155.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Excel中——日期列后添加星期

需求&#xff1a;在日期列中添加星期几&#xff1f; 第一步&#xff1a;打开需要添加星期的Excel文件&#xff0c;在日期后面添加日期 第二步&#xff1a;选择日期列&#xff0c;点击鼠标右键&#xff0c;在下拉列表中&#xff0c;选择“设置单元格格式” 第三步&#xff1a; 在…

【数据分析】Numpy (一)

目录 1.Numpy简介&#xff1a; Numpy用途&#xff1a; 2.Numpy的简单使用&#xff1a; 2.1导入Numpy&#xff1a; 2.1查看numpy的版本&#xff1a; ​编辑3.NumPy - Ndarray 对象 3.1ndarray属性&#xff1a; 3.2 numpy.array参数构造 3.3创建numpy数组&#xff1a; 3.4num…

以指标驱动,保险、零售、制造企业开启精益敏捷运营的新范式

近日&#xff0c;以“释放数智生产力”为主题的 Kyligence 用户大会在上海前滩香格里拉大酒店成功举行。大会包含上午的主论坛和下午的 4 场平行论坛&#xff0c;并举办了闭门会议、Open Day 等活动。来自金融、零售、制造、医药等行业的客户及合作伙伴带来了超过 23 场主题演讲…

微信小程序wx.getlocation接口权限申请总结

先附上申请通过截图 插播内容&#xff1a;可代开通&#xff0c;保证通过。wx.getLocation接口&#xff08;获取当前的地址位置&#xff09; qq&#xff1a; 308205428 如何申请 当申请微信小程序的wx.getLocation接口权限时&#xff0c;你可以…

华为PMS API client token auth failed

对接华为pms时出现问题&#xff0c;提示华为PMS API client token auth failed 主要是权限的问题&#xff0c;创建项目的时候选择N/A

上海市第十人民医院胃肠外科沈通一:以菌为药,非药而愈

6月29日&#xff0c;2023主动健康与临床营养高峰论坛在西安国际会展中心盛大召开&#xff0c;会议汇集了来自国内医学与营养领域杰出的专家学者&#xff0c;交流分享行业的先进理念和研究成果&#xff0c;为主动营养业界与学界能量交换搭建了新接口&#xff0c;以凝聚学术力量&…

采购分析:节省采购成本的 6 种方法

为了成功启动采购计划、稳定现金流并节省开支&#xff0c;企业需要了解从采购到付款的 P2P 周期的方方面面。 有远见的采购领导者将采购分析作为综合战略的一部分。因其有助于以简化和自动化的方式解决问题&#xff0c;从而更好地管理项目并节省大量成本。 什么是采购分析&am…

jenkins gitlab多分支构建发布

内容背景介绍 这个是新手教程,普及概念为主 公司现在还使用单分支发布测试环境和生产,多人协同开发同一个项目导致测试环境占用等待等情况 测试环境占用等待问题 测试环境代码直接合并到 master,容易导致误发布到生产的情况 避免多版本同时发布测试不完善的情况出现 中间件…

Rust dyn - 动态分发 trait 对象

dyn - 动态分发 trait 对象 dyn是关键字&#xff0c;用于指示一个类型是动态分发&#xff08;dynamic dispatch&#xff09;&#xff0c;也就是说&#xff0c;它是通过trait object实现的。这意味着这个类型在编译期间不确定&#xff0c;只有在运行时才能确定。 practice tr…

Node.js-http模块服务端请求与响应操作,请求报文与响应报文

简单案例创建HTTP服务端&#xff1a; // 导入 http 模块 const http require("http"); // 创建服务对象 const server http.createServer((request, response) > {// 设置编码格式&#xff0c;解决中文乱码问题response.setHeader("content-type", &…

MySQL安装详细教程!!!

安装之前&#xff0c;先卸载你之前安装过的数据库程序&#xff0c;否则会造成端口号占用的情况。 1.首先下载MySQL:MySQL :: Download MySQL Community Server(下载路径) 2.下载版本不一样&#xff0c;安装方法略有不同&#xff1b;&#xff08;版本5的安装基本一致&#xff0c…

启动Flink显示初始化状态怎么解决?

启动Flink显示初始化状态怎么解决&#xff1f; Flink On Yarn模式 问题 flnk任务在跑的过程中&#xff0c; 有时候任务停掉了 &#xff0c;不过我有 定时任务&#xff0c;可以把失败的flink任务拉起来&#xff0c;但是因为最新的checkpoint做失败了&#xff0c;导致脚本无法拉…

LabVIEW开发高压航空航天动力系统爬电距离的测试

LabVIEW开发高压航空航天动力系统爬电距离的测试 更多电动飞机MEA技术将发电&#xff0c;配电和用电集成到一个统一的系统中&#xff0c;提高了飞机的可靠性和可维护性。更多的电动飞机使用更多的电能来用电动替代品取代液压和气动系统。对车载电力的需求不断增加&#xff0c;…

【LeetCode】234.回文链表

题目 给你一个单链表的头节点 head &#xff0c;请你判断该链表是否为回文链表。如果是&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 示例 1&#xff1a; 输入&#xff1a;head [1,2,2,1] 输出&#xff1a;true示例 2&#xff1a; 输入&#xff1a;hea…

为机器人装“大脑” 谷歌发布RT-2大模型

大语言模型不仅能让应用变得更智能&#xff0c;还将让机器人学会举一反三。在谷歌发布RT-1大模型仅半年后&#xff0c;专用于机器人的RT-2大模型于近期面世&#xff0c;它能让机器人学习互联网上的文本和图像&#xff0c;并具备逻辑推理能力。 该模型为机器人智能带来显著升级…

【BASH】回顾与知识点梳理(四)

【BASH】回顾与知识点梳理 四 四. Bash Shell 的操作环境4.1 路径与指令搜寻顺序4.2 bash 的进站与欢迎讯息&#xff1a; /etc/issue, /etc/motd4.3 bash 的环境配置文件login与non-login shell/etc/profile (login shell 才会读)~/.bash_profile (login shell 才会读)source &…

【多模态】20、OVR-CNN | 使用 caption 来实现开放词汇目标检测

文章目录 一、背景二、方法2.1 学习 视觉-语义 空间2.2 学习开放词汇目标检测 三、效果 论文&#xff1a;Open-Vocabulary Object Detection Using Captions 代码&#xff1a;https://github.com/alirezazareian/ovr-cnn 出处&#xff1a;CVPR2021 Oral 一、背景 目标检测数…

【JVM】(三) 深入理解JVM垃圾回收机制(GC)

文章目录 前言一、死亡对象的判断方法1.1 引用计数算法1.2 可达性分析算法 二、垃圾回收算法2.1 标记-清除算法2.2 复制算法2.3 标记-整理算法2.5 分代算法2.6 Minor GC 和 Major GC 前言 JVM 的垃圾回收机制&#xff08;Garbage Collection&#xff09;是 Java 中的重要特性之…

单元测试之 - Review一个微服务的单元测试

这里以github上一个microservice的demo代码为例&#xff0c;来看看如何为一个完整的服务编写单元测试。具体代码如下所示&#xff0c;我们重点查看一下catalog和customer&#xff0c;order中的单元测试有哪些。 首先来看catalog服务的单元测试,这个服务下面主要编写了CatalogWe…

无涯教程-Lua - 变量声明

变量的名称可以由字母&#xff0c;数字和下划线字符组成。它必须以字母或下划线开头&#xff0c;由于Lua区分大小写&#xff0c;因此大写和小写字母是不同的。 在Lua中&#xff0c;尽管无涯教程没有变量数据类型&#xff0c;但是根据变量的范围有三种类型。 全局变量(Global) …