Flutter The Linux toolchain CMake build dependency (CMake 3.14 or higher is required. You are running version 3.10.2)

ubuntu 22.04 通过 snap 安装了 Flutter SDK(当前是Flutter 3.3.4),如果第三方的依赖了 CMake 3.10.2 更高的版本,会在编译的时候报错:

这个报错的原因是由于 snap 安装的 Flutter SDK 构建了一个沙箱环境,在这个环境中的 CMake3.10.2 版本,不管系统安装的是哪个版本的 CMake ,都是无效的。

要解决这个问题,或者等待 snapFlutter SDK 更新版本,或者参照 Linux install Flutter 的说明,手工安装并配置 Flutter SDK

可以参考如下代码:

参考链接


Flutter-从数据库中获取记录并使用ListView Builder显示出来

数据保存在数据库中,根据表名称获取所有记录的列表,并在"ListView.builder"中显示的代码如下:

参考链接


Flutter 3.0实现Windows本地化/国际化

参照 Flutter 2.8.1本地化/国际化应用程序名称 可以实现 Android/macOS/iOS/Web 的应用名称相关的国际化。Linux 参考 Flutter 3.0实现Linux本地化/国际化

那么在 Windows 应用上如何相同的功能呢?

下面我们探讨一下一个比较简单的解决方案,就是直接修改RC文件,这个方案适用于涉及到的语言类型不太多的情况

Windows 代码编译,需要安装 Microsoft Visual Studio 2022 Community,但是不能直接使用 Microsoft Visual Studio 2022 Community 编辑 RC 文件,打开就会报错

具体的操作方法如下:

我们假定工程的名字为 LanauageTest

首先在项目根目录下,执行

生成 build 目录,然后使用 Microsoft Visual Studio 2022 Community 打开 build\windows\LanauageTest.sln 文件。

接着在资源视图中找到字符串资源,选择默认的 StringTable ,然后右键选择 “插入副本

虽然可以使用上面的操作来添加语言,但是只能作为参考,原因在于 Microsoft Visual Studio 2022 CommunityRC 文件编辑器在修改 LanauageTest.RC 文件的时候,把预定义的宏进行了展开,直接使用宏的实际值替代了宏本身,导致这些数据失去动态变化的能力。我们只能手工再编辑一次,恢复原来的宏才可以。

至于使用的话,可以通过 LoadString 加载定义的字符串资源,更详细参考 Using Resources

参考链接


Flutter 3.0实现Linux本地化/国际化

参照 Flutter 2.8.1本地化/国际化应用程序名称 可以实现 Android/macOS/iOS/Web 的应用名称相关的国际化。但是在 Linux 应用上如何相同的功能,目前暂时没有一个统一的标准。

研究了许久,终于基本上算是搞定,解决方案如下:

使用 gettext 来实现国际化相关的功能。

首先配置,调整工程的目录如下:

project/
project/linux
project/linux/flutter
project/linux/flutter/CMakeLists.txt
project/linux/locale/en_US/app.po
project/linux/locale/zh_CN/app.mo
project/linux/locale/CMakeLists.txt
project/linux/CMakeLists.txt
project/linux/main.cc
project/linux/my_application.cc
project/linux/my_application.h

对应语言 i18n 相关配置文件的内容如下:

接下来,修改 Linux 工程的配置文件,增加对 本地化(i18n) 文件的引用,在合适的位置增加如下代码:

完整的代码参考如下:

使用多语言的代码如下:

参考链接


新一代UI框架-Flutter的单元测试方法

1、Flutter是什么

Flutter是谷歌的移动UI框架,运用Dart语言,可以快速在iOS和Android上构建高质量的原生用户界面。通俗地来讲,Flutter是一款移动应用程序SDK,一份代码可以同时生成iOS和Android两个高性能、高保真的应用程序。Flutter目标是使开发人员能够交付在不同平台上都感觉自然流畅的高性能应用程序。我们兼容滚动行为、排版、图标等方面的差异。

Flutter为什么选择Dart

1、Dart 的性能更好。 js或dart都是一种声明式的写法,但js需要解释,dart是直接语言层面支持了持了node tree的书写,且对象创建成本低,可直接编译成native代码(AOT),VM效率更高,所以运行上dart效率会很多, 而且dart 是一种同时支持 JIT/AOT 编译的语言,JIT 开发模式时能快速编译生效,是Hot Reload体验的关键。速度的提升对高帧率下的视图数据计算很有帮助。

2、Native Binding。在 Android上,v8的 Native Binding可以很好地实现,但是 iOS上的JavaScriptCore不可以,所以如果使用 JavaScript,Flutter 基础框架的代码模式很难统一。而Dart的 Native Binding可以很好地通过 Dart Lib实现。

3、Dart是类型安全的语言,拥有完善的包管理和诸多特性。Google召集了如此多个编程语言界的设计专家开发出这样一门语言,旨在取代 JavaScript,所以 Fuchsia OS内置了 Dart。Dart可以作为 embedded lib嵌入应用,而不用只能随 着系统升级才能获得更新,这也是优势之一。

Flutter的优点

1、提高开发效率

同一份代码开发iOS和Android用更少的代码做更多的事情轻松迭代 在应用程序运行时更改代码并重新加载(通过热重载)修复崩溃并继续从应用程序停止的地方进行调试

2、创建美观,高度定制的用户体验

受益于使用Flutter框架提供的丰富的Material Design和Cupertino(iOS风格)的widget实现定制、美观、品牌驱动的设计,而不受原生控件的限制

2、Flutter的测试方案

根据flutter.dev介绍,Flutter测试方案可分为三种:

单元测试 测试单一功能、方法或类。例如,被测单元的外部依赖性通常被模拟出来,如package:mockito。 单元测试通常不会读取/写入磁盘、渲染到屏幕,也不会从运行测试的进程外部接收用户操作。单元测试的目标是在各种条件下验证逻辑单元的正确性。

wiget测试 在其它UI框架称为 组件测试) 测试的单个widget。测试widget涉及多个类,并且需要提供适当的widget生命周期上下文的测试环境。 例如,它应该能够接收和响应用户操作和事件,执行布局并实例化子widget。widget测试因此比单元测试更全面。 然而,就像一个单元测试一样,一个widget测试的环境被一个比完整的UI系统简单得多的实现所取代。小部件测试的目标是验证小部件的UI如预期的那样的外观和交互。

集成测试

测试一个完整的应用程序或应用程序的很大一部分。通常,集成测试可以在真实设备或OS仿真器上运行,例如iOS Simulator或Android Emulator。 被测试的应用程序通常与测试驱动程序代码隔离,以避免结果偏差。集成测试的目标是验证应用程序作为一个整体正确运行,它所组成的所有widget如预期的那样相互集成。 您还可以使用集成测试来验证应用的性能。

3、编写Flutter的单测环境与case

创建一个Flutter的单测case,主要分以下四个步骤:

  • 创建一个被测方法
  • 引入Flutter Test Library
  • 创造flutter单元测试用例
  • 注入并执行单测case

创建被测方法 如图所示,首先编写一个简单的测试方法calc

引入Flutter Test Library 接着,需要在配置文件pubspec.yaml文件中引入对应的测试library,从而保证在测试时这个dependency可以被引入

创造flutter单元测试用例 在Module的目录下,新创建一个目录,下面放我们编写的单测用例,我们将被测用例命名为test.dart

执行用例 写一个main方法作为入口,在终端键入命令flutter test运营测试,可以看到,我们的测试用例未通过,原因是expect方法预期结果与实际结果不同导致。

这样,一个完整的flutter单元测试就完成了。

4、总结

总结来说,作为一个经验法则,单元测试虽然执行速度快,依赖少,但能给项目带来的质量信心是最低的;经过充分测试的应用程序应该具有非常多的单元和widget测试,通过代码覆盖(code coverage)进行跟踪,以及覆盖所有重要使用场景的大量集成测试,才可从各阶段、各方面保证新产品的质量品质。

参考链接


新一代UI框架-Flutter的单元测试方法

Flutter CustomPaint自定义控件 时钟

时钟效果
时钟效果

我们将用 CustomPaint 来绘制我们的时钟。CustomPaint 的重要参数 paintersizepainter 是一个继承了CustomPainter 的对象,主要实现了绘画控件的功能。size 指定了控件的大小,如果 CustomPaintchild 不为空,size 的值就是 child 控件的大小,指定 size 的值则无效;如果 child 为空,所指定的 size 的值,就是画布的大小。

ClockPainter 继承了 CustomPainter,实现了其中两个重要方法:paintshouldRepaintpaint 当自定义控件需要重画时被调用。shouldRepaint 则决定当条件变化时是否需要重画。

首先先时钟的边框,代码如下,只需 drawCircle 就可以实现边框的绘制。

时钟边框
时钟边框

canvas 的起始点是画布的左上角坐标点为起点,即 x,y 都为零。drawCircle 画一个指定了半径的圆。圆的形状和样式由 Paint 对象指定。style 决定了是画圆盘(PaintingStyle.fill)还是圆环(PaintingStyle.stroke)。当 style 设定为PaintingStyle.stroke 时,strokeWidth 就是指定了圆环的宽度。

其次,可以画时钟刻度和数字了。

刻度
刻度

时钟的刻度占整个圆弧的 360/60=6 度,运用数学公式每个刻度点的坐标,然后用 drawPoints 画出每一个刻度点。

数字
数字

canvas.save() 保存当前画布,以便画完数字恢复。
canvas.translate(radius, radius) 把画布的起始点移到画布的中心。
再次保存画布后,再把起始点移到正上方位置,这里是把起始点数字 12 的位置。
TextPainter用来画文字。
canvas.rotate(-angle.toDouble() * i); 以当前画布起始点旋转一个角度,这是为了保证每个数字在下面旋转到对应的位置后保持竖直显示。
canvas.restore() 重置画布,即把画布的起始点定位到控件的中心位置。
canvas.rotate(angle.toDouble()) 以控件中心为原点旋转一个角度,即把数字旋转到对应的位置。数字 12 旋转角度为零,数字 1 旋转角度为 30 度。
所有的数字都画完并旋转到对应的位置后即可恢复起始点到控件的左上角。

最后,我们接着画时针,分针,秒针。

完整时钟
完整时钟

一个小时占时钟角度为 30 度,利用三角函数算出时针的两个点,用 drawLine 画出带宽度的时针。
每一分钟每一秒中所占的角度为 6 度,同样利用三角函数算出各自对应的两点,再画直线就可以得到分针,秒针。

完整的代码如下:

使用的代码如下:

参考链接


Flutter CustomPaint自定义控件 时钟

Flutter 倒计时功能

参考链接


Flutter : LateInitializationError: Field ‘data’ has not been initialized

You don’t want a late variable, you want a nullable one. If you need to check if something is initialized, you should be using a nullable variable instead and your code is already set up to check for null

just change

to

E.g.

change to

参考链接


Flutter : LateInitializationError: Field ‘data’ has not been initialized, got error

Flutter画圆/虚线圆/渐变圆/进度圆

同一颜色的圆

例子样式:

废话不多说 直接上代码,注释清楚!

1.调用该方法 如果只要一个圆,赋值completeColor, completeWidth, completePercent就可以,剩下的不用赋值 就是一个圆
2.如果需要俩圆的话直接调用赋值就行
3.如果只需要一个虚线圆的话,赋值isDividerRound = true; ,lineColor, width, 剩下的不用写,completeWidth 不得大于0
这是一个全圆就是比例是百分之百的圆,可以自行修改

实践示例

我们用 Flutter 新建项目的例子代码来演示,如下:

渐变色的圆

代码看看就会了

实践示例

我们用 Flutter 新建项目的例子代码来演示,如下:

参考链接


Flutter全屏效果实现

在切换横竖屏/全屏模式时用到 SystemChrome,它作为一个全局属性,很像 AndroidApplication,功能很强大。注意,这个SystemChrome 里面的 Chrome 实质上指的是 ChromeOS 不是 Chrome 浏览器,这些 API 最早在 ChromeOS 上实现,因此才这样命名。

setPreferredOrientations

1. 单方向

2. 多方向

Tips:

  1. portraitDown 属性请注意,多方向时一般不会有效果,系统默认不会颠倒;
  2. 多方向设置时初始方向分两种情况,第一种:当前重力感应方向不在设置多方向列表中,初始方向为列表第一个设置方法;第二种:当前重力感应方向在设置多方向列表中,无论顺序第几位,默认均展示当前重力感应方向(非 portraitDown)。

setEnabledSystemUIOverlays

1. SystemUiOverlay.top

2. SystemUiOverlay.bottom

3. 两者皆有

setSystemUIOverlayStyle

1. systemNavigationBarColor

2. systemNavigationBarDividerColor

3. systemNavigationBarIconBrightness

4. statusBarColor

5. statusBarIconBrightness

6. statusBarBrightness

setApplicationSwitcherDescription

实践示例

上面都是对于 API 的介绍,但是在实际项目开发中,上述的代码究竟应该添加到何处呢?我们用 Flutter 新建项目的例子代码来演示,如下:

全屏模式简介

Flutter 定义了五种全屏模式,其实就是 Android/iOS 系统的全屏模式的映射,定义如下:

下面我们简单介绍一下这几种模式的区别:

1.  leanBack : 向后倾斜模式适用于用户不会与屏幕进行大量互动的全屏体验,例如在观看视频时。
当用户希望调出系统栏时,只需点按屏幕上的任意位置即可。

2. immersive : 沉浸模式适用于用户将与屏幕进行大量互动的应用。 示例包括游戏、查看图库中的图片或者阅读分页内容,如图书或演示文稿中的幻灯片。
当用户需要调出系统栏时,他们可从隐藏系统栏的任一边滑动。要求使用这种这种意图更强的手势是为了确保用户与您应用的互动不会因意外轻触和滑动而中断。

3. immersiveSticky : 在普通的沉浸模式中,只要用户从边缘滑动,系统就会负责显示系统栏,您的应用甚至不会知道发生了该手势。因此,如果用户实际上可能是出于主要的应用体验而需要从屏幕边缘滑动,例如在玩需要大量滑动的游戏或使用绘图应用时,您应改为启用“粘性”沉浸模式。
在粘性沉浸模式下,如果用户从隐藏了系统栏的边缘滑动,系统栏会显示出来,但它们是半透明的,并且轻触手势会传递给应用,因此应用也会响应该手势。
例如,在使用这种方法的绘图应用中,如果用户想绘制从屏幕最边缘开始的线条,则从这个边缘滑动会显示系统栏,同时还会开始绘制从最边缘开始的线条。无互动几秒钟后,或者用户在系统栏之外的任何位置轻触或做手势时,系统栏会自动消失。

4. edgeToEdge : 实现从边到边的全面屏体验后,系统栏会覆盖在应用内容前方。应用也得以通过更大幅面的内容为用户带来更具有冲击力的体验。

5.  manual : 手动配置,可以独立配置状态栏,导航栏的显示与隐藏。如果选择状态栏,导航栏都隐藏,那么行为与向后倾斜模式相同。

适配安卓刘海、水滴屏显示全屏

上面的配置在刘海、水滴屏幕上会在顶部出现一道黑色的背景,比如 Honor 30 。解决方法就是 将 shortEdges 放到 style 标签内。如下:

找到 android/app/src/main/res/目录,新建 values-v27 目录(这个APIAndroid API 27 才开始支持),并在目录下创建 styles.xml ,内容从原来的 values/styles.xml 中拷贝出来,将 shortEdges 放到 style 标签内,如下:

  • LaunchTheme 指的是启动页的主题,也就是我们常说的 Splash 页面。如果需要启动页全屏就放在里面。
  • NormalTheme 代表正常页面的主题。

同样需要修改暗黑主题相关的风格文件,如下:

创建 android/app/src/main/res/values-night-v27 目录,新建 styles.xml ,将 shortEdges 放到 style 标签内 (这个APIAndroid API 27 才开始支持),如下:

参考链接