FlutterUnit 基于 TolyUI 大大简化了界面构建的代码复杂程度,因此之前想要实现的一些小功能,就可以轻松支持。布局游乐场是通过交互的方式来 直观体验 组件的布局特性,从而更易学和掌握。目前 FlutterUnit 已在 知识集录模块新增了 布局宝库, 大家可以更新代码查看 ~


1. 什么是布局游乐场

对于新手朋友,对有些较复杂的布局组件很难把握其特性。为此 FlutterUnit 设立了 布局宝库 模块,来帮助开发者更容易理解 Flutter 中的布局特性以及核心的布局组件。其中的 Playground 指的是可交互操作的组件展示面板,如下的 Flex Playground 将淋漓尽致地展示 Flex 组件布局特性。

在这里插入图片描述

Playground 实现过程中,依赖了很多 TolyUI 中的组件:

  • 对于枚举类型的参数,通过 TolySelect 组件处理选择事件。
  • 操作的图标按钮使用 TolyAction 组件。
  • 布局宝库的侧栏导航,使用 TolyRailMenuTree 组件。

目前已经完成了 Flex、Wrap、Stack 三个多字布局的 Playground 。可以在操作面板中增加/删除,指定宽高的色块。来更好的体验组件的布局效果。

在这里插入图片描述


2. Flex Playground 功能实现 - 数据层

下面以 Flex Playground 来介绍一下功能实现。一个 Playground 主要包括两个区域:左侧的组件 效果展示区 和右侧的 操作面板区。其中右侧的交互操作会影响左侧的效果展示:

image.png

我们知道 Flutter 中,数据决定界面的表现,首先应该确定 Flex Playground 中依赖了哪些数据。当前功能是通过交互修改 Flex 组件的属性,所以 Flex 组件的属性内容是一份需要维护的状态。通过下面的 FlexAttr 类承载各个属性数据:

class FlexAttr {final Axis direction;final MainAxisAlignment mainAxisAlignment;final CrossAxisAlignment crossAxisAlignment;final MainAxisSize mainAxisSize;final TextDirection textDirection;final VerticalDirection verticalDirection;final TextBaseline textBaseline;

另外,需要若干个色块,它们有各自的宽度和高度,通过 DisplayItem 类承载相关数据:

class DisplayItem {final double width;final double height;final Color color;

这样 Flex Playground 中的状态数据就呼之欲出了:

  • [1] . DisplayItem 列表数据,记录色块信息。
  • [2]. _selectIndex 选中的色块索引,用于删除色块。
  • [3]. FlexAttr 数据,决定 Flex 组件的展示效果。
class _FlexPlaygroundState extends State<FlexPlayground> {List<DisplayItem> _data = [];late FlexAttr _attr;int _selectIndex = -1;

3. Flex Playground 功能实现 - 视图层

左侧的布局效果展示区封装为如下的 FlexDisplay 组件,依赖三个状态数据,通过 Flex 组件来构建展示内容。其中,

  • Flex 构造函数中的各个属性由 FlexAttr 数据提供;
  • children 组件由 List<DisplayItem> 数据映射得到;
  • 色块的选中事件,通过 onSelectChanged 回调,交由使用者处理,更新激活索引。

image.png

class FlexDisplay extends StatelessWidget {final List<DisplayItem> items;final FlexAttr attr;final int selectIndex;final ValueChanged<int> onSelectChanged;const FlexDisplay({super.key,required this.items,required this.attr,required this.selectIndex,required this.onSelectChanged,});Widget build(BuildContext context) {return Flex(direction: attr.direction,mainAxisAlignment: attr.mainAxisAlignment,crossAxisAlignment: attr.crossAxisAlignment,mainAxisSize: attr.mainAxisSize,textDirection: attr.textDirection,verticalDirection: attr.verticalDirection,textBaseline: TextBaseline.alphabetic,children: items.asMap().keys.map((int index) {bool active = selectIndex == index;return GestureDetector(onTap: () => onSelectChanged(index),child: DisplayPlayItem(item: items[index], selected: active),);}).toList(),);}
}

右侧的操作面板需要支持交互操作,通过触发事件来更新状态数据,然后更新界面,即可实现我们期望的功能。Flex 组件的属性中有很多枚举值,这比较适合使用下拉选择来处理。Flutter 中自带的选择器在桌面端的体验效果并不是很好,于是 TolyUI 中提供了 TolySelect 组件,便于构建类似的选择功能:

image.png

右侧的面板通过 FlexOpTool 组件展示,其中添加、删除、重置的按钮事件,分别通过回调交由使用者处理。另外属性操作时数据的变化,也会通过 ValueChanged 通知外界进行数据处理。也就是说 FlexOpTool 本身并不参与状态数据的维护逻辑。只负责基于数据构建界面,以及数据变化时的回调通知:

class FlexOpTool extends StatefulWidget {final ValueChanged<Size> onAddBox;final VoidCallback onDelete;final VoidCallback onReset;final FlexAttr attr;final ValueChanged<FlexAttr> onAttrChange;

这里着重介绍一下选择器的使用, TolySelect 主要通过 String 列表 data 和激活索引 selectIndex 决定菜单项羽和激活项;通过 cellStyle 可以简单定制菜单项的展示效果。由于这里选择器的使用场合非常多,所以封装了 ItemSelector 组件统一处理标题、布局等效果:

image.png

typedef NameCalc<T> = String Function(T data);class ItemSelector<T> extends StatelessWidget {final int selectIndex;final List<T> data;final NameCalc<T> calcFun;final ValueChanged<T> onSelect;final String label;final String subTitle;const ItemSelector({super.key,required this.selectIndex,required this.data,required this.calcFun,required this.onSelect,required this.subTitle,required this.label,});Widget build(BuildContext context) {TextStyle labelStyle = const TextStyle(color: Color(0xff61666d), fontSize: 12);DropMenuCellStyle lightStyle = const DropMenuCellStyle(padding: EdgeInsets.symmetric(horizontal: 4,vertical: 1),borderRadius: BorderRadius.all(Radius.circular(6)),foregroundColor: Color(0xff1f1f1f),backgroundColor: Colors.transparent,disableColor: Color(0xffbfbfbf),hoverBackgroundColor: Color(0xfff5f5f5),hoverForegroundColor: Color(0xff1f1f1f),textStyle: TextStyle(fontSize: 11));return Padding(padding: const EdgeInsets.symmetric(horizontal: 8.0, vertical: 6),child: Row(children: [Column(crossAxisAlignment: CrossAxisAlignment.start,children: [Text(label, style: labelStyle),Text(subTitle, style: labelStyle.copyWith(fontSize: 8)),],),const Spacer(),TolySelect(fontSize: 11,cellStyle: lightStyle,data: data.map((e) => calcFun(e)).toList(),selectIndex: selectIndex,iconSize: 16,height: 25,width: 110,maxHeight: 200,onSelected: (int index) => onSelect(data[index]),)],),);}
}

4. Flex Playground 功能实现 - 数据逻辑层

FlexOpTool 提供了交互过程中数据变化的时机,使用者需要在对应的时机来维护状态数据的正确性。

image.png

如下所示,_onAddBox 方法,会在 DisplayItem 列表中增加一个色块,触发 setState 重新构建;_deleteSelectIndex 方法将移除对应索引的色块,并重新构建更新界面:

void _onAddBox(Size size) {int index = _data.length + 1;Color color = kColors[index % kColors.length];_data.add(DisplayItem(width: size.width, height: size.height, color: color));setState(() {});
}void _deleteSelectIndex() {if (_selectIndex < 0 || _selectIndex >= _data.length) {$message.warning(message: '请先选择删除的色块!');return;}_data.removeAt(_selectIndex);_selectIndex = -1;setState(() {});
}

当属性数据变化,通过 _onAttrChange 方法更新 _attr 数据即可;重置回调时,将三个状态数据设为初始值:

void _onAttrChange(FlexAttr attr) {setState(() {_attr = attr;});
}void _reset({bool init=false}){_attr = FlexAttr(direction: Axis.horizontal);_data = [DisplayItem(width: 20, height: 20, color: kColors[0]),DisplayItem(width: 10, height: 80, color: kColors[1]),DisplayItem(width: 40, height: 30, color: kColors[2]),DisplayItem(width: 60, height: 20, color: kColors[3]),];_selectIndex = -1;if(init) return;setState(() {});
}

这就是 Flex Playground 功能的核心实现过程,紧紧把握 状态数据组件构建交互事件数据维护 四个方面,就可以很轻松地完成任何功能需求。其他的 Playground 实现方式类似,就不一一介绍了,希望大家可以在 布局游乐场 中,通过交互的方式,学习更多知识。
以后,FlutterUnit 将在 TolyUI 的加持下,支持更多的好玩和使用的功能,敬请期待~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/910431.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/910431.shtml
英文地址,请注明出处:http://en.pswp.cn/news/910431.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【数据分析一:Data Collection】信息检索

本节内容含有各典型数据集的推荐&#xff0c;以及其网址&#xff0c;大家根据需要自取 一、检索 最简单、最灵活的数据获取方式就是依靠检索&#xff1a; Google&#xff1a;更适合搜索英文信息 Google Dataset Search&#xff08;Google 数据集搜索&#xff09; 网址&…

23.ssr和csr的对比?如何依赖node.js实现

1.为什么说ssr 的node中间层请求速度快。相当于内网&#xff1f; 那vue.js加载怎么没有ssr和csr的说法啊 第一问&#xff1a;为什么说 SSR 的 Node 中间层请求速度快&#xff1f;是不是相当于内网&#xff1f; ✅ 是的&#xff0c;本质上就是「内网请求」&#xff0c;所以更快…

力扣刷题(第六十四天)

灵感来源 - 保持更新&#xff0c;努力学习 - python脚本学习 第一个错误的版本 解题思路 初始化左右边界&#xff1a;左边界 left 1&#xff0c;右边界 right n。二分查找循环&#xff1a; 计算中间版本号 mid。若 mid 是错误版本&#xff0c;说明第一个错误版本在 [le…

【图像处理入门】11. 深度学习初探:从CNN到GAN的视觉智能之旅

摘要 深度学习为图像处理注入了革命性动力。本文将系统讲解卷积神经网络(CNN)的核心原理,通过PyTorch实现图像分类实战;深入解析迁移学习的高效应用策略,利用预训练模型提升自定义任务性能;最后揭开生成对抗网络(GAN)的神秘面纱,展示图像生成与增强的前沿技术。结合代…

C++法则4: 如果一个构造函数的第一个参数是自身类类型的引用,且任何额外参数都有默认值,则此构造函数是拷贝构造函数。

C法则4&#xff1a; 如果一个构造函数的第一个参数是自身类类型的引用&#xff0c;且任何额外参数都有默认值&#xff0c;则此构造函数是拷贝构造函数。 拷贝构造函数的定义&#xff1a; 第一个参数是自身类类型的引用&#xff1a; 必须是引用&#xff08;通常为const引用&…

从头搭建环境安装k8s遇到的问题

基本信息 master节点IP&#xff1a; 172.31.0.3 node01节点IP&#xff1a;172.31.0.4 node02节点IP&#xff1a;172.31.0.5 子网掩码&#xff1a;255.255.0.0 网关&#xff1a;172.31.0.2 DNS:114.114.114.114 安装前要检查的信息 检查三台主机的mac地址是否重复&#xff1a…

Flask入门指南:从零构建Python微服务

1. Flask 是什么&#xff1f; Flask 是一个 微框架&#xff08;Microframework&#xff09;&#xff0c;特点包括&#xff1a; 轻量灵活&#xff1a;核心仅包含路由和模板引擎&#xff0c;其他功能通过扩展实现易于学习&#xff1a;代码直观&#xff0c;适合快速开发小型应用…

【LINUX网络】网络socet接口的基本使用以及实现简易UDP通信

根据本系列上两篇关于网络的初识介绍&#xff0c;现在我们开始实现一个UDP接口&#xff0c;以加强对该接口的理解。 1 . 服务器端 在本篇中&#xff0c;主要按照下面内容来实现&#xff1a; 创建并封装服务端&#xff1a;了解创建服务端的基本步骤 创建并封装客户端&#xff0…

MySQL的索引事务

索引 是什么 类似于目录&#xff0c;提高查询的速度&#xff0c;但是本身会占用空间&#xff0c;增删数据的时候也需要维护索引。所以查询操作频繁的时候可以创建索引。如果非条件查询列&#xff0c;或经常做插入、修改操作&#xff0c;或磁盘空间不足时&#xff0c;不考虑创…

安卓9.0系统修改定制化____第三方美化 bug修复 移植相关 辅助工具 常识篇 八

在修改rom中。有时候不可避免的需要对系统进行美化以及一些第三方系统的bug修复。在操作前需要了解系统的一些基本常识。例如同平台移植 跨平台移植以及内核移植 apk反编译等等相关的知识。今天解析的这款工具虽然不是直接面向安卓9.0.但对于了解以上的一些必备常识还是不错的 …

云服务器与物理服务器对比:选择最适合的业务服务器解决方案

更多云服务器知识&#xff0c;尽在hostol.com 在现代 IT 基础设施中&#xff0c;云服务器与物理服务器是两种常见的服务器解决方案。随着云计算技术的迅猛发展&#xff0c;越来越多的企业开始转向云服务器&#xff0c;但也有一些企业仍然坚持使用物理服务器&#xff0c;尤其是…

【redis使用场景——缓存——双写一致性】

redis使用场景——缓存——双写一致性 双写一致性问题的本质与场景典型不一致场景分析​​并发写操作导致的不一致​​​​读写交叉导致的不一致​​​​主从同步延迟导致的不一致​​ 解决延迟双删策略&#xff08;推荐&#xff09;优点​​&#xff1a;​​缺点​​&#xff…

【ArcGIS】在线影像底图调用

【ArcGIS】在线影像底图调用 一、 历史影像的调用二、ArcGIS online底图调用三、结语 一、 历史影像的调用 ESRI官方推出了World Imagery Wayback是一个提供全球范围内历史影像的在线服务。 官网地址&#xff1a;https://livingatlas.arcgis.com/wayback/ 操作步骤&#xff1…

密度估计:从零星足迹重建整体画像

想象你是一位侦探&#xff0c;案发现场只留下几个零散的脚印。**如何通过这些碎片&#xff0c;推断嫌疑人的身高体重&#xff1f;甚至预测他下一步的藏身之处&#xff1f;** 这种从局部反推整体的能力&#xff0c;正是**密度估计&#xff08;Density Estimation&#xff09;** …

B004基于STM32F401单片机简易交通灯实训数码管显示设计仿真资料

视频演示地址:https://www.bilibili.com/video/BV1GvNDzFEd9/ 运行环境 仿真软件:proteus8.17(切记别的版本不能运行) 编程软件:MDK525 STM32 cubmx版本:6.11.1(切记别的版本不能运行) 原理图画图软件:AD10 功能说明&#xff1a; 以STM32F401CB单片机为核心简易交通灯功能如下。…

没掌握的知识点记录

1、微内核的主要优点在于结构清晰、内核代码量少&#xff0c;安全性和可靠性高、可移植性强、可伸缩性、可扩展性高&#xff1b;其缺点是难以进行良好的整体优化、进程间互相通信的开销大、内核功能代码不能被直接调用而带来服务的效率低。 2、题目&#xff1a; 分页内存管理…

linux 远程终端执行qt应用显示到接入的物理显示器上

在显示器打开终端执行&#xff1a; xhost local: 在远程终端执行&#xff1a; export DISPLAY:0然后在终端执行qt应用就可以。 xhost local: 功能&#xff1a;允许本地用户&#xff08;local:&#xff09;访问 X 服务器&#xff08;X11 图形系统&#xff09;。 原理&#xf…

【AI驱动网络】

一、AI 驱动网络 1.1 什么是网络 1.1.1、网络的定义 ​网络是由若干节点​(如计算机、服务器、移动设备等)和连接这些节点的链路​(有线或无线传输介质)构成的系统,用于实现地理位置分散的独立设备之间的信息交换、资源共享与协同工作。在计算机领域,网络是信息传输、…

Python期末速成

一.基础内容 赋值语句&#xff1a; a 1 b "mayday" 标识符规则&#xff1a; 1.字母&#xff0c;数字&#xff0c;下划线&#xff0c;汉字组成。但数字不能开头 2.不能是保留字 3.特殊符号不行&#xff0c;*&#xffe5;^等 注释是在语句前面加&#xff03; …

【时时三省】(C语言基础)指针变量例子

山不在高&#xff0c;有仙则名。水不在深&#xff0c;有龙则灵。 ----CSDN 时时三省 存放地址的变量是指针变量&#xff0c;它用来指向另一个对象&#xff08;如变量、数组、函数等&#xff09;。 那么&#xff0c;怎样定义和使用指针变量呢? 先分析一个例子。 例题 通过…