Flutter支持稳定的桌面设备开发已经一段时间了,不得不说,Flutter多平台支持的特性真的很香。我本人并没有任何桌面开发的经验,但仍然使用Flutter开发出了一个桌面版小程序,功能很简单,就是对输入的json做格式化处理和转模型。
创新互联是一家集网站建设,顺义企业网站建设,顺义品牌网站建设,网站定制,顺义网站建设报价,网络营销,网络优化,顺义网站推广为一体的创新建站企业,帮助传统企业提升企业形象加强企业竞争力。可充分满足这一群体相比中小企业更为丰富、高端、多元的互联网需求。同时我们时刻保持专业、时尚、前沿,时刻以成就客户成长自我,坚持不断学习、思考、沉淀、净化自己,让我们为更多的企业打造出实用型网站。
话不多说,先来看看实际效果。 项目源码地址
开发环境如下:
Flutter : 2.8.1
Dart : 2.15.1
IDE : VSCode
JSON作为我们日常开发工作中经常要打交道的一种数据格式,它共有6种数据类型: null , num , string , object , array , bool 。我们势必对它又爱又恨。爱他因为他作为数据处理的一种格式确实非常方便简洁。但是在我们做Flutter开发中,又需要接触到json解析时,就会感觉非常棘手,因为flutter没有反射,导致json转模型这块需要手写那繁杂的映射关系。就像下面这样子。
数据量少还能接受,一旦量大,那么光手写这个解析方法都能让你怀疑人生。更何况手写还有出错的可能。好在官方有个工具**json_serializable**可以自动生成这块转换代码,也解决了flutter界json转模型的空缺。当然,业界也有专门解析json的网站,可以自动生成dart代码,使用者在生成后复制进项目中即可,也是非常方便的。
本项目以json解析为切入点,和大家一起来看下flutter是如何开发桌面应用的。
要让我们的flutter项目支持桌面设备。我们首先需要修改下flutter的设置。如下,让我们的项目支持 windows 和 macos 系统。
接下来使用 flutter create 命令创建我们的模版工程。
创建完项目后,我们就可以 run 起来了。
先来看下整体界面,界面四块,分别为功能模块、文件选择模块、输入模块、输出模块。
我们在新建一个桌面应用时,默认的模版又一个Appbar,此时应用可以用鼠标拖拽移动,放大缩小,还可以缩到很小。但是,我们一旦去掉这个导航栏,那么窗口就不能用鼠标拖动了,并且我们往往不希望用户将我们的窗口缩放的很小,这会导致页面异常,一些重要信息都展示不全。因此这里需要借助第三方组件 bitsdojo_window 。通过 bitsdojo_window ,我们可以实现窗口的定制化,拖动,最小尺寸,最大尺寸,窗口边框,窗口顶部放大、缩小、关闭的按钮等。
通过 InkWell 组件,可以捕捉到手势、鼠标、触控笔的移动和停留位置
这个功能是鼠标移动后的UI交互界面。要在窗口上显示一个提示框,可以使用 Overlay 。需要注意的是,由于在 Overlay 上的 text 的根结点不是 Material 风格的组件,因此会出现黄色的下划线。因此一定要用 Material 包一下 text 。并且你必须给创建的 OverlayEntry 一个位置,否则它将全屏显示。
读取说表拖拽的文件一开始想尝试使用 InkWell 组件,但是这个组件无法识别拖拽中的鼠标,并且也无法从中拿到文件信息。因此放弃。后来从文章《Flutter-2天写个桌面端APP》中发现一个可读取拖拽文件的组件 desktop_drop ,能满足要求。
使用开源组件 file_picker ,选完图片后的操作和拖拽选择图片后的操作一致。
Textfield 如果要显示富文本,那么需要自定义 TextEditingController 。并重写 buildTextSpan 方法。
在做导出功能时遇到下列报错,保存提示为没有权限访问对应目录下的文件。
通过Apple的开发文档找到有关权限问题的说明。其中有个授权私钥的key为 com.apple.security.files.downloads.read-write ,表示 对用户的下载文件夹的读/写访问权限 。那么,使用Xcode打开Flutter项目中的mac应用,修改工程目录下的 DebugProfile.entitlements 文件,向 entitlements 文件中添加 com.apple.security.files.downloads.read-write ,并将值设置为YES,保存后重启Flutter项目。发现已经可以向下载目录中读写文件了。
当然,这是正常操作。还有个骚操作就是关闭系统的沙盒机制。将 entitlements 文件的 App Sandbox 设置为NO。这样我们就可以访问任意路径了。当然关闭应用的沙盒也就相当于关闭了应用的防护机制,因此这个选项慎用。
原文地址:
在编写几个 Flutter 项目后,发现 Flutter 的强大之处在于业务中所有用到的控件以及场景都有对应的处理方案;而 Dart 语言也与 Java 、 Kotlin 类似,所以对 Android 开发者来说门槛非常低;特意记录一下常用的控件及其使用:
StatelessWidget 不需要额外的创建 State
StatefulWidget 创建 State 类,并可以在其中保存一些状态
only 可以单独设置每个方向的内边距
类似于 LinearLayout 中的 orientation 设置为 vertical , mainAxisAlignment 表示竖向的一个对齐方式, crossAxisAlignment 表示横向的对齐方式
与 Column 相反,主轴是横向,对齐方式类似, crossAxisAlignment 表示竖向的对齐方式
类似 SizedBox ,一个容器,但是主要功能是有一个 decoration —— 装饰器,作用是绘制背景,或者使用 item 中的阴影
栈,先入后出,类似于 Android 上的 FrameLayout
通常配合 Stack 使用,固定显示在某一个位置
配合多 child 使用,会填充剩余的空间
Image 功能强大,使用不同的方法可以加载不同来源的图片
看到这些方法,突然觉得 Flutter 太香了,而且 Image 可以配置 clip 等裁剪出不同形状的图片,无论是圆形还是五角星都不在话下,然而 Android 要实现不规则的形状,可是要下不少功夫的。
名字和 Android 的一模一样,但是用法却比 Android 的简单很多:
主要就是 itemCount 与 itemBuilder ,其余就是配置样式, itemBuilder 需要返回一个 widget ,当然了,每个 ListView 都有其对应的 item ,在里面的方法中编写 widget 即可
与 ListView 类似,但是需要有一个 delegate 类,作用是设置有多少列,每一列之间的间距是多少
GridView 没有 build , children 表示所有的子 view
最常用的控件之一,有非常多的样式, Flutter 中通常是使用装饰器来处理控件的,如背景使用 BoxDecoration , TextFiled 使用 InputDecoration ; 使用如下
Image是一个用于展示图片的组件。支持 JPEG、PNG、GIF、Animated GIF、WebP、Animated WebP、BMP 和 WBMP 等格式。
Image.asset - 用于从资源目录的显示图片,需要在 pubspec.yaml 文件中声明。
Image.network - 用于从网络上显示图片。
Image.file - 用于从文件里显示图片。
Image.memory - 用于从内存里(Uint8List)显示图片。
alignment → AlignmentGeometry - 图像边界内对齐图像。
centerSlice → Rect - 九片图像的中心切片。
color → Color - 该颜色与每个图像像素混合colorBlendMode。
colorBlendMode → BlendMode - 用于 color 与此图像结合使用。
fit → BoxFit - 图像在布局中分配的空间。
gaplessPlayback → bool - 当图像提供者发生变化时,是继续显示旧图像(true)还是暂时不显示(false)。
image → ImageProvider - 要显示的图像。
matchTextDirection → bool - 是否在图像的方向上绘制图像 TextDirection。
repeat → ImageRepeat - 未充分容器时,是否重复图片。
height → double - 图像的高度。
width → double - 图像的宽度。
加载资源图片需要将图片资源放入工程中,例如:新建images文件夹,将图片放在该文件夹下,图片适配则是使用ios的方式1X,2X,3X:
然后在pubspec.yaml中配置assets:
加载资源/网络/本地文件图片/内存图片:
占位图加载图片:
圆形图片:1.裁剪实现 2.CircleAvatar实现 3.Container边框实现
圆角图片:1.裁剪实现 2.Container边框实现
BoxFit.contain 全图居中显示但不充满,显示原比例
BoxFit.cover 图片可能拉伸,也可能裁剪,但是充满容器
BoxFit.fill 全图显示且填充满,图片可能会拉伸
BoxFit.fitHeight 图片可能拉伸,可能裁剪,高度充满
BoxFit.fitWidth 图片可能拉伸,可能裁剪,宽度充满
BoxFit.scaleDown 效果和contain差不多, 但是只能缩小图片,不能放大图片
下一节学习基础组件之Text
Image(图片组件)是显示图像的组件,一个显示图片的widget,支持图像格式:JPEG,PNG,GIF,动画GIF,WebP,动画WebP,BMP和WBM
构造方法
Image: 从ImageProvider获取数据
Image.network: 加载网络图片。
Image.asset: 加载本地图片文件。
new Image.file: 加载本地图片文件(File文件)图片。
new Image.memory: 加载Uint8List资源图片(byte数组)图片。
常用属性
方式一:CircleAvatar
CircleAvatar可以实现圆形头像,也可以添加一个子Widget:
在图片上加一个文本
方式二:ClipOval
ClipOval也可以实现圆角头像,而且通常是在只有头像时使用
方式三:Container+BoxDecoration
方法一:ClipRRect
方法二:Container + BoxDecoration
补充知识点
Icon字体图标和图片图标的区别 ?
Colors.red 是一个MaterialColor对象,为什么可以使用[](Colors.red[10])来设置颜色 ?
MaterialColor 继承于ColorSwatch,ColorSwatch中有[] 运算符重载;
对于初学flutter的朋友来说,要知道,flutter的UI万物皆Widget。
flutter所写的页面的结构可以被看成套娃,一层套一层,一层套一层,一层套一层。。。。。。
Flutter Widget采用现代响应式框架构建,这是从 React 中获得的灵感,中心思想是用widget构建你的UI。 Widget描述了他们的视图在给定其当前配置和状态时应该看起来像什么。当widget的状态发生变化时,widget会重新构建UI,Flutter会对比前后变化的不同, 以确定底层渲染树从一个状态转换到下一个状态所需的最小更改。
Text : 该 widget 可让创建一个带格式的文本。
Row 、 Column : 这些具有弹性空间的布局类Widget可让您在水平( Row )和垂直( Column )方向上创建灵活的布局。
Stack :取代线性布局 (和Android中的LinearLayout相似),Stack允许子 widget 堆叠, 你可以使用 Positioned 来定位他们相对于 Stack 的上下左右四条边的位置。
Container : Container 可让您创建矩形视觉元素。 您可以为 Container 装饰一个 BoxDecoration , 如 background、一个边框、或者一个阴影。 Container 也可以具有边距(margins)、填充(padding)和应用于其大小的约束(constraints)。另外, Container 可以使用矩阵在三维空间中对其进行变换。
具体的演示见我另外的博客
有一部分Widget都有一个 child 属性,用于容纳唯一的子Widget。
例如:Container、Center、Padding、Align等Widget。
还有一部分Widget允许存在多个子Widget,用 children 作为属性。
例如:Row、Column、Stack等Widget。
在StatefulWidget调用createState之后,框架将新的状态插入树种,然后调用状态对象的initState。子类化State可以重写initState,以完成仅需要一次执行的工作。当然在initState的实现中需要调用super.initState
当一个状态对象不再需要时,框架调用状态对象的dispose。也可以通过覆盖dispose方法来执行清理工作。
OVER~