关于flutter:flutter系列之builder为构造器而生

简介flutter中有很多种Builder,尽管所有的builder都是结构器,然而不同的builder之间还是有很多差距的。明天咱们来具体介绍一下Builder,LayoutBuilder,StatefulBuilder这几个builder的应用。 BuilderBuilder是flutter中最罕用的builder,它是一个StatelessWidget,如下所示: class Builder extends StatelessWidget咱们看下它的构造函数: const Builder({ Key? key, required this.builder, }) : assert(builder != null), super(key: key);能够看到Builder和一般的StatelessWidget的最大的差异就是须要传入一个builder属性,这个builder是一个WidgetBuilder类型的属性, WidgetBuilder是这样定义的: typedef WidgetBuilder = Widget Function(BuildContext context);能够看到WidgetBuilder实际上是一个返回Widget的函数,这个函数在Builder被蕴含在parent's build办法中的时候,会被调用。 那么应用Builder和一般的StatelessWidget有什么区别呢? 咱们举个例子,首先是在Scaffold中间接蕴含一个包含TextButton的Center widget,如下所示: Widget build(BuildContext context) { return Scaffold( body: Center( child: TextButton( child: Text('TextButton'), ) ), );}下面的Center也能够应用Builder来封装: Widget build(BuildContext context) { return Scaffold( body: Builder( builder: (BuildContext context) { return Center( child: TextButton( child: Text('TextButton'), ), ); }, ), );}初看起来两者没有太大的区别,然而不同的是在上面的例子中,咱们应用了Builder来构建body。 ...

October 18, 2022 · 2 min · jiezi

关于flutter:flutter系列之把box布局用出花来

简介flutter中的layout有很多,基本上看layout的名字就晓得这个layout到底是做什么用的。比如说这些layout中的Box,从名字就晓得这是一个box的布局,不过flutter中的box还有很多种,明天咱们来介绍最罕用的LimitedBox,SizedBox和FittedBox。 LimitedBoxLimitedBox是一种限度大小的Box,先来看下LimitedBox的定义: class LimitedBox extends SingleChildRenderObjectWidget 能够看到LimitedBox继承自SingleChildRenderObjectWidget,示意LimitedBox中能够有一个single child。 那么LimitedBox个别用在什么中央呢? 思考在一个可滚动列表的状况下,比方ListView,因为他是unbounded的,如果ListView的子widget是Container的话,Container会尽可能的小,这很显著不是咱们所想要的,咱们以上面的代码为例: Widget build(BuildContext context) { return ListView( children: [ for(var i=0; i < 10 ; i++) Container( color: list[i % 4], ) ], ); }在ListView中,咱们增加了一个Container,这些Container中只设置了color,并且并未设置任何大小,那么将会失去上面的界面: 能够看到当初看到的界面是空白的。 当然,你能够给Container设置height属性来达到对应的目标: Widget build(BuildContext context) { return ListView( children: [ for(var i=0; i < 10 ; i++) Container( height: 100, color: list[i % 4], ) ], ); }或者应用LimitedBox来达到同样的成果: Widget build(BuildContext context) { return ListView( children: [ for(var i=0; i < 10 ; i++) LimitedBox( maxHeight: 100, child: Container( // height: 100, color: list[i % 4], ), ) ], ); }咱们能够失去上面的界面: ...

October 14, 2022 · 1 min · jiezi

关于flutter:Flutter-Web-在一起漫部的性能优化探索与实践

一起漫部 是基于区块链技术发明的新型数字生存。 目录前言开发环境渲染模式首屏白屏优化计划 启屏页优化包体积优化 去除无用的icon裁剪字体文件deferred提早加载启用gzip压缩加载优化 大文件分片下载资源文件hash化资源文件cdn化成绩参考链接总结前言不久前,App 小组面临一场开发挑战,即『一起漫部』须要在 App 的根底上开发出一套 H5 版本。 因为一起漫部 App 版本是应用 Flutter 技术开发的,对于 H5 版本的技术选型,Flutter Web 成为咱们的第一选择对象。 通过调研, 咱们理解到在 Flutter 1.0发布会上由介绍如何让 Flutter 运行在Web 上而提出 Flutter Web 的概念, 到 Flutter1.5.4 版本推出 Flutter Web 的预览版,到 Flutter 2.0官网发表 Flutter Web 现已进入稳定版, 再到现在 Flutter 对 Web 的不断更新,咱们看到了 Flutter Web 的倒退劣势。同时,为了复用现有 App 版本的代码,咱们团队决定尝试应用 Flutter Web 来实现一起漫部 H5 版本的开发。 通过 App 组小伙伴的共同努力,一起漫部在 Flutter Web 的反对下实现了 H5 端的复刻版本, 使 H5 端放弃了和 App 同样的性能以及交互体验。 在我的项目实际过程中,Flutter Web 带来的整体验还不错,但仍然存在较大的性能问题,次要体现在首屏渲染工夫长,用户白屏体验差, 本篇文章也将围绕此问题,剖析一起漫部是如何逐渐优化,晋升用户体验的。 ...

October 13, 2022 · 8 min · jiezi

关于flutter:Flutter改变状态变量是否必须写在-setState-的-回调里面

咱们都晓得 setState(VoidCallback fn) 是这样用的: setState(() { count++;});执行完后组件会从新 build(),就能够取到 count 的最新值了。但其实这样写也是一样的: count++;setState(() {});因为 setState() 最初会调用 markNeedsBuild(),Flutter 会调度使组件 rebuild,所以状态变量的扭转不是必须写在 setState() 的回调外面,只须要最初执行一下 setState() 也能够达到刷新界面的成果。 那为什么 Flutter 要设计 setState() 有个回调函数呢?有两个起因: 一是 setState() 的状态更新是同步的,如果你在 fn 里返回了一个 Future 去扭转状态的值,setState 外部的断言会提醒你不要这样做,应该在 Future 实现后在同步代码里去调用 setState 扭转状态。 二是为了代码可维护性思考。试想一下随着业务代码的迭代,可能会有很多状态变量会产生扭转,比方一开始只有状态变量 a,起初退出了状态变量 b 和 c,代码变成这样: a++;b++;c++;setState(() {});当后续业务发生变化这些状态变量都不须要了,前面保护的童鞋把这些状态变量都删除了。因为大家通常都只关注改本人的代码,会有可能遗记删除最初的 setState,代码就变成了这样: // a++;// b++;// c++;setState(() {});这样就造成了不必要的 rebuild 节约。所以综上所述,特地是思考到代码的维护性,咱们都应该把状态变量的扭转放到 setState 的回调外面。

October 12, 2022 · 1 min · jiezi

关于flutter:在Flutter中动态地改变应用启动器图标

在本文中,咱们将探讨如何在 Flutter 应用程序的运行时动静更改多个应用程序启动器图标。 在 pubspec.yaml 文件中增加以下依赖项。 flutter_dynamic_icon:https://pub.dev/packages/flutter_dynamic_icon 思考咱们曾经筹备好根本的 UI(蕴含图像和按钮小部件)。 import 'package:flutter/material.dart';class MyHomePage extends StatefulWidget { const MyHomePage({Key? key, required this.title}) : super(key: key); final String title; @override State<MyHomePage> createState() => _MyHomePageState();}class _MyHomePageState extends State<MyHomePage> { int iconIndex = 0; List iconName = <String>['icon1', 'icon2', 'icon3']; @override Widget build(BuildContext context) { return Scaffold( appBar: buildAppBar(appBarTitle: widget.title), body: Padding( padding: EdgeInsets.all(kSpacing), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ buildIconTile(0, 'red'), buildIconTile(1, 'dark'), buildIconTile(2, 'blue'), HeightSpacer(myHeight: kSpacing), PrimaryBtn( btnFun: () => changeAppIcon(), btnText: 'Set as app icon'), ], )), ); } Widget buildIconTile(int index, String themeTxt) => Padding( padding: EdgeInsets.all(kSpacing / 2), child: GestureDetector( onTap: () => setState(() => iconIndex = index), child: ListTile( contentPadding: const EdgeInsets.only(left: 0.0, right: 0.0), leading: Image.asset( imagefiles[index], width: 45, height: 45, ), title: Text(themeTxt, style: const TextStyle(fontSize: 25)), trailing: iconIndex == index ? const Icon( Icons.check_circle_rounded, color: Colors.green, size: 30, ) : Icon( Icons.circle_outlined, color: Colors.grey.withOpacity(0.5), size: 30, )), ), ); changeAppIcon() {} ...

October 11, 2022 · 2 min · jiezi

关于flutter:FluttersetState-能在-build-中直接调用吗

setState() 能在 build() 中间接调用吗?答案是能也不能。 两种状况来看一段简略的代码: import 'package:flutter/material.dart';class TestPage extends StatefulWidget { const TestPage({super.key}); @override State<TestPage> createState() => _State();}class _State extends State<TestPage> { int _count = 0; @override Widget build(BuildContext context) { setState(() { _count++; }); return Scaffold( appBar: AppBar( title: const Text('测试页面'), ), body: Center( child: Text( '$_count', style: const TextStyle(fontSize: 24), ), ), ); }}跑起来后代码不会报错,Text('$_count') 显示后果是 1,看来 build() 调用 setState() 没啥问题呀。小改一下,来看看这个: class _State extends State<TestPage> { int _count = 0; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('测试页面'), ), body: Center( child: Builder( builder: (context) { setState(() { _count++; }); return Text( '$_count', style: const TextStyle(fontSize: 24), ); } ), ), ); }}改变次要是在 Text 下面加了一个 Builder,而后把 setState() 放在了 Builder 的 builder 中去调用。运行起来,后果呈现报错了:The following assertion was thrown building Builder(dirty): setState() or markNeedsBuild() called during build.提醒在 Builder 的 build() 过程中呈现了断言谬误:build() 中不能调用 setState() 或 markNeedsBuild()。 ...

October 11, 2022 · 2 min · jiezi

关于flutter:GitHub-供应链安全已支持-Dart-开发者生态

通过 Dart 和 GitHub 团队的共同努力,自 10 月 7 日起,GitHub 的 Advisory Database (平安征询数据库)、Dependency Graph (依赖项关系图) 和 Dependabot (依赖更新机器人) 开始反对 Dart 开发者生态,这也意味着 GitHub 为 Dart 和 Flutter 利用的供应链平安提供了全面反对: GitHub 的 Advisory Database (平安征询数据库) 为破绽报告者和我的项目维护者之间提供了一个合作平台,破绽报告者和我的项目维护者能够独特单干,在破绽被公开之前私密探讨并修复破绽。Dependency Graph (依赖项关系图) 次要是剖析 Dart / Flutter 我的项目的 pubspec.yaml 和 pubspec.lock 文件来确定我的项目依赖关系。Dependabot 是 GitHub 收买并收费凋谢的一个检测依赖项安全性的工具,一旦你依赖的 Dart package 版本发现新破绽时,Dependabot 就能够发出通知并主动创立拉取申请 (Pull Request),将 package 版本升级到没有破绽的版本。查看过往推文: Dependabot 开始反对 pub package 版本检测 理解更多。Dart 产品经理 Michael Thomsen 示意:通过与 GitHub 团队的单干,Dart 开发者们能够在新的破绽影响到客户之前发现和解决问题;GitHub 的高级产品经理 Courtney Claessens 也提到说,在供应链平安侧全面反对 Dart,不仅是对开源社区、开发者的反对,更可能帮忙数百万应用 Dart 利用的用户们。 ...

October 11, 2022 · 1 min · jiezi

关于flutter:flutter系列之按比例缩放的AspectRatio和FractionallySizedBox

简介咱们在构建UI的时候,为了适应不同的屏幕大小,通常须要进行一些自适应的配置,而最常见的自适应就是依据某个宽度或者高度主动进行组件的缩放。 明天要给大家介绍两个能够主动缩放的组件AspectRatio和FractionallySizedBox。 AspectRatioAspectRatio的目标就是将其child按比例缩放。 先来看下AspectRatio的定义: class AspectRatio extends SingleChildRenderObjectWidget能够看到AspectRatio继承自SingleChildRenderObjectWidget,示意用来出现一个single child。 AspectRatio须要的属性有两个,别离是aspectRatio和子元素child。 aspectRatio是一个double类型的数据,为了不便起见,咱们个别应用比例的格局来进行示意,比方3.0/2.0等。 尽管咱们晓得3/2的后果是1.5,然而咱们最好不要自行计算结果,因为应用3.0/2.0更加直观。 AspectRatio的逻辑是首先取得最大的width或者height,而后依据width或者height来计算height和width。接下来咱们来看几个具体的例子,来具体理解AspectRatio。 首先是一个有限宽度然而高度为150的container,而后再container的child中应用了AspectRatio组件,如下所示: Widget build(BuildContext context) { return Container( color: Colors.blue, alignment: Alignment.center, width: double.infinity, height: 150.0, child: AspectRatio( aspectRatio: 3 / 2, child: Container( color: Colors.red, ), ), );这里的aspectRatio=3/2, 那么怎么来计算aspectRatio的大小呢? 对于aspectRatio的父widget来说,他的宽度是有限的,他的高度是150,所以aspectRatio的高度是能够确定的,也就是150,咱们依据aspectRatio的比例,计算出它的width=150/2 * 3 = 225, 如下所示: 再看上面的一个例子: Widget build(BuildContext context) { return Container( color: Colors.blue, alignment: Alignment.center, width: 150.0, height: 150.0, child: AspectRatio( aspectRatio: 2.0, child: Container( color: Colors.red, ), ), ); }这个例子中Container的width和height是相等的。 ...

October 10, 2022 · 1 min · jiezi

关于flutter:Flutter-Cocoon-已达到-SLSA-2-级标准的要求

文/ Jesse Seales, Dart 和 Flutter 平安工作组工程师 今年年初,咱们公布了 Flutter 2022 产品路线图,其中「基础设施建设」这部分提到:2022 年 Flutter 团队将减少对供应链的平安的投入,目标是达到合乎基础设施 SLSA 4 级别中形容的要求。4 月份下旬,Dart 团队与 GitHub 单干,Dependabot 开始反对 pub.dev 上的 package 版本检测。 Cocoon 是一个治理 Flutter Infra CI 的工具利用,咱们曾经实现了晋升到 SLSA 2 级规范所要求的内容,将身份辨认和拜访治理 (Identity and Access Management, IAM) 权限升高到所需的最低权限,并对局部利用权限治理施行了基础设施即代码 (Infrastructure as code, IaC) 的策略。 身份辨认和拜访治理 (IAM) 是一种平安权限措施,次要用于拜访敏感技术资源时,为不同须要的人受权不同的权限。基础设施即代码 (IaC) 的外围思路是通过代码而不是用手动的形式和流程来治理我的项目的基础设施。亮点Cocoon 不仅能够治理 Flutter Infra CI,还能够将多个 CI 服务与 GitHub 集成,使得团队在 GitHub 上开发变得更容易。Cocoon 通过了 SLSA 2 级的要求,这意味着 Cocoon 曾经解决了 SLSA 1 和 2 级别中所有的平安问题。Google 的开源平安团队曾经验证并审核了 Cocoon 具备 SLSA 2 级规范的要求。 ...

October 10, 2022 · 1 min · jiezi

关于flutter:使用Flutter历时三个月我写了一个桌面象棋打谱软件

目前,该软件曾经在官网上线,官网链接:https://cca.yhdm360.cn。 该软件应用macOS UI进行开发,应用BLOC作为状态治理库,联合LeanFlutter团队一些优良的开源库,使得工作进展绝对比较顺利。 但因为桌面端Flutter的一些个性反对不全,一些中央依然不得不应用曲线救国的形式实现。 目前该版本曾经具备以下性能: 打谱,反对变招、记谱,棋谱同步等性能棋库治理、同步棋谱编辑,反对撤销、重做反对导入、导出规范PGN棋谱反对导入象棋桥CBF棋谱反对棋图生成,不便分享反对复制、粘贴FEN反对推演棋盘,随时拆解软件截图: 在这里,除了与大家分享产品与喜悦之外,也冀望能够结交一些同样在做独立开发的敌人,欢送你退出咱们的QQ交换群,一起来玩。 独立开发QQ交换群:850273774

October 7, 2022 · 1 min · jiezi

关于flutter:flutter-踩坑

1. 应用flutter_svg引入svg报错该svg是从figma导出的。翻阅 Out of order defs/references #102将defs放到svg标签的顶部,能够解决这个报错,且修改了该svg外部小图标的色彩问题,从而让页面上的svg跟figma上看起来统一。 2. 应用GridView滚动的时候报错*The following assertion was thrown while notifying status listeners for AnimationController:The provided ScrollController is currently attached to more than one ScrollPosition.* class GridList extends StatelessWidget { const GridList({ Key? key, }) : super(key: key); @override Widget build(BuildContext context) {\ return GridView.count( crossAxisCount: 3, crossAxisSpacing: 32, mainAxisSpacing: 32, scrollDirection: Axis.vertical, childAspectRatio: (1 / .75), shrinkWrap: true, children: const [ GridCard(), GridCard(), GridCard(), GridCard(), GridCard(), GridCard(), ], ); }}参考Flutter谬误The provided ScrollController is attached to more than one ScrollPosition须要给GridView增加个controller。 ...

September 30, 2022 · 2 min · jiezi

关于flutter:flutter系列之深入理解布局的基础constraints

简介咱们在flutter中应用layout的时候须要常常对组件进行一些大小的限度,这种限度就叫做constraints,用来管制layout中的组件大小。 把握了constraints才算对layout有了真正的理解,然而flutter中的constraints和咱们相熟的HTML中的constraints区别比拟大,所以咱们还是须要深刻理解flutter中contraints的个性。 Tight和loose constraints对于constraints来说,只有四个属性,别离是最小width,最大width,最小height和最大height。这四个属性所能限度的就是宽度和高度的范畴。 依据这两个属性的范畴不同,constraints能够分为tight constraints和loose constraints。 那么tight和loose有什么区别呢? 对于tight来说,它的 maximum width = minimum width, 并且maximum height = minimum height, 也就是说为width和height提供了一个特定的值。 具体而言,能够看下BoxConstraints的tight实现: BoxConstraints.tight(Size size) : minWidth = size.width, maxWidth = size.width, minHeight = size.height, maxHeight = size.height;和tight绝对应的就是loose,在loose中咱们设置了最大的width和height,然而心愿widget越小越好,这样对应width和height的最小值为0,同样以BoxConstraints为例看下它的定义: BoxConstraints.loose(Size size) : minWidth = 0.0, maxWidth = size.width, minHeight = 0.0, maxHeight = size.height;了解constraints的准则后面咱们讲到了constraints的分类,这里咱们会讲一下constraints的根本准则。 通常来说,在flutter中,一个widget的constraints是从它的parent继承而来的。而后这个widget会将constraints通知他的子widget. 子widget会有本人定义的大小,那么子widget会依据本人定义的大小来设置本人的大小,并将后果反馈跟父widget,父widget会最终依据所有子widget的大小来设置本人的大小。 所以总结而言就是,constraints是向下传递的,而size是向上传递的。 可能大家还不太明确是什么意思,没关系,接下来咱们用具体的例子来阐明。 首先,咱们应用BoxConstraints.tightFor来创立一个尽可能大的width和height的Constraints,而后在这个constraint外部新建widget来察看他们的体现。 ConstrainedBox( constraints: const BoxConstraints.tightFor( width: double.infinity, height: double.infinity), child: exampleWidget)通过替换下面的exampleWidget,咱们来察看不同的表现形式。 首先是最根底的Container,对于Container自身来说,他能够设置width和height,然而这两个属性并不是constraint,所以还得从parent widget中继承。 那么对于上面的一个widget来说: ...

September 29, 2022 · 2 min · jiezi

关于flutter:Flutter-logger一个很好的日志工具使用教程

咱们都晓得这个问题:咱们想调试打印咱们的应用程序,但聊天中的信息只是一团糟。它们没有格式化,很难失去一个概览....,这切实是不好玩。这就是为什么我将向你介绍 logger 包,它正好解决了这个问题。让咱们开始吧! 留神:Logger 可能如下所示: 装置创立应用程序后咱们要做的第一件事就是增加logger。为此,咱们将应用命令 dart pub add logger。您应该相熟这些命令,否则,我建议您再次查看 Flutter 的基础知识。 还有一个叫 logger_flutter的包,如果你应用Flutter,就能够应用它。如果你装置了这个,你能够摇摆你的手机,它将在手机上显示控制台。你能够用 flutter pub add logger_flutter 来装置它。你手机上的控制台可能看起来像这样: 根底首先,你必须创立一个 logger 变量。如果你应用像Riverpod这样的包,你能够把它们存储在一个提供者中,以便在整个应用程序中拜访它们(在这里学习Riverpod) 在这里,咱们曾经有了许多对于日志程序外观的选项: 当初咱们想在控制台中显示一些货色。有多个日志级别,我将在此处列出: 深刻理解和高级用法咱们来谈谈 LogFilter、LogPrinter 和 LogOutput。它们用于更多地定制您对日志的体验: LogFilterLogFilter 决定应该显示哪些日志事件,哪些不显示。默认设置为 DevelopmentFilter,在调试模式下显示所有 level >= Logger.level的日志,但在公布模式下,所有日志都将被疏忽。当然,你能够创立你本人的 LogFilter。为此,您必须创立一个扩大 LogFilter 的类并创立一个名为 shouldLog 的函数。 LogPrinterLogPrinter 创立并格式化输入,而后将其发送到 LogOutput(咱们将在下一章探讨 LogOutput)。当然,你能够实现本人的 LogPrinter: 本软件包的作者阐明: 如果您创立了一个可能对其他人有帮忙的酷 LogPrinter,请随时关上拉取申请。 :)LogOutputLogOutput 负责将日志行发送到所需的目的地。它的默认实现 ConsoleOutput 将每一行发送到零碎控制台。有可能,未来 LogOutput 能够将文件发送到 firebase 或 Logcat。 进一步浏览和论断在本文中,您理解了控制台管理器“logger”的基础知识。您曾经看到了它的易用性以及控制台输入的好看水平。 如果您应用 Freezed、Isar 或 Flutter Hooks 等软件包,您能够充分发挥 logger 的全副性能。如果你想学习这些附加性能,我有对于它们的残缺教程。在这里查看它们。 ...

September 28, 2022 · 1 min · jiezi

关于flutter:Flutter第十四课Image组件和Button组件

Flutter第十四课:Image组件和Button组件一:Flutter Image组件Flutter中,咱们能够通过Image来加载并显示图片,Image的数据源能够是asset、文件、内存以及网络。图片组件( Image)是显示图像的组件, Image 组件有多种构造函数 : new Image:从 ImageProvider 获取图像 。new Image.asset:加载资源图片。new Image.file:加载本地图片文件。new Image.network:加 载网络图片 。new Image.memory:加载 Uint8List 资源图片 。 当我第一次应用Image图片本地assets时候遇到如下问题: Error on line 61, column 4: Expected a key while parsing a block mapping. ╷61 │ assets: │ ^ ╵最初发现是没对齐 //形式一://加载本地资产assets图片return Scaffold( body: Center( child: Image( image:AssetImage("assets/images/star.png"),//AssetImage的父类是AssetBundleImageProvider //abstract class AssetBundleImageProvider extends ImageProvider<AssetBundleImageKey> 故:AssetImage是ImageProvider的实现类 width: 100, height: 100, ),));//形式二:return Scaffold( body: Center( child: Image.asset("assets/images/star.png", width: 200, height: 200,),));源码的属性:通过:new Image形式加载图片资源 const Image({ Key? key, required this.image,//类型为ImageProvider 抽象类,须要本人实现获取图片数据的操作 this.frameBuilder, this.loadingBuilder, this.errorBuilder, this.semanticLabel, this.excludeFromSemantics = false, this.width,//Image 显示区域的宽度和高度设置,这里须要把 Image 和图片两 个货色辨别开,图片自身有大小, Image Widget 是图片的容器,本 身也有大小。 宽度和高度的配置常常和 fit 属性配合应用 this.height, this.color,//图片色彩 this.opacity, this.colorBlendMode,//在对图片进行手动解决的时候,可能用到图层混合,如扭转图片的色彩。 此属性能够对色彩进行混合解决。 有多种模式 this.fit,//图片填充模式 this.alignment = Alignment.center,//管制图片的摆放地位,比方l图片搁置在右下角则为 Alignment. bottom this.repeat = ImageRepeat.noRepeat,//此属性能够设置图片反复模式 this.centerSlice,//当图片须要被拉伸显示时 this.matchTextDirection = false, this.gaplessPlayback = false, this.isAntiAlias = false, this.filterQuality = FilterQuality.low, }) : assert(image != null), assert(alignment != null), assert(repeat != null), assert(filterQuality != null), assert(matchTextDirection != null), assert(isAntiAlias != null), super(key: key);BoxFit取值及形容 ...

September 27, 2022 · 3 min · jiezi

关于flutter:在Flutter移动应用开发中减少应用大小

本文是对于咱们能够遵循以缩小应用程序大小的办法和技术。咱们用 Flutter 开发了一个安卓应用程序。 但令人诧异的是,与原生开发的 android 应用程序相比,调试应用程序的大小更大。因而,咱们寻找一种减小应用程序大小的办法,并尝试减小挪动应用程序的大小。所以最初咱们找到了一些解决方案来解决这个问题。咱们减小了应用程序的大小。 如果您是挪动应用程序开发人员,那么您必定会关怀应用程序的大小,并且总是尝试构建小型应用程序并应用减小大小的技术。在 4G 和古代智能手机时代为用户提供应用程序时,减小尺寸成为重要且必不可少的过程之一,因为人们更喜爱较小的应用程序,许多用户在下载任何太大的应用程序之前会防止并三思而后行。依据一份报告,大多数智能手机用户的数据套餐都是无限的,所以他们不喜爱在繁多的应用程序上破费他们的数据包。在编码过程中,咱们须要进行优化,尽量减少利用的大小。 有两个维度来掂量应用程序大小 下载大小 - 利用在 Play 商店中的大小(下载时)装置尺寸--这能够在装置应用程序后看到。这是当你下载利用、解压、编译和优化时产生的状况。这将大大扩大应用程序,可能是装置尺寸的两到三倍,甚至更多。下载大小当用户从play store上装置一个应用程序时,他会看到加载条,而后是理论的应用程序大小。依据谷歌的数据,Play Store上有259万个应用程序,难怪压服用户装置你的应用程序从未如此艰难。应用程序越大,下载失败/勾销的几率就越大。作为开发者,咱们心愿将应用程序的体积变小,以便咱们的应用程序取得尽可能多的流传。 装置大小这也有相似的景象。用户用视频、音频和图像填充他们的手机,他们会尝试装置一个新的应用程序,哎呀,没有空间了。他们会去寻找空间,去设置,而后查看哪个应用程序耗费更多空间。即便在尝试从 Play 商店下载时,它也倡议他们删除一些应用程序以适应新应用程序,甚至给他们一些倡议。 有许多良好的编码实际,建设一个稳固的架构将有助于应用程序更好地执行。有一些常见的办法和实际,你能够在你的应用程序中实现,使其变的更好。 一些缩小应用程序大小的解决方案:1.压缩PNG和JPG每当您必须在应用程序内应用图像(例如演练屏幕)并且您不想从内部主机调用图像时,您应该压缩您的 PNG 和 JPG,因为高质量的图像会减少应用程序的大小。您能够在 Google 上疾速搜寻压缩 PNG 和 JPG 的工具。 2.应用网络图片在Flutter中,开发者应用assets文件夹中的图片,这对疾速加载图片很有帮忙。然而当你在利用中存储这些图片时,assets会给利用减少更多的体积。解决方案是应用网络图片。在一个永恒的存储门路中上传图片,如Firebase存储,或AWS,并在你的代码中应用该图片的链接。这种办法也能够帮忙你缩小应用程序的大小。 3.缓存如果你应用网络图片,缓存是一件十分重要的事件,缓存不会帮忙缩小应用程序的大小,但它会使应用程序加载速度更快,进步应用程序的性能。所有罕用图片,如个人资料图片、应用 cached_network_image 插件的背景图片。 cached_network_image 包容许您应用任何小部件作为占位符。它能够在 pub.dev 中找到。 4.应用.svg格局的图标应用矢量绘图咱们能够取得一些益处。无需放心不同的设施 DPI,这也有助于缩小 apk 大小。 当您从 Google 的 Material Design 图标库下载零碎应用程序图标时,下载 .svg 格局而不是 .png, .svg 图像能够帮忙您减小应用程序大小。 5.应用无效的库 删除pubspec.yaml文件中所有未应用的包。一旦实现构建你的应用程序,你应该查看你的pubspec.yaml,删除不应用的库,并从pubspec.yaml中删除所有未应用的asset。 6.应用Google Fonts 字体是利用中一个十分重要的根本货色。它们很重,而且被卡在应用程序中。你须要字体来为用户提供最好的用户体验,它将帮忙你建设一个丑陋的应用程序。你可能想应用 google_fonts package,而不是在利用中捆绑字体。应用 google_fonts 包,.ttf 或 .otf 文件不须要存储在您的资产文件夹中并映射到 pubspec.yaml 文件中。相同,它们能够在运行时通过 HTTP 获取一次,并缓存在应用程序的文件系统中。这相似于原生 android 开发中的可下载字体。您能够在 pub.dev 上查看 google 字体包。在那里你能够从谷歌字体中找到很多不同的字体。 ...

September 27, 2022 · 2 min · jiezi

关于flutter:flutter系列之查询设备信息的利器MediaQuery

简介挪动的开发中,大家可能最头疼的就是不同设施的规格了,当初设施这么多,如何能力在诸多的设施中找到适合的widget的地位来进行绘制呢? 不必怕,在flutter中为咱们提供了一个叫做MediaQuery的利器,大家一起来看看吧。 MediaQuery详解MediaQuery从名字上来看,它的意思是媒体查问。它能够查问的货色就多了,能够查问以后你app的窗口信息,查问你指定的某个widget的信息等等,十分的弱小。 咱们先来看下MediaQuery到底是什么。 具体来说MediaQuery继承自InheritedWidget: class MediaQuery extends InheritedWidget 那么什么是InheritedWidget呢?为什么MediaQuery须要继承InheritedWidget呢? 很多时候,咱们须要从widget的子widget中获取到父widget对象,InheritedWidget就是一个能够提供简略获取办法的对象。 在InheritedWidget中能够实现of办法,通过调用BuildContext.dependOnInheritedWidgetOfExactType来从context中获取最邻近的InheritedWidget对象。 这里,因为MediaQuery是一个媒体查问工具,所以咱们可能须要在很多中央随时随地的进行对象的获取,那么这里应用InheritedWidget就是再好不过了。 MediaQuery的属性MediaQuery的自有属性只有两个,别离是MediaQueryData类型的data和Widget类型的child。 MediaQueryData是一个相似于构造体的类,用来存储各种Media的状态信息。 咱们先来看下MediaQueryData的构造函数: const MediaQueryData({ this.size = Size.zero, this.devicePixelRatio = 1.0, this.textScaleFactor = 1.0, this.platformBrightness = Brightness.light, this.padding = EdgeInsets.zero, this.viewInsets = EdgeInsets.zero, this.systemGestureInsets = EdgeInsets.zero, this.viewPadding = EdgeInsets.zero, this.alwaysUse24HourFormat = false, this.accessibleNavigation = false, this.invertColors = false, this.highContrast = false, this.disableAnimations = false, this.boldText = false, this.navigationMode = NavigationMode.traditional, })能够看到,MediaQueryData中蕴含了很多有用的属性,咱们来具体看一下具体的内容。 首先是示意media logical pixels大小的size。大家要留神的是,这里的size示意的是逻辑pixels的大小。 有logical pixels,就有Physical pixels,前者示意的逻辑大小,在任何设施上都是一样的,而后者示意的是实在的物理设施所反对的像素大小。这两种是能够不同的。一个物理像素可能代表多个逻辑像素,这个对应关系就是由devicePixelRatio这个属性来决定的。 ...

September 26, 2022 · 1 min · jiezi

关于flutter:Flutter学习第十三课文本组件Text

Flutter学习第十三课:文本组件Text一:文本组件Text //文本 const Text( String this.data, {//data必填项文本信息 Key? key, this.style,//文本款式 this.strutStyle,//文本字体款式 this.textAlign,//文本应如何程度对齐 this.textDirection,//绝对TextAlign中的start、end而言有用(当start应用了ltr相当于end应用了rtl,也相当于TextAlign应用了left) this.locale, this.softWrap,//某一行中文本过长,是否须要换行。默认为true, this.overflow,//如何解决视觉溢出//TextOverflow.fade:将溢出的文本淡化为通明。TextOverflow.clip:剪切溢出的文本以修复其容器。TextOverflow.ellipsis:应用省略号示意文本已溢出。 this.textScaleFactor,//每个逻辑像素的字体像素数 this.maxLines,//本要逾越的可选最大行数 this.semanticsLabel, this.textWidthBasis, this.textHeightBehavior, }) : assert( data != null, 'A non-null String must be provided to a Text widget.', ), textSpan = null, super(key: key);//富文本 const Text.rich( InlineSpan this.textSpan, { Key? key, this.style, this.strutStyle, this.textAlign, this.textDirection, this.locale, this.softWrap, this.overflow,//如何解决视觉溢出//TextOverflow.fade:将溢出的文本淡化为通明。TextOverflow.clip:剪切溢出的文本以修复其容器。TextOverflow.ellipsis:应用省略号示意文本已溢出。 this.textScaleFactor,//textScaleFactor字体显示倍率 this.maxLines,//maxLines文字显示最大行数 this.semanticsLabel, this.textWidthBasis, this.textHeightBehavior, }) : assert( textSpan != null, 'A non-null TextSpan must be provided to a Text.rich widget.', ), data = null, super(key: key);文本款式属性TextStyle ...

September 23, 2022 · 2 min · jiezi

关于flutter:Flutter学习第十二课弹性布局Flex和水平排列Row和垂直排列Column

Flutter学习第十二课:弹性布局Flex和程度排列Row和垂直排列Column一:弹性布局(Flex)弹性布局容许子组件依照肯定比例来调配父容器空间。弹性布局的概念在其它UI零碎中也都存在,如H5中的弹性盒子布局,Android中的FlexboxLayout等。Flutter中的弹性布局次要通过Flex和Expanded来配合实现 Flex({ Key? key, required this.direction,//Axis.vertical,Axis.horizontal,/弹性布局的方向, Row默认为程度方向,Column默认为垂直方向 this.mainAxisAlignment = MainAxisAlignment.start,//主轴排列形式 this.mainAxisSize = MainAxisSize.max, this.crossAxisAlignment = CrossAxisAlignment.center,//穿插轴排列形式 this.textDirection,// this.verticalDirection = VerticalDirection.down,//设置垂直方向上的子 Widget 的排列程序,默认为 VerticalDirection.down this.textBaseline, // NO DEFAULT: we don't know what the text's baseline should be//设置文字对齐的基线类型 this.clipBehavior = Clip.none, List<Widget> children = const <Widget>[],//子组件 }) : assert(direction != null), assert(mainAxisAlignment != null), assert(mainAxisSize != null), assert(crossAxisAlignment != null), assert(verticalDirection != null), assert(crossAxisAlignment != CrossAxisAlignment.baseline || textBaseline != null, 'textBaseline is required if you specify the crossAxisAlignment with CrossAxisAlignment.baseline'), assert(clipBehavior != null), super(key: key, children: children);1. direction设置主轴方向,可设置的值为 Axis.horizontal 和 Axis.vertical,穿插轴与主轴方向垂直。在Flutter中,Row组件和Column组件都继承自Flex组件(1).Flex组件和Row、Column属性次要的区别就是多一个direction。(2).当direction的值为Axis.horizontal的时候,则是Row。(3).当direction的值为Axis.vertical的时候,则是Column2. mainAxisAlignment:设置子 Widget 沿着主轴方向的排列形式,默认 MainAxisAlignment.start,可设置的形式如下:MainAxisAlignment.start:左对齐,默认值;MainAxisAlignment.end:右对齐;MainAxisAlignment.center:居中对齐;MainAxisAlignment.spaceBetween:两端对齐;MainAxisAlignment.spaceAround:每个 Widget 两侧的距离相等,与屏幕边缘的距离是其余 Widget 之间距离的一半;MainAxisAlignment.spaceEvently:均匀散布各个 Widget,与屏幕边缘的距离与其余 Widget 之间的距离相等.3. mainAxisSize设置主轴的大小,默认 MainAxisSize.max,可设置的值如下:MainAxisSize.max:主轴的大小是父容器的大小;MainAxisSize.min:主轴的大小是其子 Widget 大小之和。4. crossAxisAlignment设置子 Widget 沿着穿插轴方向的排列形式,默认 CrossAxisAlignment.center,可设置的形式如下:CrossAxisAlignment.start:与穿插轴的起始地位对齐;CrossAxisAlignment.end:与穿插轴的完结地位对齐;CrossAxisAlignment.center:居中对齐;CrossAxisAlignment.stretch:填充整个穿插轴;CrossAxisAlignment.baseline:依照第一行文字基线对齐。5. verticalDirection设置垂直方向上的子 Widget 的排列程序,默认为 VerticalDirection.down,设置形式如下:VerticalDirection.down:start 在顶部,end 在底部;VerticalDirection.up:start 在底部,end 在顶部。6. textBaseline设置文字对齐的基线类型,可设置的值如下:TextBaseline.alphabetic:与字母基线对齐;TextBaseline.ideographic:与表意字符基线对齐; ...

September 23, 2022 · 2 min · jiezi

关于flutter:flutter系列之Material中的3D组件Card

简介除了通用的组件之外,flutter还提供了两种格调的非凡组件,其中在Material格调中,有一个Card组件,能够很不便的绘制出卡片格调的界面,并且还带有圆角和暗影,十分的好用,咱们一起来看看吧。 Card详解在具体解说Card之前,咱们考虑一下什么时候会用到Card? 一提到Card大家第一印象就是名片,在名片中形容了一个人的相干信息,比方姓名,电话和邮箱等。而Card就是将一组相干的信息放在一起出现的组件。 咱们来看下Card的定义: class Card extends StatelessWidget 能够看到Card是一个无状态的Widget,Card的构造函数须要传入比拟多的参数,上面是Card的构造函数: const Card({ Key? key, this.color, this.shadowColor, this.elevation, this.shape, this.borderOnForeground = true, this.margin, this.clipBehavior, this.child, this.semanticContainer = true, })color示意的是Card的背景色彩,如果不设置的话,会应用ThemeData.cardTheme中指定的color,如果CardTheme.color也是空的话,那么会应用ThemeData.cardColor来代替。 shadowColor示意的是Card暗影的色彩,如果不设置的话,会应用ThemeData.cardTheme的shadowColor来代替,如果CardTheme.shadowColor也是空的话,那么会应用ThemeData.shadowColor来代替。 elevation是Card在Z轴的地位,通过设置这个值,咱们能够管制Card上面shadow的大小。 shape是Card的形态,它是一个ShapeBorder对象,有很多已知的实现,比方CircleBorder,RoundedRectangleBorder,ContinuousRectangleBorder,BeveledRectangleBorder等。 borderOnForeground示意是否将Card的border在child之前展现。 clipBehavior是Card的裁剪规定。margin是card四周的空白局部。 semanticContainer是一个bool值,示意Card中的child是否都具备雷同的semantic,或者说他们的类型是统一的。 最初一个参数就是child了,示意Card中的子元素。尽管Card中的child只有一个,然而这个child能够是能够蕴含多个child的widget,比方Row或者Column等。 Card的应用通过下面的解说,咱们对Card的应用也有了根本的理解,接下来咱们能够通过一个具体的例子,来看看Card具体是如何应用的。 尽管Card外面蕴含了一个child widget,这个child widget能够是任何值,然而通常来说还是和Column或者Row一起应用的比拟多。 这里咱们应用Column来创立一个相似于名片的界面。 Column中有一个children的属性,能够蕴含多个子元素,咱们能够在每一行中放上图片或者文字,如果要想进行简单的布局,还能够自在进行简单的组合。 然而对于相似名片这种常见的利用,flutter早就为咱们想好了,所以他提供了一个叫做ListTile的组件。 ListTile是一个固定高度的Row,并且能够蕴含一个leading icon或者trailing icon。还能够蕴含title,subtitle还有一些点击的交互,十分的不便。 具体ListTile的应用,大家能够去参考具体的API,这里就不过多讲述。 这里咱们只是借用ListTile来结构咱们须要的成果。 不同的ListTile组件,能够用Divider来进行宰割,让界面更加好看。 上面是咱们CardApp的代码: class CardApp extends StatelessWidget{ const CardApp({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return SizedBox( height: 210, child: Card( child: Column( children: [ const ListTile( title: Text( 'Han MeiMei', style: TextStyle(fontWeight: FontWeight.w500), ), subtitle: Text('上海,张江'), leading: SizedBox( width: 20, child:Center( child: CircleAvatar( backgroundImage: AssetImage('images/head.jpg'), radius: 10, )) ), ), const Divider(), ListTile( title: const Text( '18888888888', style: TextStyle(fontWeight: FontWeight.w500), ), leading: Icon( Icons.contact_phone, color: Colors.blue[500], ), ), ListTile( title: const Text('[email protected]'), leading: Icon( Icons.contact_mail, color: Colors.blue[500], ), ), ], ), ), ); }}将CardApp放在Scaffold的body中运行,能够失去上面的界面: ...

September 23, 2022 · 1 min · jiezi

关于flutter:Flutter第十课Flutter组件之Container

Flutter第十课:Flutter组件之Container一:Container组件1.能够设置宽高:flutter中大部分组件不能设置宽高,须要依赖容器2.增加背景色彩3.增加背景图像4.增加边框5.增加内外边框margin和padding //构造方法 Container({ Key? key, this.alignment,//管制child的对其形式 this.padding,//设置内边距 this.color,//设置背景色 this.decoration,//绘制在child上层的装璜,不能与color同时应用 this.foregroundDecoration,//绘制在child下层的装璜 double? width,//宽 double? height,//高 BoxConstraints? constraints,//增加到child上额定的约束条件大小,范畴束缚,constraints有四个属性:minWidth、minHeight、maxWidth、maxHeight。 this.margin,//外边距 this.transform,////设置container的变换矩阵,类型为Matrix4 this.transformAlignment, this.child,//子组件 this.clipBehavior = Clip.none, }) : assert(margin == null || margin.isNonNegative), assert(padding == null || padding.isNonNegative), assert(decoration == null || decoration.debugAssertIsValid()), assert(constraints == null || constraints.debugAssertIsValid()), assert(clipBehavior != null), assert(decoration != null || clipBehavior == Clip.none), assert(color == null || decoration == null, 'Cannot provide both a color and a decoration\n' 'To provide both, use "decoration: BoxDecoration(color: color)".', ), constraints = (width != null || height != null) ? constraints?.tighten(width: width, height: height) ?? BoxConstraints.tightFor(width: width, height: height) : constraints, super(key: key);属性名性能值所属类型alignmenttopCenter:顶部居中对齐 topLeft:顶部左对齐 topRight:顶部右对齐 center:程度垂直居中对齐 centerLeft:垂直居中程度居左对齐 centerRight:垂直居中程度居右对齐 bottomCenter 底部居中对齐bottomLeft:底部居左对齐 bottomRight:底部居右对齐Alignmentdecoration容器的润饰器,用于背景或者borderBoxDecorationmarginContainer与内部其余组件的间隔值为一个 EdgeInsets 对象。EdgeInsets 对象即可调用EdgeInsets.all() 办法对立设置左上右下四条边的边距,也能够调用 EdgeInsets.fromLTRB() 别离设置左上右下四条边的边距paddingContainer边缘与Child之间的间隔值为一个 EdgeInsets 对象。EdgeInsets 对象即可调用EdgeInsets.all() 办法对立设置左上右下四条边的边距,也能够调用 EdgeInsets.fromLTRB() 别离设置左上右下四条边的边距transform调整旋转的角度Matrix4height容器高度doublewidth容器宽度doublechild容器子元素Widghtcolor:Color背景色,不能与 decoration 属性同时设置decoration:Decoration装璜,也就是设置背景色、边框、圆角等,不能和color同时应用,Decoration是抽象类,个别应用BoxDecoration的实现类(FlutterLogoDecoration、ShapeDecoration、UnderlineTabIndicator也是Decoration的实现类) ...

September 23, 2022 · 2 min · jiezi

关于flutter:Flutter-第九课组件之Scaffold和AppBar和Drawer和FloatingActionButton

Flutter 学习第九课:Flutter组件之Scaffold和组件AppBar和Drawer抽屉组件和组件FloatingActionButton悬浮框按钮第一:Scaffold介绍Scaffold:翻译过去就是脚手架意思,Material Design布局构造的根本实现。提供展现抽屉(drawers,比方:侧边栏)、告诉(snack bars) 以及 底部按钮(bottom sheets)。 const Scaffold({ Key? key, this.appBar,//标题栏 this.body,//用于显示以后界面次要内容的Widget this.floatingActionButton,//一个悬浮在body上的按钮,默认显示在右下角 this.floatingActionButtonLocation,// 用于设置floatingActionButton显示的地位 this.floatingActionButtonAnimator,// floatingActionButton挪动到一个新的地位时的动画 this.persistentFooterButtons,// 多状态按钮 this.drawer,// 左侧的抽屉菜单 this.onDrawerChanged, this.endDrawer,// 右'侧的抽屉菜单 this.onEndDrawerChanged, this.bottomNavigationBar,// 底部导航栏。 this.bottomSheet,// 显示在底部的工具栏 this.backgroundColor,// 内容的背景色彩 this.resizeToAvoidBottomInset,// 管制界面内容 body 是否从新布局来防止底部被笼罩,比方当键盘显示的时候,从新布局防止被键盘盖住内容 this.primary = true,// Scaffold是否显示在页面的顶部 this.drawerDragStartBehavior = DragStartBehavior.start,//管制 drawer 的一些个性 this.extendBody = false,//body 是否延长到底部控件 this.extendBodyBehindAppBar = false, this.drawerScrimColor,//侧滑栏拉进去时,用来遮蔽主页面的色彩 this.drawerEdgeDragWidth,//侧滑栏拉进去的宽度 this.drawerEnableOpenDragGesture = true,//左侧侧滑栏是否能够滑动 this.endDrawerEnableOpenDragGesture = true,//右侧侧滑栏是否能够滑动 this.restorationId, }) : assert(primary != null), assert(extendBody != null), assert(extendBodyBehindAppBar != null), assert(drawerDragStartBehavior != null), super(key: key);例如:栗子 ...

September 23, 2022 · 2 min · jiezi

关于flutter:新渲染引擎自定义设计和高质量用户体验的样例应用-Wonderous-现已开源

摸索世界奇观,并体验 Flutter 的弱小之处。 Flutter 的愿景是让你可能在空白画布上绘制出不受限制的精美利用。最近,通过与 gskinner 团队的通力合作,咱们打造了一个全新的挪动利用 Wonderous 来实现这个愿景。咱们采纳不同以往的设计零碎,借助于 Flutter 为 Wonderous 创立出了极具表现力的界面,这个界面为挪动设施量身定制并实现了设计者的创意愿景。 △ Wonderous 利用截图 在开发 Wonderous 时,咱们始终关注下列指标:打造一款有用且乏味的利用。通过摸索世界的神奇景观,Wonderous 利用可让用户漫游在历史、艺术和文化的交汇之地。以后,很多人都难以出门游览,但 Wonderous 可利用精美的插图和优化的动画在你的设施上间接为你展示各地奇迹。展现高质量的用户体验。咱们心愿 Wonderous 在品质上可与零碎框架中的其余任何利用相媲美。Wonderous 以其量身定制、富裕想象力的设计吸引用户,但也应用相熟的手势和行为来确保无缝的用户体验。创立一个用于测试和基准测试的利用。咱们应用 Wonderous 来测试 Impeller,Impeller 是一款新的渲染引擎,现已可在 iOS 零碎上进行实验性预览。到目前为止,咱们对测试后果感到称心,这将有助于验证咱们对 Impeller 能够进步性能的假如。目下在 App Store 上架的这个版本就应用了 Impeller,欢送下载体验,咱们十分期待理解 Impeller 在生产环境中更宽泛的 iOS 设施中的体现。提供一个可供参考的、开源的最佳实际利用。咱们的 Wonderous 代码 在 GitHub 开源,这是一个领有自定义的设计、吸引人的交互方式和新鲜的动画成果的最佳实际利用,并且将无障碍的性能放在首位。创立其他人能够从中学习的资料及文档。在接下来的几周,gskinner 团队将公布更多对于 Wonderous 的内容,其中包含对于如何创立动画、如何整合无障碍性能以及利用性能最佳实际的具体信息。敬请期待! 在 App Store 或 Google Play 商店中下载 Wonderous 之后,你可能想要摸索以下内容: Wonders 中左右滑动时的过渡成果,如果不应用 Flutter 可能会比拟难以实现;当你在“世界历史年表”中挪动时的独特滚动模式;与 Wonderous 设计零碎匹配的定制按钮和图标。该利用已为国内用户提供中文版,请拜访 利用官网 或者到 Wonderous 的 GitHub 开源仓库页面 理解更多。 ...

September 22, 2022 · 1 min · jiezi

关于flutter:Flutter学习第八课组件学习之MaterialApp和控件之Material

Flutter学习第八课:组件学习之MaterialApp和控件之Material一:MaterialApp组件MaterialApp组件位于app.dart文件下 const MaterialApp({ Key? key, this.navigatorKey,//导航键 this.scaffoldMessengerKey,//脚手架键 this.home,//主页,利用关上时显示的页面 Map<String, WidgetBuilder> this.routes = const <String, WidgetBuilder>{},//应用程序顶级路由表 this.initialRoute,//如果构建了导航器,会显示第一个路由的名称 this.onGenerateRoute,//路由治理拦截器 this.onGenerateInitialRoutes,//生成初始化路由 this.onUnknownRoute,//当onGenerateRoute无奈生成路由时调用 List<NavigatorObserver> this.navigatorObservers = const <NavigatorObserver>[],//创立导航器的观察者列表 this.builder,//在导航器下面插入小部件 this.title = '',//程序切换时显示的题目 this.onGenerateTitle,//程序切换时生成题目字符串 this.color,//程序切换时利用图标背景色彩(仅安卓无效) this.theme,//主题色彩 this.darkTheme,//暗黑模式主题色彩 this.highContrastTheme,//零碎申请“高对比度”应用的主题 this.highContrastDarkTheme,//零碎申请“高对比度”暗黑模式下应用的主题色彩 this.themeMode = ThemeMode.system,//应用哪种模式的主题(默认追随零碎) this.locale,//初始区域设置 this.localizationsDelegates,//本地化代理 this.localeListResolutionCallback,//失败或未提供设施的语言环境 this.localeResolutionCallback,//负责计算语言环境 this.supportedLocales = const <Locale>[Locale('en', 'US')],//本地化地区列表 this.debugShowMaterialGrid = false,//绘制基线网格叠加层(仅debug模式) this.showPerformanceOverlay = false,//显示性能叠加 this.checkerboardRasterCacheImages = false,//关上栅格缓存图像的棋盘格 this.checkerboardOffscreenLayers = false,//关上渲染到屏幕外位图的层的棋盘格。 this.showSemanticsDebugger = false,//关上显示可拜访性信息的叠加层 this.debugShowCheckedModeBanner = true,//调试显示查看模式横幅 this.shortcuts,//应用程序用意的键盘快捷键的默认映射 this.actions,//蕴含和定义用户操作的映射 this.restorationScopeId,//应用程序状态复原的标识符 this.scrollBehavior,//可滚动小部件的行为形式 this.useInheritedMediaQuery = false, }) : assert(routes != null), assert(navigatorObservers != null), assert(title != null), assert(debugShowMaterialGrid != null), assert(showPerformanceOverlay != null), assert(checkerboardRasterCacheImages != null), assert(checkerboardOffscreenLayers != null), assert(showSemanticsDebugger != null), assert(debugShowCheckedModeBanner != null), routeInformationProvider = null, routeInformationParser = null, routerDelegate = null, backButtonDispatcher = null, super(key: key);个别应用: ...

September 22, 2022 · 2 min · jiezi

关于flutter:flutter系列之flutter中常用的Stack-layout详解

简介对于古代APP的利用来说,为了更加好看,通常会须要用到不同图像的重叠成果,比方在一个APP用户背景头像下面增加一个按钮,示意能够批改用户信息等。 要实现这样的成果,咱们须要在一个Image下面重叠其余的widget对象,flutter为咱们提供了这样的一个十分不便的layout组件叫做Stack,明天和大家一起来聊一聊Stack的应用。 Stack详解咱们先来看下Stack的定义: class Stack extends MultiChildRenderObjectWidget Stack继承自MultiChildRenderObjectWidget,示意在stack中能够render多个child widget对象。 因为Stack中的child是重叠关系,所以须要对child进行定位,依据定位的不同Stack中的child能够分为两种类型,别离是positioned和non-positioned。 所谓positioned,是指child widget被包装在Positioned中。什么是Positioned呢? Positioned是专门用来定位Stack中的child地位的一个widget。所以Positioned必须用在Stack中,并且Positioned和Stack的门路之间只能存在StatelessWidget或者StatefulWidget这两种widget。 如果一个对象被蕴含在Positioned中,那么这个对象就是一个Stack中的positioned对象。 Positioned中除了封装的child之外,还有6个属性,如下所示: const Positioned({ Key? key, this.left, this.top, this.right, this.bottom, this.width, this.height, required Widget child, })这六个属性别离是left,top,right,bottom,width和height。其中left,top,right,bottom别离示意到左,顶,右,底的间隔,这个间隔是绝对stack来说的。而width和height则示意的是Positioned的宽度和高度。 事实上,应用left和right能够定义出width,应用top和bottom能够定义出height。 如果在一个轴方向的三个值都不存在,那么会应用Stack.alignment来定位子元素。 如果六个值都不存在,那么这个child就是一个non-positioned的child。 对于non-positioned的child,是通过Stack的alignment来进行布局的,默认状况下是按top left corners进行布局的。 Stack的属性咱们接下来看一下Stack中有哪些属性,上面是Stack的构造函数: Stack({ Key? key, this.alignment = AlignmentDirectional.topStart, this.textDirection, this.fit = StackFit.loose, @Deprecated( 'Use clipBehavior instead. See the migration guide in flutter.dev/go/clip-behavior. ' 'This feature was deprecated after v1.22.0-12.0.pre.', ) this.overflow = Overflow.clip, this.clipBehavior = Clip.hardEdge, List<Widget> children = const <Widget>[], })能够看到Stack中有alignment,textDirection,fit,overflow和clipBehavior这几个属性。 ...

September 20, 2022 · 1 min · jiezi

关于flutter:Flutter第七课Flutter-的Widget的生命周期和App生命周期

Flutter第七课:Flutter 的Widget的生命周期和App生命周期一:StatefulWidget 的生命周期StatefulWidget 组件生命周期分为三组:1.初始化期:createState() ,initState()2.更新期:didChangeDependencies(),build(BuildContext context),didUpdateWidget()3.销毁期:deactivate(),dispose() 1.createState()(1)创立StatefulWidget之后调用的第一个办法(2)该办法是形象办法 , 必须笼罩重写该办法 2.initState()(1)该办法是创立 Widget 组件时除构造方法之外的第一个办法 (2) 对应 Android 中的 onCreate 办法 ; 对应 iOS 中的 viewDidLoad 办法 (3)在该办法中执行一些初始化操作 3.didChangeDependencies()(1)创立 Widget 组件时 , 调用完 initState 办法后 , 调用该办法(2)InheritedWidget 相干 ( 暂不波及 ) ; 4.build()(1)调用完 didChangeDependencies 办法后调用该办法 (2)调用 setState 办法之后 , 该办法也会被调用 ;(3)页面每次渲染时都会调用该办法 5.didUpdateWidget()(1)该生命周期办法不常常调用 , 只有在父容器组件重绘时才调用该办法(2)传入的 oldWidget 参数是旧的组件信息 , 将以后的 Widget 与旧的 Widget 进行比照 , 如果不相等 , 便执行额定操作 ; 6.deactivate()(1)该生命周期办法不常常调用 , 只有在组件被移除时才调用 7.dispose()(1)组件被销毁时调用 , 要在该办法中进行资源的开释与销毁操作 8.reassemble()(1)此回调是专门为了开发调试而提供的,在热重载(hot reload)时会被调用,此回调在Release模式下永远不会被调用 ...

September 16, 2022 · 2 min · jiezi

关于flutter:flutter系列之flutter中常用的ListView-layout详解

简介ListView是蕴含多个child组件的widget,在ListView中所有的child widget都是以list的模式来出现的,你能够自定义List的方向,然而和GridView不同的是ListView中的每一个List外面都只蕴含一个widget。 明天咱们来具体理解一下ListView的底层实现和具体的利用。 ListView详解和GridView一样,ListView也是继承自ScrollView,示意它是一个能够滚动的View。 具体而言,ListView首先继承自BoxScrollView: class ListView extends BoxScrollView而后BoxScrollView又继承自ScrollView: abstract class BoxScrollView extends ScrollView ListView中的特有属性首先咱们来看下ListView中的特有属性,ListView和它的父类相比,多了三个属性,别离是itemExtent,prototypeItem和childrenDelegate。 其中itemExtent是一个double类型的数据,如果给定的是一个非空值,那么示意的是child在scroll方向的extent大小。这个属性次要用来管制children的extend信息,这样每个child就不须要自行来判断本人的extend。 应用itemExtent的益处在于,ListView能够对立的在滚动机制上进行优化,从而晋升性能体现。 prototypeItem是一个widget,从名字就能够看出,这个一个prototype的widget,也就是说是一个原型,其余的child能够参照这个原型widget的大小进行extent的设置。 ListView中的最初一个自定义属性是childrenDelegate,这个childrenDelegate和GridView中的含意是一样的,用来生成ListView中child。 之前咱们在解说GirdView的时候有提到过,GirdView中还有一个自定义的属性叫做gridDelegate,这个gridDelegate是一个SliverGridDelegate的实例,用来管制子组件在GridView中的布局。 因为ListView的子组件的布局是曾经确定的,所以就不再须要gridDelegate了,这是ListView和GridView的一大区别。 ListView作为一个继承的类,须要实现一个buildChildLayout的办法: @override Widget buildChildLayout(BuildContext context) { if (itemExtent != null) { return SliverFixedExtentList( delegate: childrenDelegate, itemExtent: itemExtent!, ); } else if (prototypeItem != null) { return SliverPrototypeExtentList( delegate: childrenDelegate, prototypeItem: prototypeItem!, ); } return SliverList(delegate: childrenDelegate); }这个办法的实现逻辑和咱们之前讲到的三个属性是相关联的,在buildChildLayout中,如果itemExtent有值的话,因为itemExtent自身就是一个固定值,所以返回的是SliverFixedExtentList。 如果itemExtent没有设置,并且prototypeItem有值的话,返回的是一个SliverPrototypeExtentList。 最初,如果itemExtent和prototypeItem都没有设置的话,返回的是一个SliverList对象。 ListView的构造函数和GridView一样,为了满足咱们的多样性的设计需要,ListView也提供了多个构造函数。 首先咱们来看下ListView的最根本的构造函数: ListView({ Key? key, Axis scrollDirection = Axis.vertical, bool reverse = false, ScrollController? controller, bool? primary, ScrollPhysics? physics, bool shrinkWrap = false, EdgeInsetsGeometry? padding, this.itemExtent, this.prototypeItem, bool addAutomaticKeepAlives = true, bool addRepaintBoundaries = true, bool addSemanticIndexes = true, double? cacheExtent, List<Widget> children = const <Widget>[], int? semanticChildCount, DragStartBehavior dragStartBehavior = DragStartBehavior.start, ScrollViewKeyboardDismissBehavior keyboardDismissBehavior = ScrollViewKeyboardDismissBehavior.manual, String? restorationId, Clip clipBehavior = Clip.hardEdge, })这里itemExtent和prototypeItem这两个属性是内部传入的,childrenDelegate是通过其余的参数结构而来的: ...

September 16, 2022 · 2 min · jiezi

关于flutter:MobLink-for-Flutter

插件是基于MobLink 对Flutter进行插件裁减反对。目标是不便Flutter开发者更不便地集成应用MobLink。Demo例子:https://github.com/MobClub/Mo... 开始集成引入插件在 pubspec.yaml 文件中退出上面依赖 dependencies: moblink: mobcommonlib: iOS端配置平台设置参考iOS集成文档 实现 第一步增加配置里的XCode配置,配置初始化信息MOBAppKey 和 MOBAppSecret;第二步Mob后盾根本配置里的iOS端配置信息Android端配置平台设置参考 Android集成文档 实现 第一步按Android集成文档中的第一点注册利用,申请Mob的 AppKey 和 AppSecret;第二步按Android集成文档中的第一点实现集成配置 1.关上我的项目根目录的build.gradle,在buildscrip–>dependencies 模块上面增加classpath 'com.mob.sdk:MobSDK:+',如下所示; buildscript { repositories { maven { url "https://mvn.mob.com/android" } ... } dependencies { ... classpath "com.mob.sdk:MobSDK:2018.0319.1724" }}2.在应用MobLink模块的build.gradle中,增加MobSDK插件和扩大,如下所示: // 增加插件apply plugin: 'com.mob.sdk'// 在MobSDK的扩大中注册MobLink的相干信息MobSDK { appKey "您的Mob-AppKey" appSecret "您的Mob-AppSecret" MobLink { uriScheme "您后盾配置的scheme" appLinkHost "您后盾开启AppLink时生成的Host" }}第三步在MainActivity中增加以下代码: //导入的包import com.mob.moblink.MobLink;// 必须重写该办法,避免MobLink在某些情景下无奈还原 @Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); setIntent(intent); MobLink.updateNewIntent(getIntent(), this); } ...

September 15, 2022 · 1 min · jiezi

关于flutter:flutter系列之flutter中常用的GridView-layout详解

简介GridView是一个网格化的布局,如果在填充的过程中子组件超出了展现的范畴的时候,那么GridView会主动滚动。 因为这个滚动的个性,所以GridView是一个十分好用的Widget。明天咱们一起来摸索一下GridView这个layout组件的机密。 GridView详解GridView是一个可滚动的view,也就是ScrollView,事实上GridView继承自BoxScrollView: class GridView extends BoxScrollView而它的父类BoxScrollView,则是继承自ScrollView: abstract class BoxScrollView extends ScrollView 能够看到BoxScrollView是一个抽象类,它有两个子类,别离是明天咱们要讲的GridView和下期要讲的ListView。 这两个组件的区别是GridView是一个2D的布局,而ListView是一个线性layout的布局。 作为BoxScrollView的子类,GridView须要实现buildChildLayout办法如下所示: @override Widget buildChildLayout(BuildContext context) { return SliverGrid( delegate: childrenDelegate, gridDelegate: gridDelegate, ); }这里GridView返回了一个SliverGrid,这个SliverGrid中有两个属性,别离是childrenDelegate和gridDelegate。 其中gridDelegate是一个SliverGridDelegate的实例,用来管制子组件在GridView中的布局。 childrenDelegate是一个SliverChildDelegate的实例,用来生成GridView中的子组件。 这两个属性在GridView的构造函数中有应用,咱们接下来会具体进行解说。 GridView的构造函数GridView有很多个构造函数,首先是蕴含所有参数的全参数构造函数: GridView({ Key? key, Axis scrollDirection = Axis.vertical, bool reverse = false, ScrollController? controller, bool? primary, ScrollPhysics? physics, bool shrinkWrap = false, EdgeInsetsGeometry? padding, required this.gridDelegate, bool addAutomaticKeepAlives = true, bool addRepaintBoundaries = true, bool addSemanticIndexes = true, double? cacheExtent, List<Widget> children = const <Widget>[], int? semanticChildCount, DragStartBehavior dragStartBehavior = DragStartBehavior.start, Clip clipBehavior = Clip.hardEdge, ScrollViewKeyboardDismissBehavior keyboardDismissBehavior = ScrollViewKeyboardDismissBehavior.manual, String? restorationId, })在这个构造函数中,须要传入自定义的gridDelegate,所以在构造函数中gridDelegate是required状态: ...

September 13, 2022 · 2 min · jiezi

关于flutter:融云-Flutter-SDK跨平台开发的真香之选

(点击报名融云 2022 社交泛娱乐出海嘉年华) Flutter 可能是最受欢迎的跨平台框架。关注【融云寰球互联网通信云】理解更多 作为 Google 2018 年正式推出的构建 UI 工具包,Flutter 反对一套代码库高效构建多平台利用;应用 Dart 为开发语言,利用 Skia 绘图引擎,间接通过 CPU、GPU 进行绘制,不须要依赖任何原生的控件。 谷歌在 2022 开发大会上正式推出 Flutter 3.0,并发表目前已有超过 50 万个应用程序是用 Flutter 建设的。从咱们相熟的微信,到出海巨头 SHEIN 以及大量行业和公共机构利用,越来越多开发者采纳它构建应用程序。为了助力开发者更加简略疾速地集成 IM 和 RTC 相干性能,融云提供 Flutter SDK,为开发者带来更敌对、更简便的即时通讯和实时音视频能力。 Flutter 为何如此受青眼?多平台的解决方案在 Flutter 3.0 公布后,Flutter 曾经反对 iOS、Android、Web、Windows、Mac 以及 Linux 六个平台,开发者能够应用一套代码库在所有的平台进行运行,使得 Flutter 在跨平台的解决方案上有了更强的竞争力。 高性能的渲染计划相比其余跨平台计划,Flutter 基于 Skia 2D 硬件加速图形引擎封装的渲染计划,依赖零碎的图形绘制,最大水平保障了多平台的一致性,且渲染效率相比原生性能相差无几。 丰盛社区生态截至目前,Flutter GitHub 上曾经有 144K 个 Star,官网仓库 pub.dev 曾经上传了大概 3W 个插件,蕴含了罕用的各种性能。融云的次要性能都提供了相干的 Flutter 插件并上传到了官网仓库。 另外,在融云出品的程序员综艺《猿桌派》中,来自知乎的张彦瑞还从开发者的角度分享了应用 Flutter 的另一重吸引力: “Flutter 是开源的,让咱们有机会对 UI 零碎的构建、内存治理、编译等进行深挖。即便咱们当前不必 Flutter 了,也能够通过它去理解一套语言是怎么构建的,程序是怎么加载的,整个树是怎么构建的,渲染引擎是怎么做的。这些都是能够让咱们触类旁通的底层宝藏。” ...

September 10, 2022 · 2 min · jiezi

关于flutter:Dart-218-正式发布

互操作性加强、平台特定的网络组件、优化类型推断,以及空平安语言里程碑的近期更新 文/ Michael Thomsen, Google Flutter & Dart 产品经理 Dart 2.18 稳定版也随着 Flutter 3.3 稳定版一起公布,本次更新带来了 Dart 与 Objective-C \& Swift 互操作个性的预览版,以及依据这个个性构建的 iOS/macOS 网络组件的 package。新的 Dart 还包含泛型办法的类型推断优化、异步代码的性能晋升、pub.dev 新的性能,以及对咱们工具和外围库的一些调整。 文章最初咱们也给出了最新的空平安迁徙状态状况数据,以及最终齐全实现 Dart 空平安个性路线图的一个重要更新,请务必读到最初。 Dart 与 Objective-C 和 Swift 互调早在 2020 年的时候,咱们公布了内部性能接口 (FFI) 用于调用原生 C 语言接口的预览,并在 2021 年的 Dart 2.12 中正式公布。自那时起,大量的 package 借助于 FFI 的劣势与现有的原生 C 语言接口 API 集成,举一些例子,比方 file_picker、printing、win32、objectbox、realm、isar、tflite_flutter 以及 dbus 这些 package。 Dart 团队心愿支流编程语言之间的互操作可能在所有 Dart 能够运行的平台上都反对,2.18 正式版达到了这个指标的下一个里程碑,当初,Dart 代码能够间接调用 Objective-C 和 Swift 代码了,次要用于在 macOS 和 iOS 平台调用 API。Dart 反对“全端调用”——从后端的命令行代码,再到前端的 Flutter 界面,你能够在任何利用中应用这种互操作机制。 ...

September 8, 2022 · 4 min · jiezi

关于flutter:flutter系列之flutter中常用的container-layout详解

简介在上一篇文章中,咱们列举了flutter中的所有layout类,并且具体介绍了两个十分罕用的layout:Row和Column。 把握了下面两个根本的layout还是不够的,如果须要应酬日常的layout应用,咱们还须要把握多一些layout组件。明天咱们会介绍一个功能强大的layout:Container layout。 Container的应用Container是一个空白的容器,通常能够用Container来封装其余的widget。那么为什么还须要把widget封装在Container中呢?这是因为Container中蕴含了一些非凡的性能。 比方Container中能够设置背景色彩或者背景图片,并且能够设置padding, margins和borders。这就为组件的自定义提供了诸多空间。 首先看一下Container的定义和构造函数: class Container extends StatelessWidget { Container({ Key? key, this.alignment, this.padding, this.color, this.decoration, this.foregroundDecoration, double? width, double? height, BoxConstraints? constraints, this.margin, this.transform, this.transformAlignment, this.child, this.clipBehavior = Clip.none, })能够看到Container是一个StatelessWidget,它的构造函数能够传入多个十分有用的属性,用来管制Container的体现。 Container中有padding,decoration,constraints和margin这些和地位相干的一些属性,他们有什么关系呢? container首先将child用padding包裹起来,padding能够用decoration进行填充。 填充后的padding又能够利用constraints来进行限度(比方width和height),而后这个组件又能够应用margin空白包裹起来。 接下来咱们看一个简略的Container中蕴含Column和Row的例子。 首先结构一个container widget,它蕴含一个Column: Widget build(BuildContext context) { return Container( decoration: const BoxDecoration( color: Colors.white, ), child: Column( children: [ buildBoxRow(), buildBoxRow(), ], ), ); }这里给Container设置了一个BoxDecoration,用于指定Container的背景色彩。 在Child中给定了一个Column widget,它的child是一个Row对象。 Widget buildBoxRow() => Row( textDirection: TextDirection.ltr, children: [ Container( width: 100, child: Image.asset("images/head.jpg") ) ], );这里的Row中又是一个蕴含了Image的Container对象。 ...

September 8, 2022 · 2 min · jiezi

关于flutter:祝福-Eric-的下一段旅程Flutter-33-现已发布

Flutter 团队及社区成员们在漂亮的城市挪威奥斯陆向您发来问候,咱们正在此加入社区举办的 Flutter Vikings 流动,这是一个为期两天的开发技术交换盛会,尽管线下门票曾经售罄,但您还能够通过在线形式查看本次会议。本周,咱们也有很多更新要分享给各位开发者们。 Flutter 的使用量和生态系统都在持续增长,每天有超过 1,000 款应用 Flutter 的、新的挪动利用公布到 App Store 和 Google Play 商店,在 Web 端和桌面端的应用也在持续增长。Flutter 生态中目前也有超过 25,000 个以上的 package,这也进一步证实了 Flutter 的成熟和广泛应用。 明天,咱们正式公布 Flutter 3.3。这个版本专一于欠缺和性能改良,以增强 Flutter 3 公布以来的新个性。Flutter 3.3 退出了一些新的组件并修复了一些谬误以增强对 Material 3 标准的反对,也退出了对 iPad 上应用随手写输入文本的反对、可抉择的文本分组和触控板反对等对平板电脑和桌面开发者有帮忙的新反对。这个版本还包含了 Dart 2.18 的公布,它为应用 Swift 和 Objective-C 构建的库和代码退出了 FFI 的反对。应用这个 Dart 版本构建的利用,将会在桌面端、Web 端和挪动端体现出更好的性能。因而咱们强力建议您即刻运行命令 flutter upgrade 来降级到最新版。 公布 Wonderous 利用咱们与 gskinner 的设计团队通力合作,公布了一个名为 Wonderous 的利用,旨在向大家展现 Flutter 的弱小性能——帮忙您构建出高质量、精美的用户体验,而它自身就是一个十分精美的利用——从印度阿格拉市令人惊叹的泰姬陵到墨西哥尤卡坦半岛上的玛雅遗迹,Wonderous 将世界上一些十分了不起的中央带到您的手机上,应用视频和图像来摸索这些艺术、历史和文化的交加。 咱们心愿您与家人和敌人分享 Wonderous,更重要的是,它还作为一个开源我的项目供开发者们摸索。作为一个实在上线经营的利用,它提供了一个残缺且全面的示例,展现了咱们心愿为中高级开发者带去灵感和创想的最佳实际。将来的几周工夫里,gskinner 团队将会分享对于这个利用的更多技术细节文章,包含对无障碍的反对、动画成果以及性能方面的技巧等内容。 引入新的图形引擎: Impeller除了下面提到的 3.3 版本的改良内容之外,Flutter 团队还在致力开发 下一代的渲染层引擎: Impeller。 ...

September 7, 2022 · 1 min · jiezi

关于flutter:Flutter-第六课Flutter动画Tween和绘制CustomPainter

Flutter 第六课:Flutter动画Tween和绘制CustomPainter第一步:建设2个dart文件rose_data.dart文件里是动画的执行的坐标点 import 'package:flutter/material.dart';class RoseData { static final List<Offset> flowerPoints = [ Offset(182.0, 136.3), Offset(182.7, 135.3), Offset(183.0, 135.3), Offset(183.3, 135.3), Offset(183.7, 135.3), Offset(184.0, 135.0), Offset(184.3, 135.0), Offset(184.3, 134.7), Offset(184.7, 134.7), Offset(184.7, 134.3), Offset(185.0, 134.3), Offset(185.0, 134.0), Offset(185.3, 134.0), Offset(185.7, 134.0), Offset(185.7, 133.7), Offset(186.0, 133.3), Offset(186.0, 133.0), Offset(186.0, 132.7), Offset(186.0, 132.3), Offset(186.0, 131.7), Offset(186.0, 131.0), Offset(186.0, 130.7), Offset(186.3, 130.7), Offset(186.3, 130.3), Offset(186.7, 129.7), Offset(186.7, 129.3), Offset(186.7, 129.0), Offset(186.7, 128.7), Offset(186.7, 128.0), Offset(187.0, 127.7), Offset(187.3, 127.3), Offset(187.7, 126.7), Offset(187.7, 126.3), Offset(187.7, 126.0), Offset(187.0, 125.3), Offset(187.0, 124.7), Offset(186.7, 123.7), Offset(186.7, 123.0), Offset(186.7, 122.7), Offset(186.7, 122.3), Offset(186.7, 122.0), Offset(186.7, 121.7), Offset(186.3, 121.7), Offset(186.0, 121.7), Offset(185.7, 121.3), Offset(185.3, 121.3), Offset(185.0, 121.3), Offset(184.7, 121.0), Offset(184.3, 120.7), Offset(184.0, 120.7), Offset(184.0, 120.3), Offset(183.7, 120.3), Offset(183.3, 120.3), Offset(183.0, 120.3), Offset(182.7, 120.3), Offset(182.3, 120.0), Offset(181.7, 120.0), Offset(181.3, 120.0), Offset(180.7, 120.0), Offset(180.3, 120.0), Offset(180.0, 119.7), Offset(179.7, 119.7), Offset(179.3, 119.7), Offset(179.0, 119.7), Offset(178.7, 119.7), Offset(178.3, 119.7), Offset(178.0, 119.7), Offset(177.7, 119.7), Offset(177.3, 119.7), Offset(177.0, 119.7), Offset(176.7, 119.7), Offset(176.0, 119.7), Offset(175.7, 119.7), Offset(175.3, 120.0), Offset(174.7, 120.0), Offset(174.7, 120.3), Offset(174.3, 120.3), Offset(174.0, 120.7), Offset(173.7, 120.7), Offset(173.3, 120.7), Offset(173.3, 121.0), Offset(173.3, 121.3), Offset(172.7, 121.7), Offset(172.3, 121.7), Offset(172.0, 121.7), Offset(171.3, 122.0), Offset(170.7, 122.3), Offset(170.0, 122.7), Offset(169.3, 123.0), Offset(169.0, 123.3), Offset(168.3, 123.3), Offset(168.0, 123.7), Offset(167.7, 123.7), Offset(167.7, 124.0), Offset(167.3, 124.0), Offset(167.0, 124.3), Offset(166.7, 124.3), Offset(166.0, 124.7), Offset(165.3, 125.0), Offset(164.7, 125.3), Offset(164.3, 125.7), Offset(163.7, 125.7), Offset(163.0, 126.0), Offset(162.3, 127.0), Offset(162.0, 127.0), Offset(161.7, 127.3), Offset(161.3, 127.7), Offset(161.3, 128.0), Offset(161.3, 128.3), Offset(161.3, 128.7), Offset(161.3, 129.0), Offset(161.3, 129.3), Offset(161.3, 129.7), Offset(161.3, 130.0), Offset(161.3, 130.3), Offset(161.3, 130.7), Offset(161.3, 131.0), Offset(161.3, 131.7), Offset(161.3, 132.3), Offset(161.3, 133.3), Offset(161.3, 134.0), Offset(161.3, 134.7), Offset(161.3, 135.3), Offset(161.3, 136.0), Offset(161.3, 136.3), Offset(161.3, 136.7), Offset(161.3, 137.0), Offset(161.3, 137.3), Offset(161.3, 137.7), Offset(161.3, 138.0), Offset(161.3, 138.3), Offset(161.3, 138.7), Offset(161.3, 139.0), Offset(161.3, 139.3), Offset(161.3, 140.0), Offset(161.3, 140.7), Offset(161.3, 141.0), Offset(161.3, 141.7), Offset(161.3, 142.0), Offset(161.3, 142.3), Offset(161.7, 142.7), Offset(161.7, 143.0), Offset(162.0, 143.3), Offset(162.0, 143.7), Offset(162.3, 143.7), Offset(162.7, 144.0), Offset(162.7, 144.3), Offset(163.0, 144.3), Offset(163.3, 144.3), Offset(163.3, 144.7), Offset(163.7, 144.7), Offset(163.7, 145.0), Offset(164.0, 145.3), Offset(164.7, 145.3), Offset(165.0, 145.7), Offset(165.3, 146.0), Offset(165.3, 146.3), Offset(165.7, 146.3), Offset(165.7, 146.7), Offset(166.0, 146.7), Offset(166.3, 146.7), Offset(166.7, 146.7), Offset(167.0, 147.0), Offset(167.3, 147.0), Offset(168.0, 147.3), Offset(168.3, 147.3), Offset(168.7, 147.3), Offset(169.0, 147.3), Offset(169.3, 147.3), Offset(169.7, 147.3), Offset(170.0, 147.3), Offset(170.3, 147.3), Offset(170.7, 147.3), Offset(171.0, 147.3), Offset(171.3, 147.3), Offset(171.7, 147.3), Offset(172.0, 147.3), Offset(172.3, 147.3), Offset(172.7, 147.3), Offset(173.0, 147.3), Offset(173.3, 147.3), Offset(173.7, 147.7), Offset(174.0, 147.7), Offset(174.3, 147.7), Offset(174.7, 147.7), Offset(175.0, 147.7), Offset(175.3, 147.7), Offset(175.7, 147.7), Offset(176.3, 147.7), Offset(177.0, 147.7), Offset(177.3, 147.7), Offset(177.7, 147.7), Offset(178.0, 147.7), Offset(178.3, 147.7), Offset(178.7, 147.7), Offset(179.0, 147.7), Offset(180.0, 147.7), Offset(180.7, 147.7), Offset(182.0, 147.7), Offset(182.7, 147.7), Offset(183.3, 147.7), Offset(184.0, 147.7), Offset(184.3, 147.7), Offset(184.7, 147.7), Offset(185.0, 147.7), Offset(185.3, 147.7), Offset(185.7, 147.7), Offset(186.0, 147.7), Offset(186.3, 147.7), Offset(186.7, 147.7), Offset(187.0, 147.7), Offset(187.3, 147.7), Offset(187.7, 147.7), Offset(188.0, 147.7), Offset(188.3, 147.7), Offset(188.7, 147.7), Offset(189.0, 147.7), Offset(189.3, 147.7), Offset(189.3, 147.3), Offset(189.7, 147.3), Offset(190.0, 147.3), Offset(190.3, 147.3), Offset(190.3, 147.0), Offset(190.7, 147.0), Offset(191.0, 147.0), Offset(191.3, 147.0), Offset(191.7, 146.7), Offset(192.0, 146.7), Offset(192.3, 146.3), Offset(192.7, 146.3), Offset(193.0, 146.3), Offset(193.0, 146.0), Offset(193.3, 146.0), Offset(193.7, 145.7), Offset(194.3, 145.3), Offset(195.0, 145.0), Offset(195.3, 145.0), Offset(195.3, 144.7), Offset(196.0, 144.7), Offset(196.3, 144.3), Offset(196.3, 144.0), Offset(196.7, 144.0), Offset(197.0, 144.0), Offset(197.3, 143.7), Offset(197.7, 143.3), Offset(198.0, 143.0), Offset(198.7, 143.0), Offset(199.3, 142.3), Offset(199.7, 142.0), Offset(200.3, 142.0), Offset(200.7, 142.0), Offset(200.7, 141.7), Offset(201.0, 141.7), Offset(201.3, 141.3), Offset(201.7, 141.0), Offset(202.0, 141.0), Offset(202.0, 140.7), Offset(202.3, 140.7), Offset(202.7, 140.7), Offset(203.0, 140.3), Offset(203.3, 140.3), Offset(203.7, 140.0), Offset(204.0, 140.0), Offset(204.0, 139.7), Offset(204.0, 139.3), Offset(204.0, 139.0), Offset(204.0, 138.7), Offset(204.0, 138.3), Offset(204.3, 138.0), Offset(204.7, 138.0), Offset(205.0, 137.7), Offset(205.3, 137.3), Offset(205.3, 137.0), Offset(205.3, 136.7), Offset(205.3, 136.3), Offset(205.7, 135.7), Offset(206.0, 135.3), Offset(206.3, 135.0), Offset(206.3, 134.7), Offset(206.7, 134.7), Offset(206.7, 134.3), Offset(206.7, 134.0), Offset(206.7, 133.7), Offset(206.7, 133.3), Offset(206.7, 133.0), Offset(207.0, 132.3), Offset(207.0, 132.0), Offset(207.0, 131.7), Offset(207.0, 131.3), Offset(207.0, 130.7), Offset(207.0, 130.0), Offset(207.0, 129.3), Offset(207.0, 128.3), Offset(207.0, 127.7), Offset(207.0, 127.0), Offset(207.0, 126.7), Offset(207.0, 126.3), Offset(207.0, 126.0), Offset(207.0, 125.7), Offset(207.0, 125.3), Offset(207.0, 125.0), Offset(207.0, 124.3), Offset(206.7, 124.0), Offset(206.3, 123.3), Offset(206.0, 122.7), Offset(206.0, 122.3), Offset(205.7, 122.0), Offset(205.3, 121.7), Offset(205.3, 121.3), Offset(205.0, 121.3), Offset(205.0, 121.0), Offset(204.7, 121.0), Offset(204.3, 121.0), Offset(204.3, 120.7), Offset(204.0, 120.7), Offset(203.3, 120.3), Offset(202.7, 119.7), Offset(202.7, 119.3), Offset(202.3, 119.3), Offset(202.0, 119.3), Offset(201.7, 119.3), Offset(201.7, 119.0), Offset(201.0, 119.0), Offset(200.0, 118.3), Offset(199.7, 118.3), Offset(199.3, 118.0), Offset(199.0, 117.7), Offset(198.7, 117.3), Offset(198.3, 117.3), Offset(198.3, 117.0), Offset(198.0, 117.0), Offset(197.7, 117.0), Offset(197.3, 117.0), Offset(197.0, 116.7), Offset(196.7, 116.3), Offset(195.3, 116.0), Offset(194.7, 115.3), Offset(194.3, 115.3), Offset(194.0, 115.3), Offset(194.0, 115.0), Offset(193.0, 115.0), Offset(192.3, 115.0), Offset(191.3, 114.3), Offset(189.7, 114.0), Offset(189.0, 113.7), Offset(188.7, 113.3), Offset(188.3, 113.3), Offset(188.0, 113.3), Offset(188.0, 113.0), Offset(187.0, 113.0), Offset(186.0, 112.7), Offset(185.0, 112.3), Offset(184.0, 112.0), Offset(183.7, 111.7), Offset(183.3, 111.7), Offset(183.0, 111.7), Offset(181.7, 111.7), Offset(180.0, 111.3), Offset(179.0, 111.0), Offset(178.3, 111.0), Offset(178.3, 110.7), Offset(178.0, 110.7), Offset(177.7, 110.7), Offset(176.7, 110.7), Offset(175.3, 110.7), Offset(174.3, 110.7), Offset(173.3, 110.3), Offset(173.0, 110.3), Offset(172.7, 110.3), Offset(172.0, 110.3), Offset(171.7, 110.3), Offset(170.3, 110.3), Offset(169.3, 110.3), Offset(168.7, 110.3), Offset(168.0, 110.3), Offset(167.0, 110.3), Offset(166.3, 110.3), Offset(165.7, 110.3), Offset(164.7, 110.3), Offset(163.3, 110.7), Offset(162.3, 111.0), Offset(161.3, 111.0), Offset(160.0, 111.3), Offset(159.0, 111.3), Offset(157.0, 111.7), Offset(155.7, 111.7), Offset(155.3, 112.0), Offset(155.0, 112.0), Offset(155.0, 112.3), Offset(154.7, 112.3), Offset(153.7, 112.7), Offset(152.7, 113.3), Offset(151.0, 114.0), Offset(149.7, 114.3), Offset(149.0, 114.7), Offset(149.0, 115.0), Offset(148.7, 115.0), Offset(148.0, 115.7), Offset(147.3, 116.3), Offset(146.7, 117.0), Offset(146.3, 117.3), Offset(146.3, 117.7), Offset(146.3, 118.0), Offset(146.3, 118.3), Offset(146.3, 118.7), Offset(145.7, 119.3), Offset(145.3, 120.0), Offset(144.3, 121.3), Offset(144.3, 122.0), Offset(144.3, 122.7), Offset(144.3, 123.0), Offset(143.7, 125.0), Offset(143.0, 126.7), Offset(142.0, 129.3), Offset(141.3, 130.3), Offset(141.3, 130.7), Offset(141.0, 131.3), Offset(141.0, 131.7), Offset(141.0, 132.0), Offset(141.0, 132.3), Offset(141.0, 132.7), Offset(141.0, 133.7), Offset(140.7, 135.7), Offset(140.7, 137.0), Offset(140.7, 138.0), Offset(140.7, 138.3), Offset(140.7, 138.7), Offset(140.7, 139.0), Offset(140.7, 139.3), Offset(140.7, 139.7), Offset(140.7, 140.3), Offset(140.7, 142.0), Offset(140.7, 142.7), Offset(140.7, 143.7), Offset(141.0, 143.7), Offset(141.3, 143.7), Offset(141.7, 144.3), Offset(142.0, 144.7), Offset(142.3, 145.3), Offset(142.7, 146.3), Offset(143.3, 147.0), Offset(143.7, 148.0), Offset(144.0, 148.0), Offset(144.3, 148.7), Offset(145.0, 149.7), Offset(145.7, 150.0), Offset(145.7, 150.7), Offset(146.0, 151.3), Offset(146.3, 151.7), Offset(146.7, 152.3), Offset(147.3, 153.0), Offset(147.7, 153.7), Offset(148.3, 154.7), Offset(148.7, 155.0), Offset(149.0, 155.3), Offset(150.3, 156.3), Offset(151.0, 157.0), Offset(151.7, 157.7), Offset(152.0, 157.7), Offset(152.3, 158.3), Offset(153.7, 159.3), Offset(154.7, 160.0), Offset(154.7, 160.7), Offset(155.3, 160.7), Offset(156.7, 161.0), Offset(157.7, 161.7), Offset(159.0, 162.0), Offset(159.7, 162.3), Offset(160.0, 162.3), Offset(161.0, 162.7), Offset(162.0, 162.7), Offset(163.0, 162.7), Offset(164.0, 163.3), Offset(165.0, 163.3), Offset(165.3, 163.3), Offset(166.3, 163.7), Offset(167.0, 163.7), Offset(167.3, 163.7), Offset(167.7, 164.0), Offset(168.3, 164.3), Offset(169.0, 164.3), Offset(170.0, 164.7), Offset(170.3, 164.7), Offset(171.3, 164.7), Offset(171.7, 164.7), Offset(173.0, 164.7), Offset(174.3, 164.7), Offset(175.3, 164.7), Offset(176.3, 164.7), Offset(177.3, 164.7), Offset(178.7, 164.7), Offset(180.0, 164.7), Offset(181.0, 165.0), Offset(181.7, 165.0), Offset(182.3, 165.0), Offset(182.7, 165.0), Offset(183.3, 165.0), Offset(184.3, 165.3), Offset(186.0, 165.3), Offset(186.7, 165.3), Offset(187.7, 165.3), Offset(188.7, 165.3), Offset(189.0, 165.3), Offset(190.0, 165.3), Offset(191.0, 165.3), Offset(191.7, 165.3), Offset(192.7, 165.3), Offset(194.0, 165.3), Offset(194.7, 165.0), Offset(195.3, 164.7), Offset(196.0, 164.7), Offset(196.7, 164.3), Offset(197.7, 164.0), Offset(198.3, 163.7), Offset(199.3, 163.3), Offset(199.7, 163.3), Offset(200.7, 163.0), Offset(202.0, 162.7), Offset(203.0, 162.7), Offset(204.7, 162.0), Offset(206.0, 161.3), Offset(207.3, 161.0), Offset(208.0, 160.7), Offset(209.0, 160.3), Offset(209.3, 160.0), Offset(210.3, 160.0), Offset(211.0, 159.7), Offset(211.3, 159.3), Offset(212.3, 159.0), Offset(213.0, 158.7), Offset(213.7, 158.0), Offset(214.3, 158.0), Offset(215.0, 158.0), Offset(215.3, 157.7), Offset(216.3, 157.0), Offset(217.0, 156.7), Offset(218.0, 156.3), Offset(218.7, 156.0), Offset(220.0, 155.7), Offset(221.7, 155.0), Offset(223.3, 154.7), Offset(224.3, 154.0), Offset(225.3, 153.7), Offset(226.0, 153.3), Offset(227.0, 153.3), Offset(227.3, 153.0), Offset(228.3, 152.7), Offset(229.0, 152.3), Offset(229.3, 152.0), Offset(229.7, 152.0), Offset(230.7, 150.7), Offset(231.3, 150.3), Offset(231.7, 150.0), Offset(231.7, 149.7), Offset(232.0, 149.3), Offset(232.7, 149.0), Offset(233.0, 148.3), Offset(233.3, 148.0), Offset(233.3, 147.7), Offset(233.3, 147.3), Offset(234.0, 147.0), Offset(234.3, 146.0), Offset(234.7, 145.0), Offset(235.0, 145.0), Offset(235.0, 144.7), Offset(235.0, 144.3), Offset(235.3, 143.3), Offset(236.0, 143.0), Offset(236.0, 142.3), Offset(236.0, 142.0), Offset(236.0, 141.7), Offset(236.3, 140.3), Offset(236.7, 139.7), Offset(236.7, 139.3), Offset(236.7, 139.0), Offset(236.7, 138.7), Offset(237.0, 137.3), Offset(237.3, 136.0), Offset(237.3, 135.7), Offset(237.3, 135.3), Offset(237.3, 133.7), Offset(237.3, 132.7), Offset(237.3, 132.3), Offset(237.3, 132.0), Offset(237.3, 130.7), Offset(237.3, 129.3), Offset(237.3, 129.0), Offset(237.3, 128.3), Offset(237.3, 127.7), Offset(237.3, 126.7), Offset(237.3, 126.0), Offset(237.3, 125.7), Offset(237.3, 125.0), Offset(237.3, 124.0), Offset(237.3, 123.0), Offset(237.3, 122.7), Offset(236.7, 121.7), Offset(236.3, 120.7), Offset(235.7, 120.0), Offset(235.7, 119.7), Offset(235.3, 119.3), Offset(234.3, 118.3), Offset(233.3, 117.0), Offset(233.3, 116.3), Offset(233.0, 116.3), Offset(232.7, 116.3), Offset(232.3, 116.3), Offset(232.3, 116.0), Offset(231.7, 115.0), Offset(231.0, 114.7), Offset(230.3, 114.0), Offset(230.3, 113.7), Offset(230.0, 113.7), Offset(229.7, 113.3), Offset(229.0, 113.0), Offset(228.3, 112.3), Offset(228.0, 112.0), Offset(227.3, 111.7), Offset(226.7, 111.3), Offset(226.0, 111.3), Offset(225.3, 111.3), Offset(225.0, 111.0), Offset(224.7, 111.0), Offset(223.7, 110.7), Offset(223.3, 110.3), Offset(222.7, 110.3), Offset(222.0, 110.3), Offset(221.3, 109.7), Offset(220.7, 109.7), Offset(219.7, 109.7), Offset(218.3, 109.3), Offset(217.7, 108.7), Offset(216.7, 108.3), Offset(216.0, 108.0), Offset(215.7, 108.0), Offset(215.0, 107.7), Offset(214.3, 107.7), Offset(214.0, 107.7), Offset(213.3, 107.3), Offset(213.0, 107.0), Offset(212.3, 106.7), Offset(212.0, 106.7), Offset(211.0, 106.3), Offset(210.7, 106.3), Offset(210.0, 106.0), Offset(209.3, 105.7), Offset(208.7, 105.7), Offset(208.3, 105.7), Offset(207.7, 105.7), Offset(207.0, 105.7), Offset(206.0, 105.7), Offset(204.7, 105.3), Offset(204.3, 105.3), Offset(203.3, 105.3), Offset(202.3, 105.0), Offset(200.7, 105.0), Offset(199.7, 104.7), Offset(198.3, 104.7), Offset(196.3, 104.3), Offset(195.0, 104.0), Offset(194.0, 104.0), Offset(193.3, 103.3), Offset(192.7, 103.3), Offset(192.0, 103.0), Offset(191.3, 102.7), Offset(190.7, 102.7), Offset(190.3, 102.7), Offset(190.0, 102.3), Offset(189.3, 102.3), Offset(189.0, 102.3), Offset(188.3, 102.3), Offset(187.3, 102.0), Offset(186.7, 102.0), Offset(186.0, 102.0), Offset(185.7, 102.0), Offset(184.7, 101.7), Offset(184.0, 101.7), Offset(183.0, 101.7), Offset(182.0, 101.7), Offset(181.0, 101.7), Offset(180.0, 101.3), Offset(178.7, 101.3), Offset(177.7, 101.3), Offset(176.0, 101.3), Offset(174.3, 101.3), Offset(173.0, 101.3), Offset(171.7, 101.3), Offset(170.7, 101.3), Offset(169.7, 101.3), Offset(168.0, 101.3), Offset(167.3, 101.3), Offset(166.7, 101.3), Offset(165.3, 101.3), Offset(164.0, 101.3), Offset(163.0, 101.3), Offset(161.7, 101.3), Offset(161.0, 101.3), Offset(160.7, 101.3), Offset(160.3, 101.3), Offset(159.0, 101.3), Offset(157.7, 102.0), Offset(156.7, 102.3), Offset(156.0, 102.7), Offset(155.7, 102.7), Offset(155.3, 103.0), Offset(154.7, 103.3), Offset(153.3, 104.0), Offset(153.0, 104.7), Offset(152.0, 104.7), Offset(151.3, 105.3), Offset(151.0, 105.3), Offset(151.0, 105.7), Offset(150.3, 106.3), Offset(149.3, 106.7), Offset(147.7, 107.7), Offset(146.3, 109.0), Offset(145.7, 109.7), Offset(145.7, 110.0), Offset(145.0, 110.0), Offset(143.7, 111.0), Offset(142.7, 111.7), Offset(141.0, 113.0), Offset(140.3, 113.7), Offset(140.0, 114.3), Offset(139.7, 114.7), Offset(139.3, 115.0), Offset(138.0, 115.7), Offset(136.7, 116.7), Offset(135.7, 118.0), Offset(135.0, 118.7), Offset(135.0, 119.0), Offset(134.7, 119.3), Offset(134.3, 119.7), Offset(133.0, 120.3), Offset(131.0, 122.3), Offset(130.0, 123.3), Offset(129.3, 124.0), Offset(129.0, 125.0), Offset(128.7, 125.0), Offset(128.7, 125.3), Offset(127.7, 126.3), Offset(127.0, 126.7), Offset(125.7, 128.7), Offset(124.7, 129.3), Offset(124.3, 130.3), Offset(124.3, 130.7), Offset(124.3, 131.0), Offset(124.3, 131.3), Offset(124.0, 132.7), Offset(123.7, 133.7), Offset(123.0, 135.3), Offset(122.7, 136.0), Offset(122.7, 137.0), Offset(122.7, 137.3), Offset(122.7, 137.7), Offset(122.7, 138.3), Offset(122.7, 138.7), Offset(122.0, 141.3), Offset(121.3, 143.0), Offset(121.3, 144.0), Offset(121.0, 144.7), Offset(121.0, 145.0), Offset(120.7, 146.0), Offset(120.3, 147.3), Offset(119.3, 150.0), Offset(119.0, 151.7), Offset(118.7, 152.3), Offset(118.3, 152.7), Offset(118.3, 153.0), Offset(118.3, 154.7), Offset(118.3, 156.3), Offset(117.7, 159.0), Offset(117.7, 160.0), Offset(117.3, 161.0), Offset(117.3, 161.3), Offset(117.3, 163.3), Offset(117.3, 166.0), Offset(117.3, 167.3), Offset(117.3, 167.7), Offset(117.3, 168.7), Offset(117.3, 169.3), Offset(117.0, 170.0), Offset(116.7, 170.3), Offset(116.3, 170.3), Offset(116.3, 170.7), Offset(116.3, 171.3), Offset(115.7, 172.0), Offset(115.7, 172.7), Offset(115.7, 173.0), Offset(115.3, 173.3), Offset(114.7, 174.7), Offset(114.0, 176.0), Offset(114.0, 176.3), Offset(113.7, 177.0), Offset(113.7, 176.7), Offset(113.7, 176.3), Offset(113.7, 175.7), Offset(113.7, 175.3), Offset(113.0, 174.7), Offset(113.0, 174.0), Offset(113.0, 173.7), Offset(113.0, 173.0), Offset(113.0, 172.7), Offset(112.7, 172.7), Offset(112.3, 172.3), Offset(112.3, 172.0), Offset(112.0, 171.7), Offset(112.0, 171.3), Offset(112.0, 171.0), Offset(112.0, 170.7), Offset(111.7, 170.7), Offset(111.7, 170.3), Offset(111.7, 170.0), Offset(111.7, 169.7), Offset(111.7, 169.3), Offset(111.7, 169.0), Offset(111.7, 168.7), Offset(111.7, 168.3), Offset(111.3, 168.3), Offset(111.0, 168.0), Offset(111.0, 168.3), Offset(111.0, 168.7), Offset(111.0, 169.0), Offset(111.0, 169.7), Offset(111.0, 170.0), Offset(111.0, 170.7), Offset(111.0, 171.0), Offset(111.0, 172.0), Offset(111.0, 172.3), Offset(111.0, 173.3), Offset(111.0, 173.7), Offset(111.0, 174.7), Offset(111.0, 175.0), Offset(111.0, 175.3), Offset(111.0, 176.0), Offset(111.0, 176.3), Offset(111.0, 177.0), Offset(111.0, 177.3), Offset(111.0, 177.7), Offset(111.0, 178.0), Offset(111.0, 178.3), Offset(111.0, 178.7), Offset(111.0, 179.0), Offset(111.0, 179.7), Offset(111.0, 180.0), Offset(111.0, 180.3), Offset(111.0, 181.0), Offset(110.7, 181.3), Offset(110.7, 181.7), Offset(110.7, 182.0), Offset(110.7, 182.3), Offset(110.3, 183.0), Offset(110.3, 183.7), Offset(110.3, 184.3), Offset(110.0, 184.7), Offset(110.0, 185.3), Offset(110.0, 186.0), Offset(109.7, 186.7), Offset(109.3, 187.3), Offset(109.3, 188.0), Offset(109.0, 189.0), Offset(109.0, 189.3), Offset(109.0, 190.0), Offset(108.7, 190.3), Offset(108.7, 190.7), Offset(108.7, 191.3), Offset(108.7, 191.7), Offset(108.7, 192.7), Offset(108.7, 193.3), Offset(108.7, 194.0), Offset(108.7, 195.0), Offset(108.7, 195.7), Offset(108.7, 196.7), Offset(108.7, 198.0), Offset(108.7, 198.3), Offset(108.7, 199.0), Offset(108.7, 200.7), Offset(108.7, 201.7), Offset(108.7, 202.7), Offset(108.7, 204.3), Offset(108.7, 205.7), Offset(108.7, 206.7), Offset(108.7, 207.3), Offset(108.7, 208.3), Offset(108.7, 209.7), Offset(108.7, 210.0), Offset(108.7, 210.3), Offset(108.7, 211.3), Offset(109.0, 212.0), Offset(109.0, 212.7), Offset(109.3, 213.3), Offset(109.3, 214.3), Offset(109.7, 215.0), Offset(110.0, 216.0), Offset(110.3, 217.3), Offset(110.7, 218.3), Offset(110.7, 219.0), Offset(111.0, 220.0), Offset(111.0, 221.0), Offset(111.3, 222.0), Offset(111.3, 223.0), Offset(111.7, 223.7), Offset(111.7, 224.3), Offset(112.0, 225.0), Offset(112.0, 225.3), Offset(112.0, 226.3), Offset(112.0, 226.7), Offset(112.3, 227.3), Offset(112.7, 228.3), Offset(112.7, 228.7), Offset(112.7, 229.3), Offset(112.7, 230.3), Offset(113.0, 231.3), Offset(113.0, 232.7), Offset(113.3, 233.3), Offset(113.7, 235.0), Offset(114.0, 236.0), Offset(114.3, 237.3), Offset(114.7, 238.3), Offset(115.0, 239.0), Offset(115.0, 240.0), Offset(115.0, 240.3), Offset(115.3, 241.0), Offset(115.7, 241.3), Offset(116.0, 242.0), Offset(116.7, 242.7), Offset(116.7, 243.3), Offset(116.7, 243.7), Offset(117.3, 244.7), Offset(117.7, 245.0), Offset(118.3, 245.7), Offset(118.3, 246.3), Offset(118.7, 246.7), Offset(119.3, 247.7), Offset(119.7, 248.3), Offset(120.0, 249.0), Offset(120.3, 250.0), Offset(120.7, 250.3), Offset(121.3, 251.3), Offset(121.3, 251.7), Offset(121.7, 252.3), Offset(122.0, 253.0), Offset(122.3, 253.3), Offset(122.7, 254.3), Offset(123.0, 254.7), Offset(123.3, 255.0), Offset(123.7, 255.7), Offset(124.0, 256.3), Offset(124.3, 256.7), Offset(124.3, 257.0), Offset(124.7, 257.7), Offset(125.3, 258.0), Offset(125.7, 258.7), Offset(126.3, 259.3), Offset(127.0, 260.3), Offset(127.7, 261.0), Offset(128.0, 262.0), Offset(129.0, 263.0), Offset(129.7, 264.0), Offset(130.7, 265.0), Offset(131.0, 265.3), Offset(132.0, 266.3), Offset(132.3, 267.0), Offset(132.7, 267.3), Offset(133.0, 267.7), Offset(133.3, 267.7), Offset(133.7, 268.0), Offset(133.7, 268.3), Offset(134.0, 268.7), Offset(134.3, 269.0), Offset(134.7, 269.7), Offset(135.3, 270.3), Offset(136.0, 271.0), Offset(136.3, 271.7), Offset(137.3, 272.3), Offset(137.7, 272.7), Offset(138.3, 273.3), Offset(139.3, 274.3), Offset(140.3, 275.0), Offset(141.0, 276.0), Offset(142.0, 276.7), Offset(143.0, 277.7), Offset(143.7, 278.3), Offset(144.7, 279.0), Offset(145.3, 279.7), Offset(145.7, 279.7), Offset(146.3, 280.7), Offset(146.7, 281.0), Offset(147.3, 281.3), Offset(148.0, 282.0), Offset(148.3, 282.7), Offset(148.7, 282.7), Offset(149.3, 283.0), Offset(149.3, 283.7), Offset(150.3, 284.0), Offset(151.0, 284.7), Offset(151.7, 285.3), Offset(152.7, 285.7), Offset(153.0, 286.3), Offset(153.7, 286.7), Offset(154.3, 287.3), Offset(155.0, 287.7), Offset(155.3, 288.0), Offset(155.7, 288.3), Offset(156.3, 288.7), Offset(156.7, 289.0), Offset(157.0, 289.7), Offset(157.7, 290.0), Offset(158.0, 290.3), Offset(158.7, 291.0), Offset(159.3, 291.3), Offset(160.0, 291.7), Offset(160.3, 292.3), Offset(161.0, 292.7), Offset(161.7, 293.3), Offset(162.0, 293.7), Offset(163.0, 294.3), Offset(163.7, 295.3), Offset(164.7, 295.7), Offset(165.3, 296.3), Offset(166.0, 297.0), Offset(166.7, 297.0), Offset(167.3, 297.7), Offset(168.0, 298.0), Offset(168.3, 298.0), Offset(168.7, 298.3), Offset(169.3, 298.3), Offset(169.7, 299.0), Offset(170.0, 299.0), Offset(170.7, 299.3), Offset(171.0, 299.7), Offset(171.7, 300.0), Offset(172.3, 300.0), Offset(173.0, 300.0), Offset(174.0, 300.3), Offset(174.7, 300.7), Offset(175.3, 301.0), Offset(176.0, 301.0), Offset(176.7, 301.3), Offset(177.7, 301.7), Offset(178.3, 301.7), Offset(179.0, 301.7), Offset(179.3, 301.7), Offset(180.0, 301.7), Offset(181.0, 302.0), Offset(181.3, 302.0), Offset(182.0, 302.0), Offset(182.7, 302.0), Offset(183.0, 302.0), Offset(183.3, 302.0), Offset(183.7, 302.0), Offset(184.3, 302.0), Offset(184.7, 302.0), Offset(185.3, 302.0), Offset(186.0, 302.0), Offset(186.0, 301.7), Offset(186.3, 301.7), Offset(187.0, 301.0), Offset(187.3, 300.3), Offset(187.7, 300.3), Offset(188.3, 299.7), Offset(188.7, 299.3), Offset(189.0, 299.0), Offset(189.3, 298.3), Offset(190.3, 298.0), Offset(190.7, 297.3), Offset(191.0, 297.0), Offset(191.3, 296.7), Offset(192.0, 296.3), Offset(192.3, 296.0), Offset(193.0, 295.3), Offset(193.7, 294.7), Offset(194.0, 294.3), Offset(194.3, 294.0), Offset(194.7, 293.7), Offset(195.0, 293.0), Offset(195.7, 293.0), Offset(196.3, 292.7), Offset(196.7, 292.0), Offset(197.7, 291.3), Offset(198.3, 291.0), Offset(199.3, 290.3), Offset(200.0, 290.0), Offset(200.7, 289.7), Offset(201.7, 289.3), Offset(202.0, 289.0), Offset(203.3, 288.3), Offset(204.0, 288.0), Offset(204.3, 287.3), Offset(205.0, 287.0), Offset(205.7, 287.0), Offset(206.0, 286.3), Offset(206.7, 285.7), Offset(207.3, 285.3), Offset(208.0, 284.7), Offset(208.7, 284.0), Offset(209.3, 283.7), Offset(209.3, 283.0), Offset(210.0, 282.3), Offset(210.7, 282.0), Offset(211.0, 281.0), Offset(211.7, 280.3), Offset(212.3, 279.7), Offset(212.7, 279.3), Offset(213.3, 278.3), Offset(213.7, 278.3), Offset(214.0, 277.7), Offset(214.3, 277.3), Offset(214.7, 277.0), Offset(215.0, 276.3), Offset(215.3, 276.3), Offset(216.0, 275.7), Offset(216.3, 275.0), Offset(217.0, 274.7), Offset(217.3, 274.3), Offset(217.7, 273.7), Offset(218.0, 273.3), Offset(218.3, 273.0), Offset(218.7, 272.7), Offset(218.7, 272.3), Offset(219.3, 271.7), Offset(220.0, 271.3), Offset(220.3, 270.3), Offset(221.0, 270.0), Offset(221.7, 269.3), Offset(222.3, 268.3), Offset(222.7, 268.0), Offset(223.0, 267.3), Offset(223.3, 267.0), Offset(224.0, 266.0), Offset(224.3, 265.7), Offset(225.0, 264.7), Offset(225.3, 264.0), Offset(225.7, 263.3), Offset(226.0, 263.0), Offset(226.3, 262.3), Offset(226.7, 262.0), Offset(227.0, 261.3), Offset(227.3, 260.7), Offset(228.0, 260.0), Offset(228.3, 259.3), Offset(228.7, 258.3), Offset(229.3, 257.3), Offset(229.7, 256.7), Offset(230.3, 255.3), Offset(230.7, 254.7), Offset(230.7, 254.3), Offset(231.3, 254.0), Offset(231.3, 253.0), Offset(232.0, 252.0), Offset(232.3, 251.0), Offset(232.7, 250.7), Offset(233.0, 249.3), Offset(233.3, 248.7), Offset(233.3, 248.0), Offset(233.7, 247.3), Offset(234.0, 246.7), Offset(234.7, 246.0), Offset(234.7, 244.7), Offset(235.0, 243.7), Offset(235.3, 242.7), Offset(235.7, 241.7), Offset(236.0, 241.3), Offset(236.7, 240.0), Offset(236.7, 239.3), Offset(237.3, 237.7), Offset(238.0, 237.0), Offset(238.3, 235.7), Offset(239.0, 235.0), Offset(239.7, 234.0), Offset(240.0, 232.7), Offset(240.3, 231.3), Offset(241.0, 230.7), Offset(241.3, 229.7), Offset(242.0, 228.3), Offset(242.3, 227.7), Offset(243.0, 226.7), Offset(243.0, 226.0), Offset(243.3, 225.7), Offset(243.3, 225.0), Offset(243.7, 224.7), Offset(243.7, 224.3), Offset(244.0, 223.3), Offset(244.7, 222.3), Offset(245.3, 221.0), Offset(245.7, 220.3), Offset(245.7, 219.7), Offset(245.7, 219.3), Offset(245.7, 219.0), Offset(245.7, 218.7), Offset(245.7, 217.3), Offset(245.7, 215.3), Offset(246.0, 214.3), Offset(246.0, 213.0), Offset(246.0, 212.7), Offset(246.0, 212.0), Offset(246.0, 211.0), Offset(246.0, 210.3), Offset(246.0, 209.7), Offset(246.0, 209.3), Offset(246.0, 208.3), Offset(246.0, 206.3), Offset(246.0, 203.7), Offset(246.0, 202.3), Offset(246.0, 201.3), Offset(246.0, 201.0), Offset(246.0, 200.7), Offset(246.0, 199.3), Offset(246.0, 198.3), Offset(246.0, 197.0), Offset(246.0, 196.0), Offset(246.0, 195.0), Offset(246.0, 194.0), Offset(246.0, 193.0), Offset(246.0, 191.7), Offset(246.0, 190.7), Offset(245.7, 189.3), Offset(245.7, 188.3), Offset(245.7, 187.0), Offset(245.7, 186.0), Offset(245.7, 185.0), Offset(245.3, 184.3), Offset(245.3, 183.7), Offset(245.0, 182.0), Offset(244.7, 181.0), Offset(244.7, 179.3), Offset(244.3, 178.7), Offset(244.0, 177.3), Offset(243.7, 176.3), Offset(243.3, 174.7), Offset(243.3, 173.3), Offset(242.7, 172.0), Offset(242.3, 171.3), Offset(242.3, 170.7), Offset(242.0, 169.7), Offset(242.0, 168.3), Offset(241.7, 167.0), Offset(241.0, 165.3), Offset(241.0, 164.3), Offset(240.3, 163.7), Offset(240.0, 163.0), Offset(239.7, 162.3), Offset(239.7, 161.7), Offset(239.3, 160.7), Offset(239.3, 160.3), Offset(239.3, 159.0), Offset(239.0, 158.0), Offset(238.7, 157.3), Offset(238.7, 156.7), Offset(238.7, 156.0), Offset(238.3, 154.7), Offset(238.3, 153.7), Offset(238.0, 152.0), Offset(238.0, 150.7), Offset(237.7, 150.7), Offset(237.7, 150.0), Offset(237.7, 149.7), Offset(237.3, 149.0), Offset(236.7, 147.0), Offset(236.0, 145.7), Offset(236.0, 145.0), Offset(235.7, 144.7), Offset(235.0, 144.7), Offset(234.7, 144.7), Offset(234.3, 144.7), Offset(234.3, 145.0), Offset(234.3, 145.3), Offset(234.3, 145.7), Offset(234.3, 146.3), Offset(234.3, 147.0), Offset(234.3, 147.7), Offset(234.3, 148.0), Offset(234.3, 148.3), Offset(234.3, 148.7), Offset(234.3, 149.0), Offset(234.3, 149.3), Offset(234.3, 149.7), Offset(234.3, 150.0), Offset(234.3, 150.3), Offset(234.3, 150.7), Offset(234.3, 151.0), Offset(234.3, 151.3), Offset(234.3, 151.7), Offset(234.3, 152.0), Offset(234.3, 152.7), Offset(234.3, 153.0), Offset(234.0, 153.3), Offset(234.0, 154.0), Offset(234.0, 154.7), Offset(233.7, 155.0), Offset(233.7, 155.3), Offset(233.3, 155.7), Offset(233.3, 156.3), Offset(233.0, 156.7), Offset(232.7, 157.3), Offset(232.7, 157.7), Offset(232.3, 158.0), Offset(232.3, 158.3), Offset(232.3, 159.0), Offset(232.0, 159.3), Offset(231.7, 160.0), Offset(231.3, 160.3), Offset(231.3, 160.7), Offset(231.0, 161.0), Offset(230.7, 161.7), Offset(230.7, 162.0), Offset(230.3, 162.7), Offset(230.3, 163.0), Offset(230.0, 163.7), Offset(229.7, 164.7), Offset(229.3, 165.0), Offset(229.0, 165.7), Offset(228.7, 166.7), Offset(228.3, 166.7), Offset(228.3, 167.7), Offset(228.0, 168.3), Offset(227.3, 169.3), Offset(227.0, 170.0), Offset(226.7, 170.3), Offset(226.7, 171.0), Offset(226.3, 171.7), Offset(226.0, 171.7), Offset(225.7, 172.3), Offset(225.3, 173.0), Offset(224.7, 173.7), Offset(224.7, 174.3), Offset(224.3, 175.0), Offset(223.7, 175.7), Offset(223.3, 176.7), Offset(223.0, 177.0), Offset(222.7, 177.7), Offset(222.3, 178.3), Offset(222.0, 178.7), Offset(221.7, 179.0), Offset(221.3, 179.7), Offset(221.3, 180.0), Offset(221.0, 180.3), Offset(220.7, 181.0), Offset(220.3, 181.3), Offset(220.0, 181.7), Offset(219.7, 182.0), Offset(219.3, 182.3), Offset(219.3, 182.7), Offset(219.0, 183.0), Offset(218.7, 183.3), Offset(218.3, 184.0), Offset(218.0, 184.3), Offset(217.3, 185.0), Offset(217.0, 185.3), Offset(217.0, 186.0), Offset(216.3, 186.7), Offset(215.7, 187.3), Offset(215.3, 188.0), Offset(214.7, 188.3), Offset(214.3, 189.0), Offset(214.0, 189.7), Offset(213.7, 190.0), Offset(213.0, 191.0), Offset(212.3, 191.7), Offset(211.7, 192.0), Offset(211.3, 192.7), Offset(210.3, 194.0), Offset(209.7, 195.0), Offset(209.0, 196.0), Offset(208.3, 196.7), Offset(207.3, 197.3), Offset(206.7, 198.3), Offset(206.0, 198.7), Offset(205.0, 199.7), Offset(204.0, 200.3), Offset(203.0, 201.0), Offset(202.3, 201.0), Offset(201.7, 201.3), Offset(201.0, 201.7), Offset(200.7, 202.3), Offset(199.7, 202.7), Offset(199.3, 202.7), Offset(198.3, 203.0), Offset(197.7, 203.3), Offset(197.3, 203.7), Offset(196.3, 204.0), Offset(196.0, 204.3), Offset(195.7, 204.3), Offset(195.0, 204.3), Offset(194.0, 204.7), Offset(193.3, 204.7), Offset(193.0, 205.0), Offset(192.7, 205.0), Offset(192.3, 205.3), Offset(192.0, 205.3), Offset(191.3, 205.7), Offset(191.0, 206.0), Offset(190.7, 206.0), Offset(190.3, 206.3), Offset(190.0, 206.7), Offset(189.3, 207.3), Offset(189.0, 207.3), Offset(188.3, 208.0), Offset(187.7, 208.7), Offset(187.3, 209.0), Offset(186.3, 209.3), Offset(185.7, 210.0), Offset(185.0, 210.7), Offset(184.0, 211.0), Offset(183.0, 211.7), Offset(182.7, 212.3), Offset(181.7, 212.7), Offset(181.0, 213.3), Offset(180.3, 213.7), Offset(179.7, 214.0), Offset(179.3, 214.7), Offset(178.7, 215.0), Offset(178.0, 215.3), Offset(177.3, 216.0), Offset(177.0, 216.3), Offset(176.0, 217.0), Offset(176.0, 217.3), Offset(175.3, 217.3), Offset(174.7, 217.7), Offset(174.7, 218.0), Offset(174.0, 218.3), Offset(173.3, 218.7), Offset(173.0, 219.0), Offset(173.0, 219.7), Offset(172.0, 220.3), Offset(171.3, 220.7), Offset(171.0, 221.3), Offset(170.3, 222.0), Offset(169.7, 222.3), Offset(169.3, 222.7), Offset(169.3, 223.0), Offset(169.0, 223.3), Offset(168.7, 223.7), Offset(168.0, 224.3), Offset(167.7, 224.7), Offset(167.7, 225.0), Offset(167.3, 225.0), Offset(166.7, 225.7), Offset(166.3, 226.3), Offset(166.0, 226.7), Offset(165.7, 227.3), Offset(165.0, 227.7), Offset(165.0, 228.0), Offset(164.7, 228.0), Offset(164.7, 228.7), Offset(164.3, 229.0), Offset(164.0, 229.3), Offset(164.0, 229.7), Offset(164.0, 230.0), Offset(163.7, 230.3), Offset(163.3, 231.0), Offset(163.3, 231.3), Offset(163.0, 231.7), Offset(162.7, 232.3), Offset(162.7, 232.7), Offset(162.3, 233.3), Offset(162.0, 234.0), Offset(161.7, 234.7), Offset(161.3, 235.3), Offset(160.7, 236.0), Offset(160.7, 237.0), Offset(160.3, 238.0), Offset(160.0, 238.3), Offset(159.7, 239.7), Offset(159.3, 240.3), Offset(159.0, 241.0), Offset(158.7, 242.0), Offset(158.7, 243.0), Offset(158.7, 243.7), Offset(158.3, 244.7), Offset(158.3, 245.3), Offset(158.3, 246.3), Offset(158.3, 247.3), Offset(158.3, 247.7), Offset(158.3, 248.7), Offset(158.3, 249.7), Offset(158.3, 250.3), Offset(158.3, 250.7), Offset(158.3, 251.3), Offset(158.3, 251.7), Offset(158.3, 252.3), Offset(158.3, 252.7), Offset(158.3, 253.3), Offset(158.3, 254.0), Offset(158.3, 254.3), Offset(158.3, 255.0), Offset(158.3, 255.3), Offset(158.7, 256.3), Offset(158.7, 257.0), Offset(158.7, 257.7), Offset(158.7, 258.3), Offset(158.7, 258.7), Offset(158.7, 259.3), Offset(159.0, 259.7), Offset(159.3, 260.7), Offset(159.3, 261.0), Offset(159.3, 261.3), Offset(159.7, 262.0), Offset(160.0, 262.3), Offset(160.0, 263.0), Offset(160.0, 263.7), Offset(160.0, 264.0), Offset(160.0, 264.7), Offset(160.3, 265.7), Offset(160.3, 266.3), Offset(160.7, 266.7), Offset(160.7, 267.7), Offset(161.0, 268.3), Offset(161.0, 269.0), Offset(161.3, 269.7), Offset(161.7, 270.3), Offset(161.7, 271.0), Offset(161.7, 271.7), Offset(161.7, 272.3), Offset(161.7, 272.7), Offset(161.7, 273.0), Offset(161.7, 274.0), Offset(162.0, 274.0), Offset(162.0, 275.0), Offset(162.3, 275.7), Offset(162.3, 276.0), Offset(162.7, 276.7), Offset(162.7, 277.0), Offset(163.0, 277.0), Offset(163.0, 277.7), Offset(163.3, 278.3), Offset(163.3, 278.7), Offset(163.3, 279.3), Offset(163.3, 280.0), Offset(163.7, 280.3), Offset(164.0, 280.7), Offset(164.0, 281.7), Offset(164.7, 282.0), Offset(165.0, 282.3), Offset(165.0, 283.0), Offset(165.3, 283.7), Offset(166.0, 284.7), Offset(166.3, 285.0), Offset(166.7, 285.3), Offset(167.0, 286.3), Offset(167.3, 286.7), Offset(168.0, 287.3), Offset(168.3, 288.0), Offset(168.7, 288.7), Offset(169.0, 289.0), Offset(169.7, 289.7), Offset(170.0, 289.7), Offset(170.0, 290.3), Offset(170.3, 290.3), Offset(170.7, 290.3), Offset(171.0, 291.0), Offset(171.0, 291.3), Offset(171.3, 291.7), Offset(171.7, 292.0), Offset(172.0, 292.0), Offset(172.0, 292.3), Offset(172.3, 292.3), Offset(172.7, 292.7), Offset(173.0, 293.0), Offset(173.0, 293.3), Offset(173.3, 294.0), Offset(173.7, 294.0), Offset(173.7, 294.3), Offset(174.0, 294.7), Offset(174.3, 294.7), Offset(174.7, 295.0), Offset(175.0, 295.3), Offset(175.3, 295.3), Offset(175.3, 295.7), Offset(175.7, 296.0), Offset(176.0, 296.0), Offset(176.3, 296.3), Offset(176.3, 296.7), Offset(176.7, 297.0), Offset(177.0, 297.7), Offset(177.3, 297.7), Offset(178.0, 298.3), Offset(178.3, 299.0), Offset(178.7, 299.0), Offset(179.0, 299.3), Offset(179.0, 299.7), Offset(179.3, 300.0), Offset(179.7, 300.3), Offset(180.0, 300.0), Offset(180.0, 299.7), Offset(180.0, 299.3), Offset(180.0, 299.0), Offset(180.0, 298.7), Offset(180.0, 298.0), Offset(180.3, 297.7), Offset(180.3, 297.0), Offset(180.3, 296.3), Offset(180.7, 295.7), Offset(180.7, 294.7), Offset(181.0, 294.0), Offset(181.0, 293.7), Offset(181.7, 292.7), Offset(182.0, 292.0), Offset(182.3, 291.3), Offset(182.3, 290.7), Offset(182.3, 290.3), Offset(183.0, 289.3), Offset(183.3, 288.7), Offset(183.7, 287.7), Offset(184.0, 287.0), Offset(184.0, 286.7), Offset(184.0, 285.7), Offset(184.3, 285.0), Offset(184.7, 284.7), Offset(184.7, 284.3), Offset(185.0, 284.0), Offset(185.0, 283.3), Offset(185.3, 282.3), Offset(185.3, 282.0), Offset(185.7, 281.0), Offset(185.7, 280.3), Offset(185.7, 280.0), Offset(186.0, 279.0), Offset(186.3, 278.3), Offset(186.3, 278.0), Offset(186.7, 277.7), Offset(186.7, 277.0), Offset(187.0, 276.7), Offset(187.0, 276.0), Offset(187.0, 275.3), Offset(187.0, 274.7), Offset(187.0, 274.0), Offset(187.0, 273.3), Offset(187.3, 273.0), Offset(187.3, 272.3), Offset(187.3, 271.7), Offset(187.3, 271.0), Offset(187.3, 270.7), Offset(187.7, 270.0), Offset(187.7, 269.7), Offset(187.7, 268.3), Offset(187.7, 267.7), Offset(187.7, 266.3), Offset(187.7, 266.0), Offset(187.7, 265.0), Offset(187.7, 264.3), Offset(187.7, 263.7), Offset(187.7, 263.0), Offset(187.7, 262.7), Offset(187.7, 262.0), Offset(187.7, 261.0), Offset(187.7, 259.7), Offset(187.7, 259.0), Offset(187.7, 258.3), Offset(187.7, 257.7), Offset(187.7, 257.3), Offset(187.7, 256.7), Offset(187.7, 256.0), Offset(187.7, 255.7), Offset(187.7, 255.3), Offset(187.7, 254.7), Offset(187.7, 254.0), Offset(187.7, 253.7), Offset(187.7, 253.0), Offset(187.3, 252.7), Offset(187.0, 252.0), Offset(187.0, 251.3), Offset(187.0, 251.0), Offset(186.7, 250.7), Offset(186.7, 250.3), Offset(186.7, 250.0), Offset(186.3, 249.3), Offset(186.0, 248.7), Offset(185.7, 248.3), Offset(185.7, 247.7), Offset(185.3, 247.0), Offset(184.7, 246.3), Offset(184.3, 245.3), Offset(184.0, 244.7), Offset(184.0, 244.3), Offset(183.7, 244.0), Offset(183.3, 243.7), Offset(183.0, 243.3), Offset(182.3, 242.7), Offset(182.3, 242.0), Offset(182.0, 241.3), Offset(181.7, 241.3), Offset(181.3, 241.0), Offset(181.0, 240.0), Offset(180.7, 239.7), Offset(180.3, 239.0), Offset(180.0, 238.3), Offset(179.3, 237.7), Offset(178.3, 236.3), Offset(178.3, 235.3), Offset(177.7, 234.7), Offset(177.0, 234.0), Offset(176.7, 233.3), Offset(176.3, 233.0), Offset(176.0, 232.3), Offset(175.3, 231.3), Offset(175.0, 231.0), Offset(175.0, 230.3), Offset(174.7, 230.0), Offset(174.3, 229.7), Offset(174.0, 229.3), Offset(173.3, 228.3), Offset(173.0, 228.0), Offset(172.0, 227.0), Offset(171.7, 226.3), Offset(171.3, 226.3), Offset(170.3, 225.3), Offset(169.7, 224.3), Offset(169.3, 224.0), Offset(168.7, 223.7), Offset(168.3, 223.3), Offset(168.0, 222.7), Offset(167.7, 222.7), Offset(167.3, 222.3), Offset(166.7, 222.0), Offset(166.3, 221.7), Offset(165.7, 221.3), Offset(165.0, 221.0), Offset(164.3, 220.7), Offset(164.0, 220.0), Offset(163.3, 220.0), Offset(163.0, 219.7), Offset(162.3, 219.3), Offset(161.3, 219.0), Offset(160.7, 218.3), Offset(159.7, 218.0), Offset(159.0, 217.7), Offset(158.7, 217.7), Offset(157.7, 217.3), Offset(157.0, 217.0), Offset(156.3, 216.7), Offset(156.0, 216.3), Offset(155.3, 216.3), Offset(154.7, 216.0), Offset(154.3, 215.7), Offset(153.3, 215.0), Offset(152.7, 214.7), Offset(152.3, 214.7), Offset(151.7, 214.3), Offset(151.3, 213.7), Offset(150.7, 213.0), Offset(150.0, 212.7), Offset(149.0, 212.0), Offset(149.0, 211.7), Offset(148.3, 211.3), Offset(147.7, 211.0), Offset(147.0, 210.7), Offset(146.7, 210.3), Offset(145.7, 210.0), Offset(145.3, 209.3), Offset(144.7, 209.3), Offset(144.0, 209.0), Offset(143.3, 208.3), Offset(143.0, 208.0), Offset(142.7, 207.7), Offset(142.0, 207.7), Offset(141.7, 207.3), Offset(140.7, 206.7), Offset(140.0, 206.3), Offset(139.7, 206.0), Offset(139.0, 205.7), Offset(138.3, 205.3), Offset(137.7, 205.3), Offset(137.3, 205.0), Offset(136.7, 204.7), Offset(136.0, 204.3), Offset(135.3, 204.0), Offset(134.7, 203.7), Offset(134.0, 203.3), Offset(133.3, 203.0), Offset(132.7, 202.3), Offset(131.7, 202.3), Offset(131.3, 202.0), Offset(130.3, 201.7), Offset(129.7, 201.0), Offset(128.7, 200.7), Offset(128.0, 200.0), Offset(127.7, 200.0), Offset(127.0, 199.7), Offset(126.3, 198.7), Offset(125.7, 198.3), Offset(125.3, 197.7), Offset(125.0, 197.3), Offset(124.3, 196.7), Offset(124.0, 196.3), Offset(123.7, 196.3), Offset(123.3, 195.7), Offset(123.3, 195.3), Offset(123.0, 195.3), Offset(123.0, 195.0), Offset(122.7, 194.7), Offset(122.7, 193.7), Offset(122.0, 192.7), Offset(121.3, 191.7), Offset(120.7, 190.7), Offset(120.3, 190.0), Offset(120.0, 189.7), Offset(119.7, 189.0), Offset(119.3, 188.7), Offset(119.0, 188.0), Offset(118.7, 187.7), Offset(118.3, 187.0), Offset(117.7, 186.7), Offset(117.3, 186.0), Offset(117.3, 185.7), Offset(117.0, 185.3), Offset(116.7, 185.3), Offset(116.7, 185.0), Offset(116.0, 184.3), Offset(115.3, 183.3), Offset(115.3, 182.7), Offset(115.0, 182.0), Offset(115.0, 181.7), Offset(115.0, 181.7), Offset(115.0, 181.7), Offset(179.3, 301.7), Offset(237.7, 144.7), ]; static final List<Offset> branchPoints = [ Offset(179.3, 300.3), Offset(182.0, 338.3), Offset(182.0, 339.0), Offset(182.0, 339.7), Offset(182.7, 347.3), Offset(183.3, 348.3), Offset(183.3, 349.0), Offset(183.3, 349.7), Offset(183.3, 350.3), Offset(183.7, 351.0), Offset(183.7, 351.7), Offset(183.7, 352.3), Offset(183.7, 353.0), Offset(183.7, 353.3), Offset(184.0, 354.0), Offset(184.0, 354.3), Offset(184.0, 355.0), Offset(184.0, 355.7), Offset(184.0, 356.0), Offset(184.0, 356.7), Offset(184.0, 357.3), Offset(184.0, 358.0), Offset(184.3, 358.7), Offset(184.3, 359.3), Offset(184.3, 360.0), Offset(184.7, 360.7), Offset(184.7, 361.3), Offset(184.7, 362.0), Offset(185.0, 362.7), Offset(185.0, 363.3), Offset(185.7, 364.3), Offset(185.7, 365.3), Offset(186.0, 366.0), Offset(186.0, 366.7), Offset(186.3, 367.7), Offset(186.3, 368.3), Offset(186.7, 369.0), Offset(186.7, 370.3), Offset(187.0, 371.0), Offset(187.3, 372.0), Offset(187.7, 373.3), Offset(187.7, 374.3), Offset(188.0, 375.7), Offset(188.7, 377.3), Offset(189.3, 380.3), Offset(190.3, 381.7), Offset(190.7, 383.3), Offset(191.0, 385.0), Offset(192.0, 386.3), Offset(192.3, 388.0), Offset(192.7, 389.3), Offset(193.3, 390.3), Offset(194.0, 391.7), Offset(194.3, 393.3), Offset(194.7, 394.7), Offset(195.3, 395.7), Offset(196.0, 397.3), Offset(196.3, 399.3), Offset(197.0, 400.3), Offset(197.7, 402.3), Offset(198.7, 404.0), Offset(199.0, 405.7), Offset(199.3, 407.0), Offset(199.7, 408.7), Offset(200.3, 410.0), Offset(200.7, 411.0), Offset(201.0, 412.3), Offset(201.3, 413.3), Offset(201.7, 414.7), Offset(202.0, 416.0), Offset(202.7, 417.0), Offset(203.0, 418.3), Offset(203.3, 419.3), Offset(203.7, 420.7), Offset(204.0, 422.3), Offset(204.7, 423.3), Offset(205.0, 424.7), Offset(205.0, 426.3), Offset(205.3, 427.7), Offset(205.3, 428.7), Offset(205.7, 430.0), Offset(205.7, 431.0), Offset(206.0, 433.0), Offset(206.0, 434.0), Offset(206.0, 436.0), Offset(206.7, 437.0), Offset(206.7, 438.3), Offset(207.0, 439.0), Offset(207.0, 440.0), Offset(207.0, 441.3), Offset(207.3, 442.0), Offset(207.3, 442.7), Offset(207.3, 443.7), Offset(207.3, 444.0), Offset(207.7, 444.7), Offset(207.7, 445.3), Offset(207.7, 445.7), Offset(208.0, 446.3), Offset(208.0, 447.0), Offset(208.0, 447.7), Offset(208.0, 448.0), Offset(208.0, 448.7), Offset(208.3, 449.3), Offset(209.0, 450.7), Offset(209.3, 452.0), Offset(209.7, 453.7), Offset(210.0, 454.3), Offset(210.3, 455.0), Offset(210.7, 456.3), Offset(210.7, 457.0), Offset(211.0, 458.0), Offset(211.3, 458.7), Offset(212.0, 460.7), Offset(212.7, 462.3), Offset(213.0, 463.0), Offset(213.7, 463.7), Offset(214.3, 465.3), Offset(215.7, 466.7), Offset(216.0, 467.3), Offset(217.3, 468.3), Offset(218.3, 469.0), Offset(220.0, 470.3), Offset(223.0, 472.3), Offset(226.0, 474.3), Offset(228.3, 475.3), Offset(230.7, 477.0), Offset(231.3, 477.7), Offset(233.7, 478.7), Offset(235.0, 479.7), Offset(237.3, 481.0), Offset(239.3, 482.3), Offset(240.3, 483.0), Offset(241.7, 483.7), Offset(244.0, 485.7), Offset(246.3, 486.7), Offset(247.0, 487.3), Offset(249.0, 488.0), Offset(251.3, 489.7), Offset(252.0, 490.0), Offset(252.7, 490.3), Offset(254.0, 491.0), Offset(255.7, 491.7), Offset(257.3, 492.3), Offset(258.0, 492.7), Offset(259.0, 493.3), Offset(260.3, 494.0), Offset(261.3, 494.7), Offset(262.3, 495.3), Offset(263.7, 496.0), Offset(265.0, 496.7), Offset(265.7, 497.3), Offset(266.3, 497.7), Offset(268.0, 499.0), Offset(270.0, 500.7), Offset(272.0, 502.3), Offset(275.3, 505.0), Offset(277.3, 507.0), Offset(280.3, 509.3), Offset(282.0, 511.0), Offset(283.0, 511.7), Offset(283.3, 512.0), Offset(283.7, 512.0), Offset(283.0, 512.0), Offset(283.0, 512.0), ]; static final List<Offset> leafBranchPoints1 = [ Offset(183.0, 327.3), Offset(250.3, 319.3), ]; static final List<Offset> leafPoints1 = [ Offset(203.3, 324.0), Offset(205.0, 323.3), Offset(205.0, 323.0), Offset(205.0, 322.7), Offset(205.3, 322.3), Offset(205.7, 322.3), Offset(206.0, 322.0), Offset(206.3, 322.0), Offset(206.7, 321.7), Offset(207.0, 321.3), Offset(207.0, 321.0), Offset(207.0, 320.7), Offset(207.7, 320.7), Offset(208.7, 319.3), Offset(210.0, 317.3), Offset(210.7, 316.7), Offset(211.7, 315.3), Offset(212.7, 314.3), Offset(213.3, 313.3), Offset(214.0, 313.0), Offset(214.3, 313.0), Offset(214.7, 313.0), Offset(215.0, 312.7), Offset(215.3, 312.3), Offset(215.7, 312.0), Offset(216.0, 311.7), Offset(216.7, 311.0), Offset(217.7, 310.3), Offset(218.0, 310.0), Offset(218.3, 310.0), Offset(219.0, 309.7), Offset(220.0, 309.3), Offset(220.3, 309.0), Offset(220.7, 309.0), Offset(221.0, 308.7), Offset(221.3, 308.3), Offset(222.0, 308.0), Offset(222.7, 307.3), Offset(223.3, 307.3), Offset(224.0, 306.7), Offset(224.3, 306.3), Offset(225.0, 306.0), Offset(225.7, 305.7), Offset(226.0, 305.7), Offset(226.3, 305.3), Offset(226.7, 305.3), Offset(227.3, 305.0), Offset(228.0, 304.7), Offset(228.7, 304.3), Offset(229.3, 304.0), Offset(230.0, 304.0), Offset(230.7, 303.7), Offset(231.3, 303.3), Offset(231.7, 303.3), Offset(232.0, 303.0), Offset(232.3, 303.0), Offset(232.7, 303.0), Offset(233.0, 303.0), Offset(233.3, 303.0), Offset(233.7, 303.0), Offset(234.0, 302.7), Offset(234.7, 302.7), Offset(235.3, 302.3), Offset(236.7, 302.3), Offset(237.3, 302.0), Offset(238.3, 301.7), Offset(239.0, 301.7), Offset(240.3, 301.3), Offset(241.0, 301.3), Offset(241.7, 301.0), Offset(242.3, 301.0), Offset(243.0, 300.7), Offset(243.7, 300.7), Offset(244.3, 300.3), Offset(245.0, 300.3), Offset(245.7, 300.3), Offset(246.3, 300.0), Offset(247.0, 300.0), Offset(247.7, 300.0), Offset(248.3, 300.0), Offset(248.7, 299.7), Offset(249.3, 299.7), Offset(249.7, 299.7), Offset(250.0, 299.7), Offset(250.3, 299.7), Offset(250.3, 299.3), Offset(250.7, 299.3), Offset(251.0, 299.3), Offset(251.3, 299.3), Offset(251.7, 299.3), Offset(252.3, 299.0), Offset(253.0, 299.0), Offset(254.3, 299.0), Offset(255.0, 299.0), Offset(255.7, 299.0), Offset(256.3, 298.7), Offset(257.0, 298.7), Offset(257.3, 298.7), Offset(257.7, 298.7), Offset(258.0, 298.7), Offset(258.3, 298.7), Offset(258.7, 298.7), Offset(259.0, 298.7), Offset(259.7, 298.7), Offset(260.7, 298.7), Offset(262.7, 298.7), Offset(263.7, 298.7), Offset(264.7, 298.7), Offset(265.3, 298.7), Offset(266.0, 298.7), Offset(266.3, 298.7), Offset(266.7, 298.7), Offset(267.0, 298.7), Offset(267.7, 299.0), Offset(268.0, 299.3), Offset(270.3, 300.0), Offset(271.7, 300.3), Offset(273.3, 300.7), Offset(274.3, 300.7), Offset(274.3, 301.0), Offset(275.0, 301.3), Offset(276.7, 301.7), Offset(278.3, 302.3), Offset(278.7, 302.3), Offset(279.3, 302.7), Offset(279.7, 302.7), Offset(279.7, 303.0), Offset(280.0, 303.0), Offset(281.3, 303.7), Offset(283.3, 304.7), Offset(284.3, 305.0), Offset(285.0, 305.3), Offset(285.3, 305.3), Offset(286.0, 306.0), Offset(287.3, 307.0), Offset(288.7, 307.7), Offset(289.3, 307.7), Offset(289.7, 308.0), Offset(290.0, 308.0), Offset(290.0, 308.3), Offset(290.3, 308.7), Offset(291.7, 309.3), Offset(292.7, 310.3), Offset(293.0, 310.7), Offset(293.0, 311.0), Offset(293.0, 311.3), Offset(293.0, 311.7), Offset(293.0, 312.0), Offset(292.7, 312.0), Offset(292.3, 312.3), Offset(292.0, 312.7), Offset(292.0, 313.0), Offset(291.7, 313.3), Offset(290.3, 314.3), Offset(288.7, 316.0), Offset(288.0, 317.0), Offset(287.3, 317.7), Offset(286.7, 317.7), Offset(286.0, 319.0), Offset(285.7, 320.0), Offset(285.3, 320.0), Offset(285.3, 320.3), Offset(284.7, 320.7), Offset(283.7, 321.0), Offset(282.0, 323.3), Offset(280.3, 325.3), Offset(279.3, 326.0), Offset(279.3, 326.7), Offset(279.0, 327.3), Offset(278.7, 327.3), Offset(278.3, 327.3), Offset(276.0, 328.3), Offset(274.0, 329.7), Offset(273.0, 330.3), Offset(272.3, 330.3), Offset(272.0, 330.7), Offset(271.7, 330.7), Offset(270.7, 331.0), Offset(268.7, 331.7), Offset(266.3, 333.0), Offset(263.7, 333.7), Offset(262.3, 334.0), Offset(262.0, 334.0), Offset(261.7, 334.0), Offset(259.0, 334.3), Offset(257.3, 334.7), Offset(254.7, 335.3), Offset(253.3, 335.7), Offset(253.0, 335.7), Offset(252.7, 335.7), Offset(252.3, 335.7), Offset(252.0, 335.7), Offset(251.7, 335.7), Offset(250.3, 336.0), Offset(247.3, 336.7), Offset(244.3, 337.0), Offset(242.3, 337.3), Offset(241.3, 337.3), Offset(241.0, 337.3), Offset(240.7, 337.3), Offset(240.3, 337.3), Offset(238.7, 337.3), Offset(236.3, 337.3), Offset(234.0, 337.7), Offset(232.7, 337.7), Offset(232.0, 337.7), Offset(231.7, 337.7), Offset(231.3, 337.7), Offset(228.7, 337.7), Offset(225.0, 337.7), Offset(223.3, 337.7), Offset(220.7, 337.3), Offset(218.7, 336.7), Offset(217.0, 336.0), Offset(215.7, 335.7), Offset(215.0, 335.7), Offset(214.7, 335.3), Offset(214.3, 335.0), Offset(214.3, 334.7), Offset(214.0, 334.3), Offset(213.3, 334.0), Offset(213.0, 333.3), Offset(212.7, 333.0), Offset(212.3, 332.7), Offset(211.0, 332.0), Offset(209.0, 330.7), Offset(207.3, 330.0), Offset(206.7, 329.3), Offset(206.3, 329.3), Offset(206.0, 329.0), Offset(205.0, 328.3), Offset(202.3, 326.7), Offset(201.0, 325.3), ]; static final List<Offset> leafBranchPoints2 = [ Offset(192.7, 389.3), Offset(142.3, 397.0) ]; static final List<Offset> leafPoints2 = [ Offset(192.7, 390.7), Offset(186.0, 388.0), Offset(185.7, 387.7), Offset(185.3, 387.3), Offset(184.7, 387.0), Offset(184.3, 386.3), Offset(184.0, 386.0), Offset(183.3, 385.7), Offset(183.0, 385.3), Offset(182.7, 385.0), Offset(182.3, 385.0), Offset(182.3, 384.7), Offset(182.0, 384.7), Offset(181.7, 384.3), Offset(181.3, 384.0), Offset(181.0, 384.0), Offset(180.3, 383.0), Offset(180.0, 383.0), Offset(179.3, 382.7), Offset(179.0, 382.3), Offset(178.7, 382.3), Offset(178.3, 382.0), Offset(178.3, 381.7), Offset(178.0, 381.7), Offset(177.7, 381.7), Offset(177.3, 381.7), Offset(177.0, 381.3), Offset(176.7, 381.0), Offset(176.0, 380.7), Offset(175.7, 380.7), Offset(175.0, 380.3), Offset(174.7, 380.3), Offset(174.0, 380.3), Offset(173.3, 379.7), Offset(173.0, 379.7), Offset(172.3, 379.3), Offset(171.7, 379.3), Offset(171.3, 379.3), Offset(170.7, 379.0), Offset(170.0, 379.0), Offset(169.3, 379.0), Offset(168.7, 378.7), Offset(168.3, 378.7), Offset(167.7, 378.7), Offset(167.0, 378.3), Offset(166.7, 378.3), Offset(166.0, 378.3), Offset(165.7, 378.3), Offset(165.3, 378.3), Offset(165.0, 378.3), Offset(164.7, 378.0), Offset(164.3, 378.0), Offset(164.0, 377.7), Offset(163.7, 377.7), Offset(163.0, 377.3), Offset(162.7, 377.3), Offset(162.7, 377.0), Offset(162.3, 377.0), Offset(162.0, 377.0), Offset(161.7, 376.7), Offset(161.0, 376.7), Offset(160.7, 376.7), Offset(160.3, 376.3), Offset(160.0, 376.3), Offset(159.7, 376.0), Offset(159.3, 376.0), Offset(159.0, 376.0), Offset(158.7, 376.0), Offset(158.3, 376.0), Offset(157.7, 376.0), Offset(157.3, 376.0), Offset(156.7, 376.0), Offset(156.3, 376.0), Offset(155.7, 376.0), Offset(155.0, 376.0), Offset(154.3, 376.0), Offset(153.3, 376.0), Offset(152.0, 376.0), Offset(151.3, 376.0), Offset(150.3, 376.0), Offset(149.7, 376.0), Offset(149.0, 376.0), Offset(148.3, 376.0), Offset(148.0, 376.0), Offset(147.3, 376.0), Offset(147.0, 376.0), Offset(146.7, 376.0), Offset(146.0, 376.0), Offset(145.7, 376.0), Offset(145.0, 376.0), Offset(144.7, 376.0), Offset(144.0, 376.0), Offset(143.3, 376.0), Offset(142.7, 376.0), Offset(142.0, 376.0), Offset(141.3, 376.0), Offset(140.7, 376.3), Offset(140.0, 376.3), Offset(139.3, 376.7), Offset(138.7, 376.7), Offset(138.0, 376.7), Offset(137.3, 377.0), Offset(137.0, 377.0), Offset(136.3, 377.0), Offset(135.0, 377.3), Offset(134.3, 377.3), Offset(133.7, 377.7), Offset(133.0, 378.0), Offset(131.7, 378.3), Offset(130.3, 378.7), Offset(129.0, 379.0), Offset(128.7, 379.3), Offset(128.0, 379.3), Offset(127.0, 379.7), Offset(126.0, 379.7), Offset(125.3, 379.7), Offset(124.7, 380.0), Offset(124.0, 380.0), Offset(123.7, 380.0), Offset(123.7, 380.3), Offset(123.3, 380.3), Offset(123.0, 380.3), Offset(122.7, 380.7), Offset(122.3, 380.7), Offset(122.0, 380.7), Offset(121.7, 381.0), Offset(121.3, 381.0), Offset(121.3, 381.3), Offset(121.0, 381.3), Offset(120.7, 381.3), Offset(120.0, 381.7), Offset(119.7, 382.0), Offset(119.0, 382.3), Offset(118.3, 382.7), Offset(117.7, 383.0), Offset(116.7, 383.7), Offset(116.0, 384.0), Offset(115.7, 384.3), Offset(115.3, 384.7), Offset(115.0, 385.0), Offset(114.7, 385.3), Offset(114.3, 385.3), Offset(114.3, 385.7), Offset(114.0, 385.7), Offset(113.0, 386.0), Offset(113.0, 386.3), Offset(112.7, 386.3), Offset(112.3, 386.7), Offset(112.3, 387.0), Offset(112.0, 387.0), Offset(112.0, 387.3), Offset(111.7, 387.3), Offset(111.3, 387.3), Offset(111.0, 387.7), Offset(110.7, 388.0), Offset(110.0, 388.3), Offset(110.0, 388.7), Offset(109.7, 389.0), Offset(109.3, 389.3), Offset(109.0, 389.3), Offset(108.7, 389.7), Offset(108.7, 390.0), Offset(108.3, 390.3), Offset(108.3, 390.7), Offset(108.3, 391.0), Offset(108.3, 391.3), Offset(108.0, 391.7), Offset(107.3, 392.0), Offset(107.0, 392.7), Offset(106.3, 393.3), Offset(106.0, 394.0), Offset(105.3, 395.0), Offset(104.7, 395.7), Offset(104.0, 396.3), Offset(103.7, 397.0), Offset(103.3, 397.7), Offset(103.0, 398.0), Offset(103.0, 398.3), Offset(102.7, 398.7), Offset(102.7, 399.0), Offset(102.3, 399.0), Offset(102.3, 399.3), Offset(102.0, 399.3), Offset(101.3, 399.7), Offset(101.0, 400.0), Offset(101.0, 400.3), Offset(100.7, 400.3), Offset(100.3, 400.3), Offset(100.0, 400.7), Offset(100.3, 400.7), Offset(100.7, 400.7), Offset(101.0, 400.7), Offset(101.3, 400.7), Offset(101.7, 401.0), Offset(101.7, 401.3), Offset(102.0, 401.3), Offset(102.3, 401.7), Offset(102.7, 401.7), Offset(103.0, 402.0), Offset(103.3, 402.0), Offset(103.3, 402.3), Offset(103.3, 402.7), Offset(103.7, 402.7), Offset(103.7, 403.0), Offset(104.0, 403.0), Offset(104.3, 403.0), Offset(104.3, 403.3), Offset(104.7, 403.3), Offset(104.7, 403.7), Offset(105.0, 404.3), Offset(105.7, 404.7), Offset(106.0, 405.0), Offset(106.3, 405.3), Offset(106.7, 405.7), Offset(106.7, 406.0), Offset(107.7, 406.3), Offset(108.3, 406.7), Offset(108.3, 407.0), Offset(108.7, 407.0), Offset(109.7, 407.7), Offset(110.0, 407.7), Offset(111.0, 408.3), Offset(112.7, 409.3), Offset(114.0, 409.7), Offset(115.0, 410.3), Offset(115.7, 411.0), Offset(116.3, 411.0), Offset(117.3, 411.0), Offset(118.7, 411.7), Offset(120.0, 411.7), Offset(120.0, 412.0), Offset(120.7, 412.0), Offset(121.3, 412.3), Offset(121.7, 412.3), Offset(122.7, 412.3), Offset(123.3, 412.3), Offset(124.3, 412.3), Offset(125.3, 412.7), Offset(125.7, 412.7), Offset(126.3, 412.7), Offset(126.7, 412.7), Offset(128.0, 412.7), Offset(129.3, 413.3), Offset(130.3, 413.3), Offset(131.7, 413.7), Offset(132.7, 414.0), Offset(133.3, 414.3), Offset(134.3, 414.3), Offset(134.7, 414.3), Offset(135.3, 414.7), Offset(137.3, 415.0), Offset(139.3, 415.3), Offset(141.3, 415.7), Offset(142.7, 416.0), Offset(143.3, 416.0), Offset(143.7, 416.0), Offset(144.7, 416.0), Offset(146.7, 416.0), Offset(148.0, 416.0), Offset(149.3, 416.0), Offset(150.7, 416.0), Offset(151.3, 416.0), Offset(151.7, 416.0), Offset(152.7, 416.0), Offset(154.3, 416.0), Offset(155.7, 416.0), Offset(156.3, 416.0), Offset(157.7, 416.0), Offset(159.0, 416.0), Offset(159.7, 416.0), Offset(160.3, 416.0), Offset(160.3, 415.7), Offset(160.7, 415.3), Offset(161.7, 414.7), Offset(164.3, 413.7), Offset(165.7, 412.7), Offset(166.7, 412.0), Offset(167.0, 412.0), Offset(167.3, 412.0), Offset(167.7, 411.7), Offset(168.7, 410.7), Offset(169.7, 409.7), Offset(171.7, 408.0), Offset(173.0, 407.0), Offset(173.7, 406.7), Offset(174.0, 406.3), Offset(174.7, 405.7), Offset(175.3, 405.0), Offset(175.7, 404.7), Offset(175.7, 404.3), Offset(176.0, 404.0), Offset(176.7, 403.3), Offset(177.7, 402.3), Offset(179.0, 401.3), Offset(180.0, 400.3), Offset(180.3, 399.7), Offset(181.0, 399.7), Offset(181.3, 399.3), Offset(182.0, 399.0), Offset(182.7, 398.3), Offset(183.0, 398.0), Offset(183.0, 397.7), Offset(183.7, 397.3), Offset(185.0, 396.3), Offset(187.0, 395.0), Offset(188.3, 394.0), Offset(189.0, 394.0), Offset(189.0, 393.3), Offset(189.0, 393.0), Offset(189.0, 392.3), Offset(189.0, 392.0), Offset(192.7, 390.7), ];}rose_flower.dart文件下是具体的界面和逻辑 ...

September 6, 2022 · 28 min · jiezi

关于flutter:flutter系列之UI-layout简介

简介对于一个前端框架来说,除了各个组件之外,最重要的就是将这些组件进行连贯的布局了。布局的英文名叫做layout,就是用来形容如何将组件进行摆放的一个束缚。 在flutter中,基本上所有的对象都是widget,对于layout来说也不例外。也就是说在flutter中layout也是用代码来实现的,这和其余的用配置文件来形容layout的语言有所不同。 你能够把layout看做是一种看不见的widget,这些看不见的widget是用来作用在可见的widget对象上,给他们施行一些限度。 flutter中layout的分类flutter中的layout widget有很多,他们大略能够分为三类,别离是只蕴含一个child的layout widget,能够蕴含多个child的layout widget和可滑动的Sliver widgets。 这三种layout也有很多种具体的实现,对于Single-child layout widgets来说,蕴含上面这些widgets: Align -- 用来对其蕴含在其中的组件进行对其操作。AspectRatio -- 对其中的组件进行比例缩放。Baseline -- 通过应用子组件的baseline来进行定位。Center -- 自组件位于两头。ConstrainedBox -- 相似于IOS中的constrain,示意子组件的限度条件。Container -- 一个罕用的widget,能够用来蕴含多个其余的widget。CustomSingleChildLayout -- 将其单个子项的布局推延。Expanded -- 将Row, Column 或者 Flex的child进行扩大。FittedBox -- 依据fit来缩放和定位其child。FractionallySizedBox -- 将child依照总可用空间进行调整。IntrinsicHeight -- 一个将其child调整为child固有高度的小部件。IntrinsicWidth -- 一个将其child调整为child固有宽度的小部件。LimitedBox -- 限度一个box的size。Offstage -- 将child放入render tree中,然而却并不触发任何重绘。OverflowBox -- 容许child笼罩父组件的限度。Padding -- 为child提供padding。SizedBox -- 给定size的box。SizedOverflowBox -- 能够笼罩父组件限度的box。Transform -- 子组件能够变换。以上是蕴含单个child的layout组件,上面是能够蕴含多个child的layout组件: Column -- 示意一列child。CustomMultiChildLayout -- 应用代理来定位和缩放子组件。Flow -- 流式布局。GridView -- 网格布局。IndexedStack -- 从一系列的child中展现其中的一个child。LayoutBuilder -- 能够依赖父组件大小的widget tree。ListBody -- 依据给定的axis来布局child。ListView -- 可滚动的列表。Row -- 示意一行child。Stack -- 栈式布局的组件。Table -- 表格模式的组件。Wrap -- 能够对子child进行动静调整的widget。可滑动的Sliver widgets有上面几种: ...

September 5, 2022 · 3 min · jiezi

关于flutter:独立产品灵感周刊-DecoHack-029-随便逛逛谷歌街景

本周刊记录乏味好玩的独立产品设计开发相干内容,每周公布,感兴趣的搭档能够点击订阅我的周刊。为保障每期都能收到,倡议邮件订阅。欢送通过 Twitter 私信举荐或投稿。产品举荐1. Dime - 一个完全免费的记账利用,设计和市面上的记账类型 APP 还是有点点区别能够试试看。 Marqly - 这是一个书签管理工具,目前在 BATA 测试阶段,性能还很简洁,除了 Raindrop 这个老产品之外不晓得大家还有没有用过相似的书签管理工具。I Miss My Cafe - 一个模仿咖啡馆的网站,之前有举荐过相似的 FM 网站。很乏味。Confetti - 这是一个习惯管理工具,做了多终端,性能就是通过可视化来开始养成好习惯并打消坏习惯。反对 iOS,Android,浏览器插件,还有网页端。月订阅费 2.50 美元或每年 25 美元。Muslim Tab - 这是一个穆斯林标签浏览器插件,每次关上新标签时都会显示简短的穆罕默德圣训作为揭示。如果你是穆斯林,能够试试看。ThisOrThat - 这是一个测试 YouTube 封面的工具,不晓得具体是怎么实现的性能,就想广告投放一样做A/B测试,看哪个视频的封面的点击率更高。这的确是很不错,Youtuber必定会有这个需要。Popsy - 这是一个 No-Code 制作网站的产品,能够像 Notion 编辑器一样制作网站,非常简单好用。官网有很多模板能够参考,关注这个产品也很久了,上周在 ProductHunt 上线了,反应很不错,Product Hunt App - 上周 Product Hunt 终于公布了测试了很久的挪动端产品,之前曾经有十分多的非官方APP了。这次官网客户端上线了,能够下载试试看,反对 Android 和 iOS。ProjectsForSale - 这又是一个售卖副业的新平台,不过如果你想看有哪些产品正在售卖以及产品具体的经营数据是怎么样的就必须付费订阅这个平台才能够看,售卖本人的我的项目是收费的,这样能筛选一部分不想买我的项目的人,不过我还是放弃狐疑这种商业化的成果。OpenArt - 这个网站收集了十分多从 DALL·E 2 生成的艺术图片,能够看看生成的图片是怎么形容的,能够在这里找找灵感。Plantnet - 这个网站面向动物爱好者,动物数据库十分全,能够辨认以及摸索野生植物。另外动物辨认类型的 APP 曾经呈现很多年了,这也不算是小众用户了,用户群体还是十分宽泛的。smalldev.tools - 一个开发者会用的一些小工具集,这类产品很多,这个网站做的很简洁。craftle - 你如果不晓得要买什么家具,能够上这个网站看看,只须要输出一个估算价格,这个网站就会举荐给你一些产品组合。RandomStreetView - 不晓得干啥的时候上这个网站看看,随机带你去一个谷歌街景逛逛。这又是一个用来杀工夫的好网站!你还能够指定国家。Comparison of “House Of The Dragon” Characters Height - 这个网站切实是又无聊又乏味,最近上映的《势力的游戏前传:龙族》,你能够在这个网站上比照本人和剧中人物的身高!开源我的项目1. Linksnap - 收费的 Biolink 产品,面向开发者的 Linktree ,开源的。做的很不错,还会主动同步你 Github 上的奉献数据。开发者@BrodasGeo。轻易看看1. WWDC22 视频现已提供简体中文字幕 - 还是有很多场会议值得回味一遍的。没看的敌人们当初能够回去看看了。更多内容能够订阅我的周刊: 竹白订阅|官网|RSS订阅 |Telegram频道|Twitter另外,感兴趣的搭档能够看看本周刊的会员打算。

September 5, 2022 · 1 min · jiezi

关于flutter:flutter系列之Material主题的基础MaterialApp

简介为了简化大家的应用,尽管flutter举荐所有的widget都有本人来进行搭建,然而在大框架下面,flutter提供了Material和Cupertino两种主题格调的Widgets汇合,大家能够在这两种格调的继承上进行个性化定制和开发。 这两种格调翻译成中文就是:资料和库比蒂诺?什么鬼....咱们还是应用默认的英文名来称说它们吧。 本文咱们将会深刻解说Material主题的根底-MaterialApp。 MaterialApp初探如果你应用最新的android Studio创立一个flutter我的项目的话,android Studio会主动为你创立一个基于flutter的应用程序。 咱们来看下主动创立的main.dart文件: Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', theme: ThemeData( primarySwatch: Colors.blue, ), home: const MyHomePage(title: 'Flutter Demo Home Page'), ) }这个build办法返回的widget就是这个flutter应用程序的根Widget。能够看到,默认状况下是返回一个MaterialApp。 在下面的样例代码中,为MaterialApp设置了tile,theme和home属性。 title是MaterialApp的题目,theme是整个MaterialApp的主题,home示意的是app进入时候应该展现的主页面。 默认状况下MyHomePage会返回一个相似上面代码的Scaffold: return Scaffold( appBar: AppBar( title: Text(widget.title), ), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: const <Widget>[ Text( 'home page', ), ], ), ), );这样咱们能够失去常见的MaterialApp界面: MaterialApp详解有了下面的框架,咱们就能够在home中构建本人的组件,从而开始flutter的欢快app之旅。 那么MaterialApp还有其余的什么性能吗?它的底层原理是怎么样的呢?一起来看看吧。 首先是MaterialApp的定义: class MaterialApp extends StatefulWidget能够看到MaterialApp是一个StatefulWidget,示意MaterialApp可能会依据用户的输出不同,从新build子组件,因为通常来说MaterialApp示意一个应用程序总体,所以它须要思考很多简单的交互状况,应用StatefulWidget是很正当的。 MaterialApp中的theme接下来咱们看下MaterialApp能够配置的主题。 MaterialApp中有上面几种theme: ...

September 2, 2022 · 2 min · jiezi

关于flutter:Flutter可扩展聚合广告插件GTAds

因为之前flutter_universalad开发时未思考到扩展性,前面在接入新的广告商时发现接入很麻烦,所以对插件进行重构,开发了GTAds,可能按需加载须要的广告,也能够通过简略的接入就实现自定义广告,开发者无需关注广告的展现,插件会依据配置主动抉择不同的广告商广告进行展现,临时不反对bidding模式。 广告的展现抉择通过传入的展现概率来抉择展现。 一、反对插件gtads(本体)gtads_csj(穿山甲广告反对)gtads_ylh(优量汇广告反对)gtads_sigmob(Sigmob广告反对)二、应用1、pubspec.yaml除gtads本体必须引入外,其余广告能够按需引入。如果想要的广告不反对,则能够通过通过扩大接口进行自定义广告接入。 //广告根底库 必须引入 gtads: ^0.0.6 //须要应用的广告按需引入,以下可选 //穿山甲广告 gtads_csj: ^0.0.5 //优量汇广告 gtads_ylh: ^0.0.2 //Sigmob广告 gtads_sigmob: ^0.0.12、引入import 'package:gtads/gtads.dart';3、增加广告广告初始化前必须实现增加 GTAds.addProvider([GTAdsCsjProvider("csj","5098580","5098580")]);GTAdsCsjProviderc参数 alias: 广告别名,必须保障惟一,后续广告加载回调将返回这个别名 辨认是哪家的广告 androidId: andorid appId iosId: ios appId 4、初始化//isDebug 是否开启debug日志await GTAds.init(isDebug: true);//return [{csj: true}],增加的广告初始化后果5、横幅广告 GTAdsBannerWidget( //须要的广告位数组 codes: [GTAdsCode(alias: "csj", probability: 5,androidId: "945410197",iosId: "945410197")], //宽 width: 300, //高 height: 400, //超时工夫 当广告失败后会顺次重试其余广告 直至所有广告均加载失败 设置超时工夫可提前勾销 timeout: 5, //回调 callBack: GTAdsCallBack( onShow: (code) { print("Banner显示 ${code.toJson()}"); }, onClick: (code) { print("Banner点击 ${code.toJson()}"); }, onFail: (code,message) { print("Banner谬误 ${code.toJson()} $message"); }, onClose: (code) { print("Banner敞开 ${code.toJson()}"); },)),6、激励广告 var b = await GTAds.rewardAd( //须要的广告位数组 codes: [GTAdsCode(alias: "csj", probability: 5,androidId: "945418088",iosId: "945418088")], //处分名称 rewardName: "100金币", //处分数量 rewardAmount: 100, //用户id userId: "user100", //扩大参数 customData: "123", //超时工夫 当广告失败后会顺次重试其余广告 直至所有广告均加载失败 设置超时工夫可提前勾销 timeout: 5, callBack: GTAdsCallBack( onShow: (code) { print("激励广告显示 ${code.toJson()}"); }, onFail: (code, message) { print("激励广告失败 ${code.toJson()} $message"); }, onClick: (code) { print("激励广告点击 ${code.toJson()}"); }, onClose: (code) { print("激励广告敞开 ${code.toJson()}"); }, onVerify: (code, verify, transId, rewardName, rewardAmount) { print( "激励广告敞开 ${code.toJson()} $verify $transId $rewardName $rewardAmount"); }, onExpand: (code, param) { print("激励广告自定义参数 ${code.toJson()} $param"); }),);if (b) { print("激励广告开始申请");}else{ print("激励广告开始申请失败");}7、插屏广告var b = await GTAds.insertAd( //须要的广告位组 codes: [GTAdsCode(alias: "csj", probability: 5,androidId: "946201351",iosId: "946201351")], isFull: false, width: 300, height: 500, //超时工夫 当广告失败后会顺次重试其余广告 直至所有广告均加载失败 设置超时工夫可提前勾销 timeout: 5, callBack: GTAdsCallBack( onShow: (code) { print("插屏广告显示 ${code.toJson()}"); }, onFail: (code, message) { print("插屏广告失败 ${code.toJson()} $message"); }, onClick: (code) { print("插屏广告点击 ${code.toJson()}"); }, onClose: (code) { print("插屏广告敞开 ${code.toJson()}"); },));8、开屏广告GTAdsSplashWidget( //须要的广告位组 codes: [GTAdsCode(alias: "csj", probability: 5,androidId: "887367774",iosId: "887367774")], width: MediaQuery.of(context).size.width, height: MediaQuery.of(context).size.height, //超时工夫 当广告失败后会顺次重试其余广告 直至所有广告均加载失败 设置超时工夫可提前勾销 timeout: 5, callBack: GTAdsCallBack( onShow: (code) { print("开屏显示 ${code.toJson()}"); }, onClick: (code) { print("开屏点击 ${code.toJson()}"); }, onFail: (code, message) { print("开屏谬误 ${code.toJson()} $message"); Navigator.pop(context); }, onClose: (code) { print("开屏敞开 ${code.toJson()}"); Navigator.pop(context); }, ),),9、信息流GTAdsNativeWidget( //须要的广告位组 codes: [GTAdsCode(alias: "csj", probability: 5,androidId: "945417699",iosId: "945417699")], width: 300, height: 200, //超时工夫 当广告失败后会顺次重试其余广告 直至所有广告均加载失败 设置超时工夫可提前勾销 timeout: 5, callBack: GTAdsCallBack( onShow: (code) { print("信息流显示 ${code.toJson()}"); }, onClick: (code) { print("信息流点击 ${code.toJson()}"); }, onFail: (code,message) { print("信息流谬误 ${code.toJson()} $message"); }, onClose: (code) { print("信息流敞开 ${code.toJson()}"); }, ),),三、广告位GTAdsCode阐明如果不想展现某个广告商的广告,则能够通过不传入该广告的code来显示 ...

September 2, 2022 · 3 min · jiezi

关于flutter:Flutter-新一代图形渲染器-Impeller

一、背景在2022年6月Google官网公布的Flutter 3.0 版本中,正式将渲染器 Impeller 从独立仓库中合入 Flutter Engine 骨干进行迭代,这是2021年Flutter团队推动从新实现Flutter渲染后端以来,首次明确了Impeller将来代替 Skia 作为 Flutter 主渲染计划的定位。Impeller的呈现是Flutter团队用以彻底解决 SkSL(Skia Shading Language)引入的Jank问题所做的重要尝试,那什么是着色器编译Jank问题呢? 家喻户晓,Flutter底层应用了skia做为2D图形渲染库,而skia外部定义了一套SkSL(Skia shading language),SkSL 属于 GLSL 变体。这句话怎么了解呢?艰深的讲,SkSL就是基于某一固定版本的GLSL语法进行的设计,其作用是抹去不同GPU驱动API着色器语法的差别,以便对不同的GPU驱动进一步输入为指标着色器语言,因而SkSL能够看做是着色器的预编译语言。 在Flutter的光栅化阶段,第一次应用着色器时Skia会依据绘图命令和设施参数生成 SkSL,而后再将 SkSL 转换为特定后端(GLSL、GLSL ES 或 Metal SL)着色器,并在设施上编译为着色器程序。而编译着色器可能破费几百毫秒,导致数十帧的失落。定位着色器编译Jank问题能够查看trace信息是否有 GrGLProgramBuilder::finalize 调用,比方。 官网首次留神到 Flutter的Jank问题是在 2015 年,过后推出的最重要的优化是对Dart代码应用 AOT编译优化执行效率,不过Jank也带来了新的问题。 Jank问题可分为首次运行卡顿(Early-onset Jank)和非首次运行卡顿,首次运行卡顿的实质是运行时着色器的编译行为阻塞了 Flutter Raster 线程对渲染指令的提交。在原生利用开发过程中,开发者通常会基于UIkit等零碎级别的UI框架开发利用,极少应用自定义的着色器,所以原生利用极少呈现着色器编译引起的性能问题,更常见的是用户逻辑对 UI 线程适度占用。 官网为了优化首次运行卡顿 ,推出了SkSL的Warmup计划,Warmup计划的原理是将局部性能敏感的 SkSL 生成工夫前置到编译期,依然须要在运行时将SkSL转换为MSL能力在GPU上执行。Warmup计划须要在开发期间在实在设施上捕捉 SkSL 导出配置文件,在利用打包时通过编译参数能够将局部SkSL预置在利用中。此外因为 SkSL 创立过程中捕捉了用户设施特定的参数,不同设施 Warmup 配置文件不能互相通用,这种计划带来的性能晋升十分无限。 同时,给Warmup计划带来的另一个挑战是,Apple 在2019年发表在其生态中废除OpenGL技术,转而应用新的Metal渲染器,为此,Flutter在2.5版本实现了对Metal渲染器的适配。不过,与预期不符的是,Metal的切换使得Early-onset Jank的状况更加好转,Warmup计划的实现须要依赖Skia团队对Metal的预编译做反对,因为Skia团队的排期问题,一度导致Warmup计划在 Metal后端上不可用。与此同时社区中对 iOS 平台 Jank 问题的反馈更加强烈,社区中一度呈现屏蔽Metal的Flutter Engine Build,回退到GL后端。与之绝对的是,因为Android平台领有 iOS 缺失的着色器机器码的缓存能力,Android 平台呈现 Jank 的概率比 iOS 低很多。 ...

September 1, 2022 · 4 min · jiezi

关于flutter:Flutter-33-正式发布

Flutter 3 是咱们正式为全平台提供反对的一个重量级里程碑,间隔它的公布仅过来了三个月,明天让咱们有请 Flutter 3.3 正式版!近三个月咱们并没有加快更新迭代的速度——自 Flutter 3 公布以来,咱们曾经为 Flutter 合并了 5687 个拉取申请。 本次更新带来了 Flutter Web 平台、桌面端平台、文本处理的性能和其余更新内容。 同时咱们也会介绍 go_router package、DevTools (开发者工具) 和 VS Code 扩大相干的更新内容。与咱们一起浏览具体理解它们吧! 框架更新全局抉择到当初为止,Flutter 在 Web 上的文本抉择交互依然没有达到预期。与 Flutter 利用不同,原生的 Web 利用会将每个节点构建为树形构造。在传统的 Web 利用中你能够轻松用拖动手势来抉择网页上的节点,这在 Flutter Web 利用中无奈轻松达成。 从今天起,所有都产生了变动。咱们引入了 SelectionArea widget,它的子 widget 现已能够进行随便抉择! 只需应用 SelectionArea 包裹住路由显示的内容 (例如 Scaffold),Flutter 会替你解决好所有,你便能够享受到这项强力的新个性。 想要更全面深刻地理解这个绝妙的新性能,请拜访 SelectionArea API 页面。 触控板操作Flutter 3.3 优化了针对触控板的反对。Flutter 不仅提供了更丰盛且顺滑的管制,同时也缩小了几种特定状况的误触。若你想理解误触的示例,你能够查看 Flutter 实用教程 页面。将页面滚动到底部的 DartPad,并追随以下步骤进行操作: 放大窗口让上半局部呈现滚动条将指针悬停在上半局部应用触控板进行滚动在 Flutter 3.3 以前,应用触控板滚动会拖动元素,因为 Flutter 将模仿的手势事件进行了下发从 Flutter 3.3 开始,应用触控板滚动会正确地滚动列表,因为 Flutter 会传递「滚动」事件,卡片不会辨认这些事件,而列表会进行对应的解决想理解更多信息,请拜访 Flutter 触控板手势.pdf "Flutter 触控板手势")) 的设计文档,并且查看以下的拉取申请: ...

August 31, 2022 · 3 min · jiezi

关于flutter:flutter系列之移动端的手势基础GestureDetector

简介挪动的和PC端有什么不同呢?同样的H5能够运行在APP端,也能够运行在PC端。两者最大的区别就是挪动端能够用手势。手势能够做到一些比方左滑右滑,上滑下滑,缩放等操作。 原生的andorid和IOS当然能够做到这些事件,作为一个挪动的的开发框架flutter,天然也可能反对手势。flutter中的手势反对叫做GestureDetector,一起来看看flutter中的手势根底吧。 Pointers和Listener咱们先来考虑一下最简略的手势是什么呢?很显著,最简略的手势就是模仿鼠标的点击操作。咱们能够将其称之为Pointer event,也就是各种点击事件。 flutter中有四种Pointer事件,这些事件如下所示: PointerDownEvent --示意用手点击了屏幕,接触到了一个widget。PointerMoveEvent --示意手指从一个地位挪动到另外一个地位。PointerUpEvent --手指从点击屏幕变成了来到屏幕。PointerCancelEvent --示意手指来到了该应用程序。那么点击事件的传递机制是什么样的呢? 以手指点击屏幕的PointerDownEvent事件为例,当手指点击屏幕的时候,flutter首先会去定位该点击地位存在的widget,而后将该点击事件传递给该地位的最小widget. 而后点击事件从最新的widget向上开始冒泡,并将其分派到从最外面的widget到树根的门路上的所有widget中。 留神,flutter中并没有勾销或进行进一步分派Pointer事件的机制。要想监听这写Pointer事件,最简略间接的方法就是应用Listener: class Listener extends SingleChildRenderObjectWidget { /// Creates a widget that forwards point events to callbacks. /// /// The [behavior] argument defaults to [HitTestBehavior.deferToChild]. const Listener({ Key? key, this.onPointerDown, this.onPointerMove, this.onPointerUp, this.onPointerHover, this.onPointerCancel, this.onPointerSignal, this.behavior = HitTestBehavior.deferToChild, Widget? child, }) : assert(behavior != null), super(key: key, child: child);能够看到Listener也是一种widget,并且能够监听多种Pointer的事件。 咱们能够把要监听Pointer的widget封装在Listener中,这样就能够监听各种Pointer事件了,具体的例子如下: Widget build(BuildContext context) { return ConstrainedBox( constraints: BoxConstraints.tight(const Size(300.0, 200.0)), child: Listener( onPointerDown: _incrementDown, onPointerMove: _updateLocation, onPointerUp: _incrementUp, child: Container( color: Colors.lightBlueAccent, child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ const Text( 'You have pressed or released in this area this many times:'), Text( '$_downCounter presses\n$_upCounter releases', style: Theme.of(context).textTheme.headline4, ), Text( 'The cursor is here: (${x.toStringAsFixed(2)}, ${y.toStringAsFixed(2)})', ), ], ), ), ), ); void _incrementDown(PointerEvent details) { _updateLocation(details); setState(() { _downCounter++; }); } void _incrementUp(PointerEvent details) { _updateLocation(details); setState(() { _upCounter++; }); } void _updateLocation(PointerEvent details) { setState(() { x = details.position.dx; y = details.position.dy; }); }然而对于Lisenter来说只能监听最原始的Pointer事件,所以如果想监听更多类型的手势事件的话,则能够应用GestureDetector. ...

August 29, 2022 · 2 min · jiezi

关于flutter:flutter系列之构建Widget的上下文环境BuildContext详解

简介咱们晓得Flutter中有两种Widget,别离是StatelessWidget和StatefulWidget,StatelessWidget中有一个build办法来创立对应的Widget,尽管StatefulWidget中没有对应的build办法,然而和StatefulWidget对应的State中也有同样的build办法。 这个build办法就是用来创立Widget的外围办法。 咱们来看下build办法的定义: Widget build(BuildContext context);build办法传入一个BuildContext对象,返回一个Widget对象,也就是说这个BuildContext中蕴含了要创立的Widget的所有信息。这个BuildContext被称为是Widget的上下文构建环境。 那么BuildContext有什么个性呢?咱们又该如何应用BuildContext呢?一起来看看吧。 BuildContext的实质还记得flutter中的三颗树吗? 他们别离是Widgets树,Element树和Render树。其中Widgets树和Element树是一一对应的。而Render树和Element中的RenderObjectElement是一一对应的。 事实上BuildContext就是一个Element对象。怎么说呢? 咱们先看下BuildContext的定义: abstract class BuildContext { Widget get widget; ...}BuildContext是一个抽象类,咱们再看一下Element类的定义: abstract class Element extends DiagnosticableTree implements BuildContext {能够看到,Element对象实现了BuildContext接口,而每一个BuildContext都有一个和其绑定的Widget对象。 通过简单的关系传递运算,咱们能够晓得Element对象和Widget对象从代码层面来说,的确是一一对应的。 BuildContext和InheritedWidgetInheritedWidget是一种widget用来在tree中向下传递变动信息,在tree的子节点中,能够通过调用BuildContext.dependOnInheritedWidgetOfExactType在子节点中查找最近的父InheritedWidget,从而将以后的BuildContext绑定的widget和InheritedWidget建设绑定关系,从而在下次InheritedWidget产生变动的时候,会主动触发BuildContext绑定的widget的rebuild办法。 听起来如同很简单的样子,然而实际上很简略,咱们举个例子,首先咱们须要定义一个Widget用来继承InheritedWidget: class FrogColor extends InheritedWidget { const FrogColor({ Key? key, required this.color, required Widget child, }) : super(key: key, child: child); final Color color; static FrogColor of(BuildContext context) { final FrogColor? result = context.dependOnInheritedWidgetOfExactType<FrogColor>(); assert(result != null, 'No FrogColor found in context'); return result!; } @override bool updateShouldNotify(FrogColor old) => color != old.color; }在这个办法中,咱们须要定义一个of办法,这个该办法中,咱们调用context.dependOnInheritedWidgetOfExactType办法,用来查找离BuildContext最近的FrogColor。 ...

August 26, 2022 · 1 min · jiezi

关于flutter:flutter系列之用来管理复杂状态的State详解

简介Flutter的根底是widget,依据是否须要跟用户进行交互,widget则能够分为StatelessWidget和StatefulWidget。StatelessWidget只能依据传入的状态进行简略的初始化widget,如果要实现跟用户交互这种简单的性能,则须要用到StatefulWidget。 然而对于StatefulWidget自身来说,它并不存储任何状态,所有的状态都是寄存在和StatefulWidget关联的State中的。 明天,让咱们来摸索一下StatefulWidget和State的关系。 StatefuWidget和StateStatefulWidget的定义很简略,它是一个abstract class,继承它只须要实现一个createState的办法: abstract class StatefulWidget extends Widget { const StatefulWidget({ Key? key }) : super(key: key); @override StatefulElement createElement() => StatefulElement(this); @protected @factory State createState(); }留神,这里的createState是一个工厂类办法。这就意味着一个StatefulWidget能够创立多个State。 比方,如果从树中删除一个StatefulWidget,稍后再次将其插入到树中,Flutter将再次调用StatefulWidget.createState 来创立一个新的 State对象。 那么State中能够拜访创立它的StatefulWidget吗?答案是必定的。 在State中定义了一个T类型的widget, 这个T是StatefulWidget的子类: abstract class State<T extends StatefulWidget> with Diagnosticable { T get widget => _widget!; T? _widget;这里的_widget是不须要咱们自行去设置的,这个_widget是由flutter框架在调用initState之前设置的。该_widget实际上就是和State关联的StatefulWidget。 咱们能够间接在在State中应用widget来援用它。 State的生命周期讲完StatefulWidget和State的关系之后,接下来咱们来理解一下State是如何变动的,艰深的讲,就是State的生命周期是怎么样的。 通常来说,一个State的生命周期有4个状态,别离是created,initialized,ready和defunct状态,这四个状态是定义在枚举类_StateLifecycle中的: enum _StateLifecycle { /// State曾经被创立胜利了,State.initState办法被调用。 created, /// State.initState办法尽管被调用了,然而State对象还没有构建结束。 这时候会调用State.didChangeDependencies办法. initialized, /// State对象创立胜利,State.dispose办法还没有被调用。 /// called. ready, /// State.dispose办法被调用过了,State对象不容许再调用build办法。 defunct,}咱们具体来解说一下State的生命周期。 ...

August 22, 2022 · 1 min · jiezi

关于flutter:邀请参与-2022-第三季度-Flutter-开发者调查

自 Flutter 3 公布之后,咱们在以挪动端为核心到多平台框架的路线上稳步前行,用 Dart 2.17 的新语言个性帮忙大家晋升工作效率,并对外围工具进行了改良,让您在跨平台打造优良体验时更加得心应手。这一路的经验让咱们深知随时理解开发者诉求的重要性,这里诚邀您参加本次 ☟Flutter 开发者问卷调研☟,来帮忙 Flutter 做到更好。 本次调研会较为具体地理解大家对 Flutter 框架、开发语言、package 生态 (包含 Firebase package)、IDE 插件以及 Material Design / Cupertino 系列 widget 的应用体验等多个方面的满意度。您能够随时来到问卷页面,并在不便的时候返回持续作答,但请留神 本次调研将于 2022 年 8 月 27 日截止。

August 19, 2022 · 1 min · jiezi

关于flutter:Flutter学习第四课SharedPreferences本地存储的简单使用

一:第一步:Main.dart界面 import 'package:flutter/material.dart';import 'package:flutter_first/storage/storage_sp.dart';void main() { runApp(MyApp());}class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: "SharedPreferences示例", theme: ThemeData(primarySwatch: Colors.blue), home: StorageSp(), ); }}第二步:SharePrefences 数据存储界面 import 'package:flutter/material.dart';import 'package:shared_preferences/shared_preferences.dart';class StorageSp extends StatefulWidget { const StorageSp({Key? key}) : super(key: key); @override State<StatefulWidget> createState() => _StorageSpState();}class _StorageSpState extends State<StorageSp> { //第一步:实例化本地存储对象 Future<SharedPreferences> _prefs = SharedPreferences.getInstance(); //昵称及抉择语言的值 文本输出的控制器 var controller = TextEditingController(); //定义变量 value_dart,value_js,value_java bool value_dart = false; bool value_js = false; bool value_java = false; @override void initState() { super.initState(); initFromCache(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text("SharedPreferences示例"), ), body: Container( padding: EdgeInsets.all(15), child: Column( crossAxisAlignment: CrossAxisAlignment.center, children: <Widget>[ TextField( controller: controller, //一个自定义控制器,可实现相似TextEditingController decoration: InputDecoration( //一个输入框 labelText: "昵称:", hintText: "请输出名称"), ), Text("你喜爱的编程语言"), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: <Widget>[ Text("Dart"), //Switch 示意开关组件 value选中的值,onChanged 扭转时触发的事件 Switch( value: value_dart, onChanged: (isChanged) { //设置状态扭转要存储的值 setState(() { this.value_dart = isChanged; }); }) ], ), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: <Widget>[ Text("JavaScript"), Switch( value: value_js, onChanged: (isChanged){ //设置状态扭转要存储的值 setState(() { this.value_js=isChanged; }); }) ], ), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: <Widget>[ Text("Java"), Switch( value: value_java, onChanged: (isChanged){ //设置状态扭转要存储的值 setState(() { this.value_java=isChanged; }); }) ], ), MaterialButton( child: Text("保留"), onPressed: (){ saveInfo(controller.text); }) ], ), ), ); } //从缓存中获取信息填充 void initFromCache() async { //获取SharedPreferences对象 final SharedPreferences prefs = await _prefs; //依据键(key)获取本地存储的值(value) final value_nickname = prefs.getString("key_nickname"); final value_dart = prefs.getBool("key_dart"); final value_js = prefs.getBool("key_js"); final value_java = prefs.getBool("key_java"); //获取到缓存中的值后,应用setState更新界面信息 setState(() { controller.text = (value_nickname == null ? "" : value_nickname); this.value_dart = (value_dart == null ? false : value_dart); this.value_js = (value_js == null ? false : value_js); this.value_java = (value_java == null ? false : value_java); }); } //保留界面的输出抉择信息 void saveInfo(String value_nickname) async{ final SharedPreferences prefs=await _prefs; prefs.setString("key_nickname", value_nickname); prefs.setBool("key_dart", value_dart); prefs.setBool("key_js", value_js); prefs.setBool("key_java", value_java); }}在Android下的数据data/data/包名/shared_prefs ...

August 19, 2022 · 2 min · jiezi

关于flutter:flutter系列之widgets构成flutter的基石

简介flutter中所有的组件都是由widgets组成的,flutter中有各种各样的widgets,这些widgets形成了flutter这个大厦。 那么flutter中的widget有什么特点呢?咱们应该怎么学习widget呢? 一起来看看吧。 StatelessWidget和StatefulWidget实时上,flutter中的widgets是受到React的启发来实现的。flutter中的widget能够分为StatefulWidget和StatelessWidget,别离代表有状态的Widgets和无状态的Widgets。 有状态和无状态,大家听起来是不是很相熟,咱们在应用程序中也常常会用到有状态的Bean和无状态的Bean。他们的原理和flutter的两类Widget其实是差不多的。 StatelessWidget因为是无状态的,所以它只会依据初始传入的配置信息来构建Widget,因为Widget是不可变的,所以StatelessWidget创立进去就不会再变动。 对于StatefulWidget来说,除了依据初始传入的配置来创立Widget之外,它外部还蕴含了一个State。这个State用来和用户的行为进行交互,从而对State中的值进行批改。当State被批改后,和其绑定的Widget会依据特定的算法进行比拟,看是否须要进行重绘,从而将用户的交互反映在用户界面上。 widget提供了一个build办法,build办法返回一个Widget,用于生成最初的RenderObject对象。 build办法的定义如下: Widget build(BuildContext context);但事实上,只有StatelessWidget中才有build办法。那么StatefulWidget为什么没有build办法呢? StatefulWidget尽管没有build办法,然而它有一个createState办法用来创立跟它关联的State: State createState(); 而这个build办法是放在State外面的。 StatelessWidget详解什么样的组件能够做成无状态的组件呢?那些不须要和用户交互的组件就能够。 flutter中的无状态Widget都有那些呢? 这里列出几个flutter中根本和常常应用的StatelessWidget: Text: 用来创立文本。 Row和Column: 示意的是纵向扩大和横向扩大的行和列。Row和Column是基于web的flexbox布局。 还有一个基于web的相对定位的布局叫做Positioned,Positioned通常是和Stack一起应用的。 Stack就是一个栈的构造,在Stack中你能够将一个widget放在另外一个widget的下面。 Positioned用在Stack中,能够绝对于top, right, bottom或者left边界进行绝对定位,十分好用。 另外一个罕用的组件就是Container,它示意的是一个长方形的元素,Container能够用BoxDecoration来润饰,用来示意背景、边框和暗影等。 Container还能够蕴含margins,padding和尺寸限度等个性。 接下来咱们来通过一个具体的例子来阐明StatelessWidget到底是怎么应用的。 如果咱们想构建一个上面款式的界面,该怎么做呢? 这个界面能够分为两局部,下面的个别称之为appBar,上面的个别叫做content。 appBar按列的布局又能够分为三局部,第一局部是一个IconButton示意导航菜单,第二局部是一个Text示意页面题目,第三局部也是一个IconButton示意搜寻按钮。 这三局部依照Row来进行组合. 那么依照Flutter的widget的构建准则,咱们能够把appBar构建成一个Widget。因为这个Widget的行为只跟初始化状态无关,所以能够将其设置成为StatelessWidget: class MyAppBar extends StatelessWidget { const MyAppBar({required this.title, Key? key}) : super(key: key); final Widget title; @override Widget build(BuildContext context) { return Container( height: 56.0, // bar的高度 padding: const EdgeInsets.symmetric(horizontal: 8.0), decoration: BoxDecoration(color: Colors.blue[500]), // 按Row来进行布局 child: Row( children: [ const IconButton( icon: Icon(Icons.menu), tooltip: '导航菜单', onPressed: null, // 目前不可点击 ), // Expanded组件,用于填充所有可用的空间 Expanded( child: title, ), const IconButton( icon: Icon(Icons.search), tooltip: '搜寻', onPressed: null, ), ], ), ); }}下面的代码中,咱们把Row蕴含在一个Container中,而后将这个Container返回作为appBar的理论内容。 ...

August 18, 2022 · 2 min · jiezi

关于flutter:Flutter-学习第四课综合部分页面详情页

一:实现上面的的页面二:main.dart页面 import 'package:flutter/material.dart';import 'package:flutter_first/scenery/landscape_detail.dart';void main() { runApp(MyApp());}class MyApp extends StatelessWidget{ @override Widget build(BuildContext context) { return MaterialApp( title: "布局综合示例", //自定义主题,主体色彩为绿色格调 theme: ThemeData(brightness: Brightness.light,primaryColor: Colors.lightGreen[600],accentColor: Colors.orange[600]), home: LandsDetail(), ); }}第二步:landscape_detail.dart 应用ListView 实现布局滚动 import 'package:flutter/material.dart';class LandsDetail extends StatefulWidget { const LandsDetail({Key? key}) : super(key: key); @override State<StatefulWidget> createState() => _LandsDtailState();}class _LandsDtailState extends State<LandsDetail> { @override Widget build(BuildContext context) { return new Scaffold( appBar: AppBar( title: Text( "武当山风景区", style: TextStyle(color: Colors.white), ), ), //应用列表视图默认为垂直布局,并且子元素可能高低滚动 body: ListView( children: <Widget>[ //风景图片 Image.asset("lib/assets/images/wudang.jpg", width: 600.0, height: 240.0, fit: BoxFit.cover), AddressContainer(), ButtonsContainer(), TextContainer(), ], ), ); }}class AddressContainer extends StatelessWidget { @override Widget build(BuildContext context) { return Container( padding: EdgeInsets.all(32.0), //此局部周围距离肯定间隔 //程度布局 child: Row( children: <Widget>[ Expanded( child: Column( //垂直布局 crossAxisAlignment: CrossAxisAlignment.start, //次轴说释怀左侧对齐 children: <Widget>[ Container( padding: EdgeInsets.only(bottom: 8.0), //与上面文本距离肯定间隔 child: Text( "风景区地址", style: TextStyle(fontWeight: FontWeight.bold), ), ), Text( "湖北十堰市丹江口市", style: TextStyle(color: Colors.grey[500]), ) ], )), //图标 Icon( Icons.star, color: Colors.red[500], ), Text("66") ], )); }}class ButtonsContainer extends StatelessWidget { @override Widget build(BuildContext context) { return Container( child: Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, //程度方向均排列每一个元素 children: <Widget>[ buildButtonColumn(Icons.call, "电话"), buildButtonColumn(Icons.near_me, "导航"), buildButtonColumn(Icons.share, "分享"), ], ), ); } Column buildButtonColumn(IconData icon, String label) { //垂直布局 return Column( //垂直方向大小最小化 mainAxisSize: MainAxisSize.min, //垂直方向居中对齐 mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ //下面图标局部 Icon( icon, color: Colors.lightGreen[600], ), //间隔下面肯定间距 Container( margin: EdgeInsets.only(top: 8.0), child: Text( label, style: TextStyle( fontSize: 12.0, fontWeight: FontWeight.w400, color: Colors.lightGreen[600]), ), ), ], ); }}class TextContainer extends StatelessWidget { @override Widget build(BuildContext context) { return Container( padding: const EdgeInsets.all(32.0), //文本块肯定要用'''来援用 child: Text(''' 武当山,中国道教圣地,又名太和山、谢罗山、参上山、仙室山,古有“太岳”、“玄岳”、“大岳”之称。位于湖北西北部十堰市丹江口市境内。东接闻名古城襄阳市,西靠车城十堰市,南望原始森林神农架,北临高峡平湖丹江口水库。 明代,武当山被皇帝封为“大岳”、“治世玄岳”,被尊为“皇室家庙”。武当山以“四大名山皆拱揖,五方仙岳共朝宗”的“五岳之冠”位置闻名于世。 1994年12月,武当山古建筑群入选《世界遗产名录》,2006年被整体列为“全国重点文物保护单位”。2007年,武当山和长城、丽江、周庄等景区一起入选“欧洲人最青睐的中国十大景区”。2010至2013年,武当山别离被评为国家5A级旅游区、国家森林公园、中国十大避暑名山、海峡两岸交换基地,入选“中国最美地质公园”。 截至2013年,武当山有古建筑53处,建筑面积2.7万平方米,修建遗迹9处,占地面积20多万平方米,全山保留各类文物5035件。 武当山是道教名山和武当武术的发源地,被称为“亘古无双胜境,天下第一仙山”。武当武术,是中华武术的重要流派。元末明初,道士张三丰集其大成,创始武当派。'''), ); }}第三步:援用的图片资源 ...

August 16, 2022 · 2 min · jiezi

关于flutter:flutter系列之flutter架构什么的看完这篇文章就全懂了

简介Flutter是google开发的一个跨平台的UI构建工具,flutter目前最新的版本是3.0.5。应用flutter你能够应用一套代码搭建android,IOS,web和desktop等不同平台的利用。做到一次编写到处运行的目标。 说到一次编写处处运行,大家可能会想到java。那么flutter跟java是不是相似呢? 对于JAVA来说,在编写完JAVA代码之后,将其编译成为class字节码,而后这个class字节码就能够不须要进行任何转换的在任何平台上运行。其底层原理是JAVA开发了适配不同操作系统和平台的JVM,class理论运行在JVM中,所以对底层到底运行在哪个平台是无感的。所有的适配都是由JVM来执行的。 Flutter其实更像是C或者C++,尽管代码是一样的,然而须要依据不同的平台编译成不同的二进制文件。而Flutter也是一样,尽管咱们应用同一套dart代码编写了Flutter程序,然而须要不同的命令编译成不同平台的命令和安装包。 当然,在开发过程中,flutter提供了虚拟机,实现了hot reload的性能,在代码进行批改之后,能够立即重载,而不须要从新编译整个代码。 FLutter这么神奇,那么它到底是怎么工作的呢? Flutter的架构图咱们先来看下Flutter的架构图,当然这个架构图是官网来的,官网的架构图示意的是权威: 从上图中,咱们能够看到Flutter的架构能够分为三局部,从下到上别离是embedder,Engine和Framework。 embedderembedder能够称为嵌入器,这是和底层的操作系统进行交互的局部。因为flutter最终要将程序打包到对应的平台中,所以这个嵌入器须要和底层的平台接口进行交互。 具体而言,对于Android平台应用的是Java和C++,对于iOS和macOS平台,应用的是Objective-C/Objective-C++,对应Windows平台和Linux平台的是C++。 为什么C++这么弱小? 这里就可以看进去了,基本上所有底层的货色都是用C++写的。回到embedder,为什么叫做嵌入器呢?这是因为Flutter打包的程序,能够作为整个应用程序,也能够作为现有程序的一部分被嵌入应用。 engineengine也叫做flutter engine,它是flutter中最外围的局部。 Flutter engine基本上应用C++写的。engine的存在是为了反对Dart Framework的运行。它提供了Flutter的外围API,包含作图、文件操作、网络IO、dar运行时环境等外围性能。 engine次要是通过dart:ui裸露给Flutter framework层的。 Flutter framework这一层是用户编程的接口,咱们的应用程序须要和Flutter framework进行交互,最终构建出一个应用程序。 Flutter framework次要是应用dart语言来编写的。 framework从下到上,咱们有最根底的foundational包,和构建在其上的 animation, painting和 gestures 。 再下面就是rendering层,rendering为咱们提供了动静构建可渲染对象树的办法,通过这些办法,咱们能够对布局进行解决。 接着是widgets layer,它是rendering层中对象的组合,示意一个小挂件。 最初是Material和Cupertino库,这些库应用widegts层中提供的小部件,组合成了不同格调的控件集。 Flutter framework就是这样一层层的构建起来的。 当然,下面的embedder和engine属于比拟底层的货色,咱们只须要晓得Flutter有这么一个货色,是这么应用的即可。 真正和咱们程序员相干的,就是Flutter framework了。因为咱们在编写代码的过程中,须要和Flutter framework打交道。 接下来,咱们重点关注下Flutter framework中的几个外围局部。 WidgetsWidgets翻译成中文就是小插件的意思。Widgets是Flutter中用户界面的根底。你在flutter界面中可能察看到的用户界面,都是Widgets。 当然这些大的Widgets又是由一个个的小的Widgets组成的,而这些小的Widgets又是由更小的Widgets组成的。 这样就形成了Widgets的档次依赖构造,这些层次结构的关联关系是通过Widget中的child Widget进行关联的。 在这种层次结构中,子Widgets能够共享父Widgets的上下文环境。 Flutter中的Widgets跟其余语言中的相似的Widgets组合有什么不同呢? 他们最大的不同是,Flutter中的Widgets更多,每个Widgets专一的性能更小。即使是一个很小很小性能,在Flutter中都能够找到与之对应的Widgets。 这样做的益处就是,你能够应用不同的,十分根底的Widgets任意组合,从而构建出非常复杂的,个性化的大的Widgets。 当然,它的毛病也非常明显,就是代码外面的Widgets太多了,导致代码中的层级构造特地的多,可能会看的目迷五色。 举个简略的例子,Container是flutter提供的一个根本的容器Widget,咱们通常这样来应用它: Container( constraints: BoxConstraints.expand( height: Theme.of(context).textTheme.headline4!.fontSize! * 1.1 + 200.0, ), padding: const EdgeInsets.all(8.0), color: Colors.blue[600], alignment: Alignment.center, child: Text('Hello World', style: Theme.of(context) .textTheme .headline4! .copyWith(color: Colors.white)), transform: Matrix4.rotationZ(0.1), )咱们向Container中传入了constraints,padding,color,alignment,child,transform等信息。 ...

August 15, 2022 · 3 min · jiezi

关于flutter:Flutter学习第三课侧边栏Drawer的抽屉组件简单用法

一:第一步:主界面链接到MainApp() import 'package:flutter/material.dart';import 'package:flutter_first/main/main_app.dart';void main() { runApp(MyApp());}class MyApp extends StatelessWidget{ @override Widget build(BuildContext context) { return new MaterialApp( title: "Drawer抽屉组件示例", home: new MainApp(), ); }}二:抽屉组件界面 import 'package:flutter/material.dart';class MainApp extends StatefulWidget { const MainApp({Key? key}) : super(key: key); @override State<MainApp> createState() => _MainAppState();}class _MainAppState extends State<MainApp> { @override Widget build(BuildContext context) { return new Scaffold( appBar: AppBar( title: Text("Drawer抽屉组件示例"), ), drawer: Drawer( child: ListView( children: <Widget>[ //设置用户信息,如头像,用户名,Emails UserAccountsDrawerHeader( accountName: new Text("Rocky_ruan"), accountEmail: new Text("ruanzhiqiang_cnstrong@163.com"), //设置以后用户头像 currentAccountPicture: new CircleAvatar( backgroundImage: new AssetImage("lib/assets/images/photo.jpg"), ), onDetailsPressed: () {}, //属性原本是用来设置以后的其余头像 otherAccountsPictures: <Widget>[ new Container( child: ClipOval( child: Image.asset("lib/assets/images/photo.png", height: 200, width: 200, fit: BoxFit.cover)), ), ], ), ListTile( leading: new CircleAvatar( child: Icon(Icons.color_lens), ), title: Text("共性打扮"), ), ListTile( leading: new CircleAvatar( child: Icon(Icons.photo), ), title: Text("我的相册"), ), ListTile( leading: new CircleAvatar( child: Icon(Icons.wifi), ), title: Text("免流量特权"), ) ], ), ), ); }}这外面用到了图片资源是从assets资产目录拿到了要建设一个资产目录同时pubspec.yaml文件下要增加assets目录配置 ...

August 15, 2022 · 1 min · jiezi

关于flutter:Flutter-学习第二课Dio网络请求简单用法和数据适配

主页main.dart import 'package:flutter/material.dart';import 'package:flutter_first/pages/good_list_page.dart';void main() { runApp(MyApp());}class MyApp extends StatelessWidget{ @override Widget build(BuildContext context) { return MaterialApp( title: "Dio申请", home: Scaffold( appBar: AppBar( title: Text('Dio申请'), ), body: GoodListPage(), ), ); }}二:数据模型层good_list_model.dart //商品列表数据模型class GoodListModel { //状态码 String? code; //状态信息 String? message;//商品列表数据 late List<GoodModel> data; //构造方法,初始化时传入空数组[]即可 GoodListModel({required this.data,this.code, this.message}); //通过传入json数据转换成数据模型 GoodListModel.fromJson(Map<String, dynamic> json) { code = json['code']; message = json['message']; if (json['data'] != null) { data = <GoodModel>[]; //循环迭代Json数据冰将其每一项数据转成GoodModel json['data'].forEach((v) { data.add(GoodModel.fromJson(v)); }); } } //将数据模型转成Json Map<String, dynamic> toJson() { final Map<String, dynamic> data = Map<String, dynamic>(); data['code'] = this.code; data['message'] = this.message; if (this.data != null) { data['data'] = this.data.map((v) => v.toJson()).toList(); } return data; }}class GoodModel { //商品图片 String? image; //原价 int? oriPrice;//现有价格 int? presentPrice; //商品名称 String? name;//商品Id String? goodsId;//构造方法 GoodModel( {this.image, this.oriPrice, this.presentPrice, this.name, this.goodsId});//通过传入的Json数据转换成数据模型 GoodModel.fromJson(Map<String, dynamic> json) { image = json['image']; oriPrice = json['oriPrice']; presentPrice = json['presentPrice']; name = json['name']; goodsId = json['goodsId']; }//将数据模型转成Json Map<String, dynamic> toJson() { final Map<String, dynamic> data = new Map<String, dynamic>(); data['image'] = this.image; data['oriPrice'] = this.oriPrice; data['presentPrice'] = this.presentPrice; data['name'] = this.name; data['goodsId'] = this.goodsId; return data; }}三:数据申请Diohttp_service.dart ...

August 12, 2022 · 3 min · jiezi

关于flutter:Flutter学习第一课两个页面的计数同步增加获取

两个页面的计数同步减少获取import 'package:flutter/material.dart';import 'package:provider/provider.dart';void main() { runApp(MyApp());}class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { //应用MultiProvider能够创立多个顶层共享数据 return MultiProvider( providers: [ChangeNotifierProvider(create: (_) => Counter())], child: MaterialApp( title: "Provider示例", home: FirstPage(), ), ); }}//第一个页面class FirstPage extends StatefulWidget { const FirstPage({Key? key}) : super(key: key); @override _FirstPageState createState() => _FirstPageState();}class _FirstPageState extends State<FirstPage> { late Counter counter; @override Widget build(BuildContext context) { counter = context.watch<Counter>(); return Scaffold( appBar: AppBar( title: Text("第一个页面"), actions: <Widget>[ FlatButton( child: Text("下一页"), //路由跳转至第二页 onPressed: () => Navigator.push(context, MaterialPageRoute(builder: (context) { return SecondPage(); })), ), ], ), body: Center( //获取计数器中的count的值 child: Text("${Provider.of<Counter>(context).count}"), ), floatingActionButton: FloatingActionButton( onPressed: () { //调用数据模型中的increment办法更改数据 counter.increment(); // context.read<Counter>().increment(); //Provider.of<Counter>(context,listen: false).increment(); }, child: Icon(Icons.add), ), ); }}//第二页class SecondPage extends StatelessWidget { @override Widget build(BuildContext context) { //Provider.of<Counter>(context,listen: true);等价于context.watch<Counter>().increment(); //Provider.of<Counter>(context,listen: false);等价于context.read<Counter>().increment(); Counter counter =Provider.of<Counter>(context,listen: true); print("我是用来打印的哦"); return Scaffold( appBar: AppBar( title: Text("第二个页面"), ), body: Center( //获取计数器中的count值 child: Text("${counter.count}"), ), floatingActionButton: FloatingActionButton( onPressed: () { //调用数据模型中的increment办法更改数据 context.read<Counter>().increment();//第一种形式 // Provider.of<Counter>(context,listen: false).increment();//第二种形式 // counter.increment();//第三种形式 }, child: Icon(Icons.add), ), ); }}//计数器类Counter 即为数据Model 实际上就是状态//Counter不仅存储了数据,还蕴含了更改数据的办法,并裸露相干的数据//当调用notifyListeners 时它会告诉所有的听众进行刷新class Counter with ChangeNotifier { //存储数据 int _count = 0; //提供内部可能拜访的数据 int get count => _count;//提供更改数据的办法 void increment() { _count++; //告诉所有的听众进行刷新 notifyListeners(); }}

August 11, 2022 · 1 min · jiezi

关于flutter:Flutter-新一代图形渲染器-Impeller

Flutter在2022年的Roadmap中提出须要重新考虑着色器的应用形式,打算重写图像渲染后端。最近该渲染后端 Impeller(叶轮)初见端倪,本文将介绍 Impeller 解决的问题、指标、架构和渲染细节。背景Flutter在过来一年多工夫解决了很多Jank问题,但着色器编译导致的Jank问题始终没有彻底解决。这里咱们先理解下什么着色器编译Jank。Flutter底层应用了skia做为2D图形渲染库,而skia外部定义了一套SkSL(Skia shading language),SkSL 属于 GLSL 变体。在Flutter的光栅化阶段,当第一次应用着色器时Skia会依据绘图命令和设施参数生成 SkSL,而后再将 SkSL 转换为特定后端(GLSL、GLSL ES 或 Metal SL)着色器,并在设施上编译为着色器程序。而编译着色器可能破费几百毫秒,导致数十帧的失落。定位着色器编译Jank问题能够查看trace信息是否有 GrGLProgramBuilder::finalize 调用。Flutter为了解决该问题,在Flutter 1.20 版本中为GL后端实现了SkSL预热机制,反对离线收集应用程序中应用的 SkSL 着色器并保留为json文件,而后把该文件打包到应用程序中,最终用户首次关上应用程序时预编译 SkSL着色器,从而缩小着色器编译 jank。随后,在 Flutter 2.5中反对了 iOS metal 着色器的预编译。Flutter gallery利用预热前后,在Moto G4上从~90ms缩小到~40ms,在iPhone 4s上从~300ms缩小到~80ms,性能晋升很显著。在Flutter官网提供了SkSL着色器预热后,社区常常提到的一些高频问题收集如下:Q1. 为什么不预编译用到的所有着色器?为了获得最佳性能,Skia GPU backend在运行时会依据一些参数(如绘图命令,设施型号等)动静生成着色器。这些参数的组合会生成大量的着色器,无奈在应用程序中预编译和内置。Q2. 不同设施上捕捉的 SkSL shader 通用吗?实践上,没有机制保障在一台设施上捕捉的 SkSL shader 在其余设施上也无效。实际上,(无限的)测试表明 SkSL shader 能体现的较好,即便在iOS上捕捉的 SkSL 利用到Android设施,或者模拟器上捕捉的SkSL利用到真机上。Q3. 为什么不创立一个超级着色器并仅编译一次?这样的着色器会十分大,实质上是从新实现 Skia GPU 性能。大shader须要更长的编译工夫,从而引入更多的 Jank。但SkSL着色器预热也存在本身的毛病和局限性: 利用包体积变大利用启动工夫变长,因为须要预编译 SkSL shader开发体验不敌对SkSL shader 的通用性无保障且不可预测以下工夫线列举了Flutter在解决Jank问题上的致力和停顿:对于着色器编译Jank问题,官网通过屡次尝试仍然无奈彻底解决,因而在2022年的roadmap中请明确提出要重新考虑应用着色器的形式,打算重写图像渲染后端。在2022年打算在iOS上将 Flutter 迁徙到新架构上,而后依据教训将该解决方案移植到其余平台上。最近,该图形渲染后端 impeller(叶轮)初见端倪,接下来让咱们看看 impeller有什么独特之处。 Impeller架构Impeller是为flutter量身定做的渲染器,目前处于早起原型阶段,仅实现了metal后端,反对iOS和Mac零碎。工程方面,他依赖了 flutter fml 和 display list,并实现了display list dispatcher 接口,能够容易的替换skia。Impeller被flutter flow子系统所应用,因而得名。Impeller外围指标: 可预测的性能:在编译时离线编译所有着色器,并依据着色器事后构建 pipeline state objects。可检测:所有的图形资源(textures、buffers、pipeline state对象等)都被追踪和标记。动画能够被捕捉并长久化到磁盘而不影响渲染性能。可移植:没有与特定的渲染API相绑定,着色器编写一次并在须要时转换。应用古代图形API:大量应用(但不依赖)古代图形API(如Metal和Vulkan)的个性。无效利用并发性:能够在多线程上散发单帧工作负载。impeller软件架构impeller大抵能够分为Compiler、Renderer,Entity、Aiks以及根底库Geomety和Base等几个模块。Compiler: host端工具,蕴含着色器 Compiler 和 Reflector。Compiler用于把 GLSL 4.60 着色器源码离线编译为特定后端的着色器(如MSL)。Reflector 依据着色器离线生成 C++ shader bindings,以在运行时疾速构建pipeline state objects (PSO)Renderer: 用于创立buffer、从shader bindings生成pipeline state objects、设置RenderPass、治理uniform-buffers、细分曲面、执行渲染工作等Entity:  用于构建2D渲染器,蕴含了着色器,shader bindings和pipeline state objectsAiks:  封装 Entity 以提供类 Skia API,长期存在,便于对接到 flutter flow ...

August 8, 2022 · 3 min · jiezi

关于flutter:Flutter-的-6-个最有用的-VS-Code扩展

1. Pubspec AssistPubspec Assist 是一个 Visual Studio Code 扩大,它容许您轻松地将依赖项增加到您的 Dart 和 Flutter 我的项目的 pubspec.yaml,所有这些都无需来到您的编辑器。 只需关上命令面板(默认状况下,Windows 上为 Ctrl+Shift+P,Mac 上为 ⌘+Shift+P)并搜寻“Pubspec Assist”。 2. Material Icon Theme 这个扩大为你的文件列表提供了丑陋的图标。如果文件是 JavaScript,那么它将在文件名旁边的资料款式中蕴含一个 JavaScript 图标。如果您更像是视觉开发人员,那么此扩大程序适宜您。它被数百万用户宽泛应用。 3. Awesome Flutter Snippets Awesome Flutter Snippets 是罕用的 Flutter 类和办法的汇合。它通过打消与创立小部件相干的大部分样板代码来进步您的开发速度。StreamBuilder 和 SingleChildScrollView 等小部件能够通过别离键入快捷方式 streamBldr 和 singleChildSV 来创立。 个性: 放慢开发速度打消样板反对简单的小部件(例如:Custom Clipper 和 Custom Paint)4. Bloc 您能够通过启动命令面板(查看 -> 命令面板)并运行输出命令名称来激活命令,或者您能够右键单击要在其中创立 bloc/cubit 的目录并从上下文中抉择命令菜单。 5. Error Lens ErrorLens 通过使诊断更加突出来加强语言诊断性能,在语言生成诊断的任何地位突出显示整行,并内联打印消息。 个性: 突出显示蕴含诊断的行将诊断作为文本附加到行尾在gutter显示图标在状态栏中显示音讯6. Json to Dart Model ...

August 7, 2022 · 1 min · jiezi

关于flutter:抢先体验-在浏览器里写-Flutter-是一种什么体验

Invertase 是一间位于英国的开源软件制作公司。次要构建对于开发者工具、SDK 等应用程序,早在 Flutter 2.2 的时候,Invertase 团队就开始帮忙构建和奉献 Firebase 相干的 Flutter 插件 (FlutterFire);在 Flutter 2.8 正式版公布的时候,文章里也介绍了他们和 Canonical 的单干:独特在 Linux 和 Windows 上开发最风行的 Flutter Firebase 插件。除此之外,他们还构建了很多开源产品,你能够在他们的 GitHub 主页上查看:github.com/invertase 昨天,Invertase 团队公布了一款新的产品「Zapp」,一个在浏览器里构建 Flutter 利用的 Web 利用: Zapp 服务反对应用任何 Pub 上的 package,也通过内置的 Dart 分析器提供语法高亮和主动实现等性能,与此同时也能够将你的工程代码分享给其他人,也能够像 VS Code 中一样应用命令面板执行操作,还有深色主题、调试、Git 代码治理、测试等性能。 配图来自 Zapp 的命令面板性能 目前 Zapp 正处于关闭测试期,任何人都能够申请加入 Zapp 的 EAP 打算,办法是关上 利用官网:zapp.run,并应用 GitHub 账户登陆,当收到 EAP 资格后,会收到电子邮件告诉。 有任何性能反馈能够在 Zapp 的 GitHub Issue 区 提出,期待社区成员们的试用报告和反馈!

July 15, 2022 · 1 min · jiezi

关于flutter:Flutter-Cupertino-教程如何构建外观和感觉原生的-iOS-应用

所有前端应用程序都应用某种设计零碎来帮忙用户更轻松地实现工作。他们可能会应用外部开发的定制设计零碎或成熟的设计零碎,例如 Material Design 或 Cupertino (iOS)。 Material Design 由 Google 开发,可用于开发 Android、iOS、Web 和桌面应用程序。 Cupertino 由 Apple 开发。它基于 Apple 的人机界面指南,该指南实现了以后的 iOS 设计语言。 Flutter SDK 附带 Material 和 Cupertino 小部件库,用于开发一个外观和感觉都实用于任一平台的应用程序。 你依然能够仅仅应用Material widgets库来构建一个应用程序。然而,如果你想建设一个看起来像规范iOS格调的应用程序,你应该强烈思考应用Cupertino库。 在本教程中,咱们将构建一个底部有三个选项卡的简略应用程序;通话、聊天和设置。 在通话标签上,咱们将增加简略的导航栏;聊天标签将显示会员列表,并容许最终用户搜寻任何会员;在设置标签上,咱们将应用各种Cupertino格调的部件来建设设置页面。 这是最终应用程序的外观: 1.创立一个简略的页面让咱们先创立一个简略的页面,在顶部显示页面题目,在两头显示 "Hello "信息。要建设这样一个页面,你必须删除新创建的我的项目的所有内容,用上面的代码代替它: import 'package:flutter/cupertino.dart';import 'package:flutter/material.dart';import 'package:flutter/services.dart';import 'simple_page.dart';void main() { WidgetsFlutterBinding.ensureInitialized(); SystemChrome.setPreferredOrientations([ DeviceOrientation.portraitUp, DeviceOrientation.portraitDown, ]).then((value) => runApp(MyApp())); runApp(const MyApp());}class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); // This widget is the root of your application. @override Widget build(BuildContext context) { // 1 <-- SEE HERE return CupertinoApp( // 2 <-- SEE HERE theme: CupertinoThemeData(brightness: Brightness.light), home: CupertinoSimpleHomePage(), ); }}class CupertinoSimpleHomePage extends StatefulWidget { const CupertinoSimpleHomePage({Key? key}) : super(key: key); @override _CupertinoSimpleHomePageState createState() => _CupertinoSimpleHomePageState();}class _CupertinoSimpleHomePageState extends State<CupertinoSimpleHomePage> { @override Widget build(BuildContext context) { // 3 <-- SEE HERE return const CupertinoPageScaffold( // 4 <-- SEE HERE navigationBar: CupertinoNavigationBar( middle: Text('Chat App'), ), child: Center( child: Text('Hi'), ), ); }}代码阐明: ...

July 14, 2022 · 4 min · jiezi

关于flutter:初识-Flutter

运行篇flutter SDK 下载https://docs.flutter.dev/deve...你能够抉择任意一种形式进行下载,包含不限于 git 和 间接下载安装包 我的项目新建首先关上vscode 新建一个空的 或者 open 一个我的项目工程文件夹关上vscode 的终端,在终端上输出:flutter create flutter_app01 ,创立3.终端输出命令 flutter run 运行 全局设置 flutter命令行输出vim ~/.bash_profile编辑模式关上 设置:export PUB_HOSTED_URL=https://pub.flutter-io.cn //国内用户须要设置export FLUTTER_STORAGE_BASE_URL=https://storage.flutter-io.cn //国内用户须要设置export PATH=PATH_TO_FLUTTER_GIT_DIRECTORY/flutter/bin:$PATH命令行输出source ~/.bash_profile现有我的项目运行flutter doctorflutter run参考:https://doc.flutterchina.club...

July 11, 2022 · 1 min · jiezi

关于flutter:mac-flutter环境搭建

明天在mac上搭建flutter的第一个Android开发环境以及运行demo。 1.下载Android studio(以下简称AS),到官网下载最新版本即可。 2.关上AS,在AS的Tools菜单下,关上SDK Manager,在SDK Platforms装置一个版本的SDK。而后在SDK Tools菜单下Android SDK Command-line Tools(latest),装置这些是为了解决之后可能遇到的问题。 3.为AS装置flutter插件,关上插件首选项 (Preferences>Plugins),搜寻flutter下载安装重启AS即可。 4.AS的局部到此为止,上面开始下载flutter。到官网下载最新版,https://docs.flutter.dev/deve...,下载实现后解压。 5.增加flutter相干工具到path中 export PATH=`pwd`/flutter/bin:$PATH 6.命令行运行,flutter doctor,没有报错即flutter环境搭建实现。 7.接下来就是创立第一个flutter利用了。 Android Studio: 为Flutter提供残缺的IDE体验.创立新利用抉择 File>New Flutter Project抉择 Flutter application 作为 project 类型, 而后点击 Next输出项目名称 (如 myapp,名字不能用驼峰命名), 而后点击 Next点击 Finish期待Android Studio装置SDK并创立我的项目.上述命令创立一个Flutter我的项目,我的项目名为myapp,其中蕴含一个应用Material 组件的简略演示应用程序。在我的项目目录中,您应用程序的代码位于 lib/main.dart.运行应用程序定位到Android Studio 工具栏:Main IntelliJ toolbar在 target selector 中, 抉择一个运行该利用的Android设施. 如果没有列出可用,请抉择 Tools>Android>AVD Manager 并在那里创立一个在工具栏中点击 Run图标, 或者调用菜单项 Run > Run.如果一切正常, 您应该在您的设施或模拟器上会看到启动的应用程序:Starter App on Android可能遇到的问题: 1.Cannot resolve symbol 'FlutterActivity'解决办法:AndroidStudio中,project视图中,右键android,抉择 Flutter-->Open Android Module In Android Studio,即可在Android视图看到构建过程,期待一会就ok了 ...

June 27, 2022 · 1 min · jiezi

关于flutter:基于-Flutter-3x-实战跨平台混合开发网盘分享

download:基于 Flutter 3.x 实战跨平台混合开发网盘分享再次意识 WebAssembly简略地说,Wasm 是一个编译指标,能够应用大概 30 种语言编写的代码,应用特定于 WebAssembly 的工具来编译它,将其编译为 .wasm 文件,目前最风行的针对 Wasm 的语言是 C、C++ 和 Rust(即因为它们本人治理内存并且不须要垃圾收集器)。对 Go、Python 和 JavaScript 生态系统的反对也在快速增长。编译生成的.wasm 文件能够在浏览器或服务器上。Wasm 文件蕴含虚拟机能够读取的二进制指令,并且因为 Wasm 以虚拟机为指标,因而它实用于许多芯片架构,它以风行硬件的最小公分母为指标,堆栈机,这是它区别于其余产生二进制代码的指标的中央。Wasm 最后是为浏览器构建的,然而随着技术的成熟,在服务器端看到了越来越多的用例。本文再次介绍 WebAssembly 的劣势及利用场景,并通过示例意识其我的项目开发的过程,点击查看代码。 领有什么劣势Wasm 容许应用相熟的语言编写代码并在任何中央运行它。 更快的启动工夫在服务器上,Wasm 能够实现比 Docker 容器快 10-100 倍的冷启动工夫,因为它不须要为每个容器创立一个 OS 过程。在浏览器中,解码 Wasm 比解析、解释和优化 JavaScript 更快,因而 Wasm 代码在浏览器中的执行速度比 JavaScript 更快。 近乎原生的性能对于 Wasm 的性能细节存在一些争议,但它的劣势在于容许用户将其应用程序的计算密集型局部封装到较低级别的语言。 Wasm 的许多性能劣势来自于它(它是 Wasm 代码)被构建为尽可能靠近本机机器代码这一事实。 轻量级Wasm 二进制文件体积小,因而只应用大量带宽,通常比浏览器中的穿插编译 JavaScript 破费更少的工夫通过网络传输。便捷通用任何 Wasm 运行时都能够运行任何 Wasm 代码(只管并非所有运行时都反对所有 Wasm 扩大,即不同的 WASI 接口类型)。大多数浏览器都反对 WebAssembly,并且在服务器端(WasmEdge、Wasmtime 等)有许多运行 Wasm 代码的运行时。鉴于浏览器和服务器(以及硬件)对 Wasm 的广泛支持,它是具备可移植的,并且也十分通用,大概 30 种语言能够编译或在其中执行(C、C++、Rust、Python、Go、AssemblyScript、JavaScript等等)。 ...

June 24, 2022 · 2 min · jiezi

关于flutter:基于-Flutter-3x-实战跨平台混合开发超清无密

基于 Flutter 3.x 实战跨平台混合开发点击下载:网盘链接以短视频APP为例,疾速上手原生/Flutter 混合开发Flutter 3已公布,跨平台支持性更好。本课程会手把手教你用简略、高效且通用的形式,将原生我的项目迁徙成一个Flutter/原生混合开发的我的项目,从双平台开发转变为跨平台开发,大大提高我的项目开发效率。 学好 Flutter,它的灵便、高效,将在你的工作实际中浮现极大威力。 适宜人群挪动端开发者心愿把握跨平台开发的学员对Flutter感兴趣的程序员技术储备不须要很深的Android开发技术但须要相熟Java或者某一门面向对象的开发语言环境参数Dart语言 2.XFlutter 3.X章节目录: 第1章 课程介绍与学习指南 试看2 节 | 11分钟本章次要针对课程做整体介绍,提出一些好的学习办法与领导倡议。收起列表图文:1-1 课前必读(不读错过一个亿)视频:1-2 Flutter3.x实战APP--课程导学 (10:37)试看第2章 Flutter整体介绍 试看11 节 | 85分钟从多个维度介绍Flutter3.0,让大家对Flutter有一个理性的意识,而后手把手带你疾速上手Flutter。并展现本课程案例的实现成果,带着指标去学习,事倍功半。收起列表视频:2-1 Flutter技术倒退概览--本章导学 (02:41)视频:2-2 Flutter技术倒退概览--整体介绍 (04:20)视频:2-3 Flutter技术倒退概览--倒退历程 (03:28)视频:2-4 Flutter的整体框架结构介绍 (06:54)视频:2-5 为什么抉择Dart语言 (09:01)视频:2-6 Dart语言个性 (05:36)视频:2-7 Dart的线程治理及框架 (08:59)视频:2-8 Dart的异步编程- (11:34)试看视频:2-9 工程构造 (09:51)视频:2-10 布局形式及差别 (19:43)视频:2-11 Flutter技术倒退概览--本章总结 (02:11)第3章 开发工具装置及环境搭建5 节 | 46分钟搭建开发环境,晋升高发效率。可能迅速上手开发第一个Flutter 跨端App收起列表视频:3-1 开发工具装置及环境搭建--本章导学 (03:03)视频:3-2 Flutter几种常见开发工具比照介绍 (04:43)视频:3-3 Flutter SDK下载及装置 (22:00)视频:3-4 Android Studio装置及配置 (13:21)视频:3-5 开发工具装置及环境搭建--本章总结 (02:21)第4章 Flutter实现混合式开发10 节 | 100分钟解说Flutter与原生互相调用,实现混合开发模式。可能实用于一个新我的项目也能够对以前的原生我的项目进行加强革新,当初大厂相对支流、最受欢迎的开发模式收起列表视频:4-1 Flutter混合开发--本章导学 (02:38)视频:4-2 混合开发技术简介 (11:02)视频:4-3 混合开发项目管理形式 (03:43)视频:4-4 Flutter工程模式 (07:00)视频:4-5 BasicMessageChannel根底音讯通道(一) (19:40)视频:4-6 BasicMessageChannel根底音讯通道(二) (19:05)视频:4-7 EventChannel事件通道 (11:01)视频:4-8 混合开发的要害MethodChannel办法通道(一) (14:00)视频:4-9 混合开发的要害MethodChannel办法通道(二) (07:26)视频:4-10 Flutter混合开发--本章总结 (04:22)第5章 Flutter3.x新个性6 节 | 34分钟解说最新的Flutter 3.x新个性。教你应用一套代码运行6大平台,分享更多实用小工具及应用技巧帮忙你晋升App品质,高效开发的同时拉满App的用户体验。收起列表视频:5-1 Flutter3.x新个性--本章导学 (01:24)视频:5-2 Flutter3.x简介 (03:23)视频:5-3 Flutter3.x反对多平台运行实战演示 (17:51)视频:5-4 Flutter3.x无障碍性能反对的开发 (07:39)视频:5-5 Flutter3.x新增dev tool加强 (01:13)视频:5-6 Flutter3.x新个性--本章总结 (02:19)第6章 Flutter 编译原理及多场景的调试优化技术7 节 | 63分钟从Flutter底层编译原理角度介绍Flutter 3.x中几种最罕用的调试形式,用理论例子联合讲师多年大型项目经验总结解析每种调试形式的优劣及实用场景。让大家在实战中遇到异样问题可能应答自若,轻松解决,有能力为同我的项目其余成员解决疑难杂症,助你在工作开发中更蛟龙得水。...收起列表视频:6-1 Flutter代码调试--本章导学 (04:34)视频:6-2 Flutter 底层编译原理及打包形式 (05:16)视频:6-3 通过断点的形式深刻Dart代码运行时 (16:52)视频:6-4 基于JIT热更新的高效Log调试 (05:58)视频:6-5 通过Inspector深刻优化UI布局 (13:57)视频:6-6 性能面板的应用技巧及Dart内存调优 (08:24)视频:6-7 Flutter代码调试--本章总结 (07:04)第7章 实战--混合式开发框架搭建及我的项目架构设计8 节 | 86分钟本章次要实现App首页我的项目的开发,可能让你启动属于本人的新我的项目,肉眼可见的播种成长。收起列表视频:7-1 首页框架搭建--本章导学 (03:56)视频:7-2 实战-- 混合开发我的项目创立 (09:10)视频:7-3 实战--实现页面导航治理(一) (06:51)视频:7-4 实战--实现页面导航治理(二) (17:33)视频:7-5 实战--实现页面导航治理(三) (17:37)视频:7-6 实战--实现页面导航治理(四) (16:09)视频:7-7 实战--我的项目功能分析 (09:39)视频:7-8 首页框架搭建--本章总结 (04:38)第8章 实战-Android原生我的项目进行革新6 节 | 51分钟在放弃原有代码不变的前提下,用最简略的形式,将已有的原生我的项目革新成Flutter/原生混合式我的项目。开启多端跨平台开发模式,让原生与Flutter顺滑的互相调用,实现两种开发方式的一键切换。收起列表视频:8-1 Android原生我的项目革新--本章导学 (03:04)视频:8-2 原生我的项目现状剖析 (07:22)视频:8-3 原生开发流程解析 (08:16)视频:8-4 Flutter 覆盖面剖析 (11:50)视频:8-5 当Android遇到Flutter (15:11)视频:8-6 Android原生我的项目革新--本章总结 (04:25)第9章 实战--Flutter视频播放器封装及播放列表开发视频播放是本实战我的项目的外围性能,本章次要学习视频H264/H265编码格局,各种罕用封装格局以及视频中罕用的参数抉择。在视频播放性能根底上创立罕用的播放控件,随心定制一款属于本人的跨端视频播放器。第10章 实战--网络申请及数据解析框架——视频下载网络申请是每个App必不可少的一部分,本章次要学习Flutter网络申请形式并且手把手教你做框架封装,一次开发可能在其余App中轻松移植。第11章 实战--数据长久化与缓存结构设计——数据缓存本章次要学习本地长久化技术并减少缓存机制,优化性能的一些必要伎俩。第12章 实战--动画特效与评论列表开发——互动模块互动模块减少App的用户体验,减少用户时长,列表滑动渲染始终都是Android/iOS开发中常见的问题,本章应用Flutter一键解决。第13章 实战--瀑布列表——集体核心视频列表时下App最风行的款式,简直所有App都会蕴含瀑布流,本章次要学习大厂Flutter瀑布流的用法,同样能够做到移植性强第14章 实战--相机模块开发——上传视频本章次要学习调用原生物理设施,展现摄像头数据并实现照片保留。第15章 实战--Flutter 我的项目打包公布到此整个实战App曾经开发结束,学习如何做好最初一步,让你的App登上每个人的手机桌面。第16章 Flutter多段适配(挪动端、PC端及Web端)本章次要针对大屏——MAC/WINDOWS等零碎进行UI适配,学习多端适配的规定和设计模式。第17章 课程总结课程总结本课程继续更新中 ...

June 23, 2022 · 1 min · jiezi

关于flutter:flutterdatingtemplate

flutter_dating_templateflutter 版本的交友 app 模板,总计页面35个,测试数据基于 mockjs 创立。 疾速理解 迅速定位页面 ⚡ mock 数据拆散 - history_match - index.dart # 布局文件 - mock.dart # mock实例文件 不依赖于第三方 api, 基于 mockjs 本地创立测试数据,更加稳固 flutter 2.10.x 版本flutter --versionFlutter 2.10.4 • channel stable • https://github.com/flutter/flutter.gitFramework • revision c860cba910 (5 weeks ago) • 2022-03-25 00:23:12 -0500Engine • revision 57d3bac3ddTools • Dart 2.16.2 • DevTools 2.9.2所用插件及作用我的项目中所用的插件,均反对空平安。插件名作用flutter_native_splash设置启动页group_buttoncheckbox groupgetx路由治理dart_mockmock datascan扫描二维码局部截图 仓库地址:GitHub ...

June 17, 2022 · 1 min · jiezi

关于flutter:使用-DartPad-制作代码实践教程

DartPad 是一个开源的、在浏览器中体验和运行 Dart 编程语言的线上编辑器,指标是为了帮忙开发者更好地理解 Dart 编程语言以及 Flutter 利用开发。 DartPad 我的项目起始于 2015 年,最后只是一个在线的编译器,能够编译、剖析和显示 Dart 代码运行后果。前期次要进行过几次重要的改良: 2019 年 12 月,新版的 DartPad 公布,不仅推出了独立的拜访域名 (dartpad.dev),同时也反对运行 Flutter 利用 (通过网页展示)2020 年 4 月,CodePen 开始反对 Flutter 利用,其应用了与 DartPad 雷同的后端解决2020 年 10 月,DartPad 空平安版本上线,为开发者们提供空平安编译环境的 Dart SDK2021 年 5 月,DartPad 正式反对 Workshop 格局内容2021 年 11 月,DartPad 反对 SDK 版本切换 (Stable / Beta / Old),并引入一些罕用的 package,比方 Google 字体 (google_fonts)、bloc、http、intl,并打算在前期一直引入新的 package,目前曾经反对了 87 个 packageDartPad 用户大部分是学习 Dart 编程语言的开发者,能够免于配置本地开发环境间接测试 Dart 编程语言个性。另一个场景是用于代码片段的分享,这能够是一个小性能,比方 Flutter API 文档里介绍某个 widget 时就会内嵌一个 DartPad 向开发者展现这个 widget 理论运行时的成果,代码片段也能够是一个最小可复现的 bug 代码,不便在形容问题的时候,同时将代码分享给 debug 的开发者。 ...

June 14, 2022 · 2 min · jiezi

关于flutter:译-一文带你学会全部Flutter的Provider

原文在这里。 尽管官网Flutter站点(状态治理入门app)说Provider“非常容易了解”,我(作者)可不这么认为。我想是因为Provider的品种有点多: ProviderListenableProviderChangeNotifierProviderValueListenableProviderStreamProviderFutureProviderMultiProviderProxyProviderChangeNotifierProxyProvider更多我只想用最简略的办法治理我的app的状态。为什么有这么多的抉择?我应该用哪一个呢?从哪里开始呢? 本文的目标就是帮你了解次要的Provider类型是怎么用的。我会给每一个Provide类型一个简略的例子。帮忙你了解,之后你就能够本人决定用哪个来治理你的app的状态了。 筹备我的例子会应用这样的布局 也就是: 那个“Do something”按钮代表扭转app状态的事件。那个“Show something”文本Widget代表显示app state的UI右边的绿色方框和左边的蓝色的方框代表了widget树的不同局部。用来强调一个事件和与这个事件所更改的状态相干的更新的UI。这里是代码: import 'package:flutter/material.dart';void main() => runApp(MyApp());class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar(title: Text('My App')), body: Row( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Container( padding: const EdgeInsets.all(20), color: Colors.green[200], child: RaisedButton( child: Text('Do something'), onPressed: () {}, ), ), Container( padding: const EdgeInsets.all(35), color: Colors.blue[200], child: Text('Show something'), ), ], ), ), ); }}这些例子须要你装置Provider包 ...

June 8, 2022 · 6 min · jiezi

关于flutter:Flutter与webview通信桥梁开发

最近业务有需要须要在flutter内应用webview进行内嵌H5进行展现,此时须要波及到H5与flutter之间额通信问题。比方发送音讯或者H5调用Flutter的相机等等 webview选型这里咱们应用官网保护的插件webview_flutter 如何通信?webview在初始化的时候须要向容器内注册一个全局办法供H5进行调用 WebView( initialUrl: 'https://flutter.dev', javascriptMode: JavascriptMode.unrestricted, javascriptChannels: <JavascriptChannel>{ _toasterJavascriptChannel(context), } .... ....)JavascriptChannel _toasterJavascriptChannel(BuildContext context) { return JavascriptChannel( name: 'Toaster',//注册一个名字为Toaster的全局js办法 onMessageReceived: (JavascriptMessage message) { //解决业务的代码逻辑 print(message) });}H5发送音讯给flutterH5发送音讯采纳xxxx.postMessage模式,留神这里对象须要JSON.stringify Toaster.postMessage( JSON.stringify({ name: 'tom', age: 12 }));flutter发送音讯给H5须要调用runJavascript办法,咱们能够在H5中申明一个全局windows办法 window.globalCallback = function (data) { console.log(data)};flutter发送采纳runJavascript模式 WebViewController!.runJavascript('globalCallback(123)');//如果是对象也须要json.encode序列化交换群

June 2, 2022 · 1 min · jiezi

关于flutter:Flutter-图片库重磅开源

作者:新宿 背景去年,闲鱼技术团队新一代图片库 PowerImage 在通过一系列灰度、问题修复、代码调优后,已全量稳固利用于闲鱼。 绝对于上一代 IFImage,PowerImage 通过进一步的演进,适应了更多的业务场景与最新的 flutter 个性,解决了一系列痛点:比方,因为齐全摈弃了原生的 ImageCache,在与原生图片混用的场景下,会让一些低频的图片反而占用了缓存;比方,咱们在模拟器上无奈展现图片;比方咱们在相册中,须要在图片库之外再搭建图片通道。 详情可浏览:《Flutter 图片库高燃新退场》 PowerImage相干链接: GitHub:(✅star) https://github.com/alibaba/po... Flutter pub:(✅like) https://pub.dev/packages/powe... 简介PowerImage 是一个充分利用 native 原生图片库能力、高扩展性的flutter图片库。咱们奇妙地将外接纹理与 ffi 计划组合,以更贴近原生的设计,解决了一系列业务痛点。 能力特点反对加载 ui.Image 能力。在基于外接纹理的计划中,应用方无奈拿到真正的 ui.Image 去应用,这导致图片库在这种非凡的应用场景下无能为力。反对图片预加载能力。正如原生precacheImage一样。这在某些对图片展现速度要求较高的场景下十分有用。新增纹理缓存,与原生图片库缓存买通!对立图片缓存,防止原生图片混用带来的内存问题。反对模拟器。在 flutter-1.23.0-18.1.pre之前的版本,模拟器无奈展现 Texture Widget。欠缺自定义图片类型通道。解决业务自定义图片获取诉求。欠缺的异样捕捉与收集。反对动图。(来自淘特的PR)Flutter 原生计划在介绍新计划开始之前,先简略回顾一下 flutter 原生图片计划。 原生 Image Widget 先通过 ImageProvider 失去 ImageStream,通过监听它的状态,进行各种状态的展现。比方frameBuilder、loadingBuilder,最终在图片加载胜利后,会rebuild 出 RawImage,RawImage 会通过 RenderImage 来绘制,整个绘制的外围是 ImageInfo 中的 ui.Image。 Image:负责图片加载的各个状态的展现,如加载中、失败、加载胜利展现图片等。\ImageProvider:负责 ImageStream 的获取,比方零碎内置的 NetworkImage、AssetImage 等。ImageStream:图片资源加载的对象。在梳理 flutter 原生图片计划之后,咱们发现是不是有机会在某个环节将 flutter 图片和 native 以原生的形式买通? 新一代计划咱们奇妙地将 FFi 计划与外接纹理计划组合,解决了一系列业务痛点。 FFI正如结尾说的那些问题,Texture 计划有些做不到的事件,这须要其余计划来互补,这其中外围须要的就是ui.Image。咱们把 native 内存地址、长度等信息传递给 flutter 侧,用于生成ui.Image。 首先 native 侧先获取必要的参数(以 iOS 为例): ...

June 2, 2022 · 2 min · jiezi

关于flutter:参与-2022-第二季度-Flutter-开发者调查

2022 Google I/O 大会正式落下帷幕,Flutter 作为 14 个开发者产品和平台中的一款,吸引了来自寰球的很多开发者们的关注。随着全国很多中央曾经进入冬季,Flutter 往年第二季度的开发者考察也如约而至。在此,咱们特地邀请大家 参加本次开发者考察,本次考察自今日正式开始,并于一周之后截止。 Flutter 3 和 Dart 2.17 的公布,让 Flutter 从挪动端和 Web 端,正式来到了 对桌面端的稳固反对;Flutter 往年也连续了去年的“传统”,公布了一个联合了 Flutter 和 Firebase 的 Web 利用「I/O 弹球游戏」,咱们也看到社区的成员们玩儿的不可开交。随同着和 Firebase 团队的深刻单干,当初 Flutter 曾经正式成为 Firebase 官网反对的平台之一 了。与此同时,除了在利用开发上可能让开发者得心应手之外,Flutter 还拓展和摸索了 新的应用场景——「休闲小游戏」,这一类「游戏」有点相似「利用」,比方棋牌、消消乐等,从技术角度说,这类游戏领有「利用」一样的设计和逻辑,并不像大型游戏利用一样须要投入大量资源,因而,「休闲小游戏」十分值得利用开发者们尝试。为此,Flutter 团队公布了 Flutter 休闲游戏工具包 (Casual Game Toolkit),帮忙开发者拓展更多新的业务和方向。 随着 Flutter 产品逐步走向成熟,越来越多的不同规模的团队、公司、组织开始应用 Flutter 构建,从微信 (WeChat) 等 社交利用,到 Betterment 和 Nubank 等 金融和银行类利用,再到 SHEIN 和 trip.com 等 商旅利用 以及 Fastic、Tabcorp 等 生存形式类利用,还有 My BMW 此类的 硬件连贯类利用,最初是巴西 政府等公共机构 的官网利用等,Flutter 在这些细分畛域也在大放异彩。在本次 I/O 大会的这个重要工夫节点上,Flutter 团队特地公布了 字节跳动外部各个团队和产品应用 Flutter 的视频,字节跳动对 Flutter 的应用包含娱乐、企业、行业利用,从挪动端到 Web 端,再到硬件产品上。字节跳动也把 Flutter 布局和定位为公司多平台开发策略的外围。 ...

May 27, 2022 · 1 min · jiezi

关于flutter:报名开启|和你约定在-Google-应用出海指南针

Google 谷歌公布的《2021 挪动利用全球化指南》报告中提到,在挪动互联网高度浸透的当下,寰球用户爆发进去的宽泛需要为中国新生代创业者带来了微小的历史时机。过来十年,依靠于技术和人才劣势,中国企业在全球化过程中取得了长足的倒退。 依据 App Annie (data.ai) 公布的报告,过来 10 年,中国开发者 在寰球利用下载市场份额 增长了将近一倍。依据 Statista 的公布统计报告,2021 年,寰球利用下载数量 超过 2300 亿次,2015 - 2022 年中国手游海内市场支出逐年攀升,2022 年将达到 798.4 亿元人民币。 面向这样广大的市场前景,到海内市场寻找本人的潜在客户群体成为很多开发者们的抉择,Google 为国内的中小型手游和利用公司推出了 Google 利用出海指南针 打算,每一期内容均围绕 开发、增长、营利 为开发者带来干货满满的分享,往年举办的「利用出海指南针」第五期,为期两个月、每月为一个阶段,通过直播的形式在线上举办,现已 开启报名通道: △ 能够 点击这里,或者扫描上方二维码报名加入 预期播种本次流动并非全部都是技术内容分享,但对于开发者来说,把握和了解利用的出海经营技巧和实际,能够帮忙你更好地理解利用开发全生命周期以及裁减与产品相干技能点,也同时能够帮忙扩大视线,全面理解寰球市场的利用/游戏经营状况。 或者你能够 将本流动邀请转发给公司/团队里负责市场经营、优化投放的共事,这个流动对曾经有利用在海内市场,或者将来打算拓展海内市场业务的公司/团队十分有帮忙。 流动工夫安顿 本期利用出海指南针流动离报名截止工夫 (6月5日) 只剩下 不到两周的工夫 了,请各位感兴趣的开发者们抓紧时间报名。本期流动为期两个月,每个月为一个阶段,别离是入门周和进阶周阶段,每天直播工夫是 14:00 - 16:30,具体安顿如下: 入门周 (6 月 14 日 - 6 月 16 日) 的主题是:从零到一,谷歌助力开启全新价值挖掘之旅,三天、每天两个半小时的直播流动将别离是: Day 1 开发日 Google Play 团队和 Google Play 政策团队分享产品性能更新、最新趋势;Day 2 成长日 Google Ads 团队带你解析趋势前瞻,理解预注册、账户设置、市场剖析工具等;Day 3 营利日Google AdMob 团队和你独特摸索市场新机会点,理解新赛道、新产品、新政策。进阶周 (7 月 12 日 - 7 月 13 日) 的主题是:谷歌带你更深刻地探讨利用与游戏出海“神秘”,两天干货满满的直播流动内容将别离是: ...

May 26, 2022 · 1 min · jiezi

关于flutter:一起看-IO-Flutter-3-更新详解

作者 / Kevin Jamaul Chisholm, Technical Program Manager for Dart and Flutter at Google 又到了 Flutter 稳定版公布工夫,咱们无比骄傲地发表推出 Flutter 3 !仅 3 个月前,咱们发表了 Flutter 对 Windows 的反对。当初,咱们再次怀着冲动的情绪发表,继 Windows 之后,Flutter 现已稳固反对 macOS 和 Linux! 咱们总计合并了 5,248 条 PR,感激各位 Flutter 贡献者的辛勤工作! 此版本中激动人心的降级包含: 更新了 Flutter 对 macOS 和 Linux 的反对,性能失去了显著晋升,针对挪动设施和 web 端的更新,以及诸多其余性能!此外,咱们还带来了对于缩小对旧版 Windows 提供反对的音讯,以及几条重大变更。上面让咱们直奔主题吧! 全桌面平台生产就绪Linux 和 macOS 平台的反对已进入稳固状态,内含下列性能: 级联菜单和 macOS 零碎菜单栏反对当初您能够应用 PlatformMenuBar widget 在 macOS 上创立平台渲染的菜单栏,反对插入仅限该平台应用的菜单,并管制 macOS 利用菜单中的显示内容。 △ 级联菜单示意 残缺反对全桌面平台多国文本输出全副三种桌面平台残缺反对多国文本输出,包含应用文本 输入法编辑器 (IME) 的语言,如中文、日文和韩文。同时反对第三方输入法,如搜狗 (Sogou)、谷歌日文输入法 (Google Japanese Input) 等。 ...

May 25, 2022 · 3 min · jiezi

关于flutter:字节跳动的多平台绽放秘诀-Flutter-开发者故事

字节跳动旗下经营着一系列胜利的用户产品、企业应用以及服务,笼罩信息、教育、娱乐等不同畛域。随着产品阵容的一直倒退,传统的原生双平台开发曾经难以满足团队更高效、更灵便、更精美,以及更多样的产品研发需要。Google 首次公布 Flutter 的时候,团队就果决决定用手上的 iOS 和 Android 利用来测试其跨平台开发能力,而 Flutter 也用不逊于原生框架的性能体现和极高的生产力迅速驯服了团队成员们的心。 https://www.bilibili.com/vide... Flutter 领有令人难以置信的超高效率,与原生双端开发相比,Flutter 为咱们的团队节俭了大概 1/3 的开发工夫。 —— 董岩, 字节跳动 Flutter Infra 团队负责人 多平台出击,拥抱更多时机在更多的平台上笼罩更多用户始终是字节跳动产品团队的指标之一。比方在中国十分受欢迎的短视频娱乐利用 "抖音火山版",就让 iOS 和 Android 平台的用户都能够通过分享短视频来展现他们的喜好、技能与日常,且领有十分统一的体验。 △ 抖音火山版 在 2B 畛域,字节跳动则有一款反对企业协同办公的一站式利用 Lark,通过音视频会议、文档共享、及一系列项目管理与能效工具来反对团队的即时通讯需要。整个 Lark 的生态系统在 Flutter 的助力下全面笼罩了 iOS、Android、web 端与桌面平台。 △ 协同办公一站式利用 Lark 开发更高效,开释团队创意热重载 (Hot reload) 始终是 Flutter 最令开发者们称道的开发个性之一,让工程师不再须要一遍遍地期待漫长的编译,从而高效调试代码,疾速将 UI 设计师的想法变为事实。 为了让开发者们能最大限度利用各个平台的原生底层性能,Flutter 还提供了内部性能接口 FFI。这使得 Flutter 利用能够间接调用 C++ 层代码,进步与硬件交互的效率,同时实现端上深度学习模型的部署。 "极课错题打印机" 和 "极课阅卷巨匠" 两款智能设施上搭载的利用都应用 Flutter 开发,前者用于搁置在校园内供学生们自助打印错题,后者则能够帮忙老师智能辨认学生的答卷以及统计分数。借助 Flutter,团队得认为超过 200 所学校的师生疾速实现设施软件的开发以及迭代。 ...

May 18, 2022 · 1 min · jiezi

关于flutter:译-10-个-Flutter-组件推荐-–-5

译 10 个 Flutter 组件举荐 – 5咱们将关注网站、软件包、 GitHub 仓库、小工具、扩大以及更多内容,所以我倡议你当初就追随我,不要错过这个! 浏览欢快! Flutter Carplay与此同时,它在炒作,扑卡玩。你能够用它在 Flutter 开发一个能够在苹果 Carplay 上运行的应用程序。 Scribblehttp://pub.dev/packages/scribble Scribble 是一个简略的包,能够让你画。它能对压力的变动做出反馈,反对不同厚度的划臂等等。 它依然处于开发阶段,然而它正在一直地取得新的个性,并且曾经具备了最重要的个性。 Badgeshttp://pub.dev/packages/badges 包徽章用于向任何小部件增加徽章。这个数字能够示意你的购物车里有多少商品或者有多少条新音讯,然而它也能够用来示意正告,例如一个叹号或者一个新的性能。正如你所见,可能性简直是无穷无尽的。 最棒的是它非常容易应用。您只需用“ Badge”小部件包装您的小部件,而后指定 badeContent,例如文本。上面是一个例子: Pinputhttps://pub.flutter-io.cn/pac... Pinput 用于创立引脚代码输出,其中每个像素都是可定制的。 Flutter Blurhashhttps://pub.dev/packages/flut... 这个软件包是为图像增加一个含糊成果。Blurhash 是一种代码,它指定您的图像看起来会变得模糊不清。要失去这个代码,你须要去 https://blurha.sh/图片库,并粘贴你的图片到那里。这里有一个视觉示例来阐明这是如何工作的: 当初要插入 blurhash,你必须在你的 flutter 代码中实现上面的代码: Bottom Bar with Sheethttps://pub.dev/packages/bott... 是一个一般的底部栏,然而它提供了一个十分有用的性能。有时候你想在屏幕上有更多的空间,然而你是怎么做到的呢?嗯,非常简单: 有了这个导航条,你能够拉出一个“第二屏幕”/表,通过这样做,你失去更多的空间。上面是一个小例子: 看起来有点简单,但实际上并不简单。包中有一个很棒的自述文件,能够具体解释所有。 String Validatorhttp://pub.dev/packages/strin... 这个包裹曾经为我节俭了很多工夫。String \_ validator 用于验证一个字符串(谁会想到呢)。这听起来并不令人兴奋,然而如果你看看有多少种可能性能够用这个包验证一个字符串,那么它简直属于每个 Flutter 我的项目。 Flutter genhttp://pub.dev/packages/flutt... 这个工具十分有用。咱们都晓得基于字符串的 api 并不是最平安的。如果插入的单个字符不正确,整个字符串将进行工作。问题是您常常在 Flutter 中应用 sting api。资产,字体,色彩... 抖动原是有解决这个问题。 ...

May 18, 2022 · 1 min · jiezi

关于flutter:译-10-个-Flutter-组件推荐-–-4

译 10 个 Flutter 组件举荐 – 4原文https://tomicriedel.medium.co...注释明天咱们又要解决软件包了。咱们次要解决的是数据库上的软件包,所以... ... 让咱们一起去浏览吧! Hivehttp://pub.dev/packages/hive Hive 是最好的数据库包之一。作为一个开发者,它提供了很多可能性,对你很有帮忙。要晓得的最重要的一点是,Hive 是一个 NoSQL 数据库。另一个十分重要的一点是,你有十分弱小的加密内置。没有多少数据库包有这个性能,这使得 Hive 更加非凡。哦,还忘了说: 它有很好的文档。底线: 为您的下一个应用程序,你须要一个 NoSQL 数据库,蜂巢相对应该包含在内!你能够通过 Reso Coder 或 Johannes Milke 的教程来学习 Hive: sqflitehttp://pub.dev/packages/sqflite 是一个基于 SQLite 原理的 Android,iOS 和 macOS 的数据库系统。因而,简略地说,如果您想在 SQL 表中存储数据,这是正确的包。 你能够通过 Johannes Milke 的教程或者 Flutter in the Package of the Week 系列的教程来学习如何应用这个软件包: Moorhttp://pub.dev/packages/moor Moor 是一个基于 SQLite 的数据库系统,应用 Dart 编写,能够在任何平台上应用。它比拟出名的 sqflite 软件包有许多长处。然而,因为它是绝对未知的,所以很难找到问题的解决方案。你能够应用 Reso Coder 的系列教程来学习 Moor: Flutter Slidablehttp://pub.dev/packages/flutt... Flutter 滑动是一个包,容许您创立滑动列表我的项目。这也是可能的 Flutter 没有一个包,但这个包提供了一个很好的动画抉择。让咱们来看一下动画: ...

May 17, 2022 · 2 min · jiezi

关于flutter:Dart-217-正式发布

文/ Michael Thomsen, Google Dart 团队产品经理,2022 年 5 月 12 日发表于 Dart 官网博客 随着 Flutter 3 在本次 I/O 大会的公布,咱们也同时正式公布了 Dart 2.17 稳定版 SDK。这个版本的公布是围绕着咱们的外围主题构建的,即:当先的生产力和平台可移植性。 Dart 2.17 提供了新的语言个性:枚举反对成员变量、改良的超类参数继承,以及更为灵便的命名参数。咱们同时为 package:lints 开启了 2.x 版本,这是一套官网的 lint 规定,是依据咱们总结的 Dart 最佳实际整合而成的一个 lint 规定集。与此同时,咱们也更新了外围库的 API 文档,为其带来了丰盛的示例代码。并且,为了改善平台集成个性,咱们在 Flutter 插件中提供了一个新的模版,应用 dart:ffi 与原生平台进行 C 语言的互操作、对 RISC-V 指令集提供实验性反对,以及对 macOS 和 Windows 可执行文件的签名反对。 编程语言新个性助力生产力晋升咱们始终在继续地改良 Dart 编程语言,一直增加新个性以及改良现有的个性,以助力开发者们工作效率的晋升。Dart 2.17 减少了对枚举成员变量的反对,优化了在构造函数中应用命名参数的形式,并且开始应用继承超类的参数以缩小简短和反复的代码。 加强的反对成员变量的枚举枚举非常适合示意一组离散的状态。例如,咱们能够将水形容为 enum Water { frozen, lukewarm, boiling }。但如果咱们想在 enum 上增加一些办法,例如,将每个状态转换为温度,并反对将 enum 转换为 String,该怎么办?或者咱们能够应用扩大办法来增加一个 waterToTemp() 办法,但咱们必须时刻留神它与 enum 的同步。对于 String 咱们心愿覆写 toString() 办法,但它不反对这么做。 ...

May 16, 2022 · 3 min · jiezi

关于flutter:10-个-Flutter-组件推荐-3

有人问我书房(工地)设计留神啥,我只能说桌子竟可能的宽,深度太大没有意义,是否升降桌意义不大,工作个 2 小时还不起来流动下么,人体工程椅子千元左右吧次要是牢固能调节坐得稳,墙面空间要利用上,墙面寒色,少灯光净化,白天自然光用上,放点绿色,宜家很多扩大能够买。 明天咱们再次探讨包,但也探讨 VSCode 扩大。咱们次要解决用户界面,所以... 让咱们去和欢快的浏览! 原文https://tomicriedel.medium.co...注释Animate dohttps://pub.dev/packages/anim... 在我开始写这篇文章的前一天,我看到了这个软件包,并立刻更新了我的整个应用程序。当初听起来不是很有能源吗?好吧,让我先解释一下这个包能做什么。我集体很厌恶动画。我想很多人都批准我的观点。然而,当初你不得不应用动画来吸引用户。这就是 animate do 的用武之地。Animate do 提供了大量曾经筹备好的动画抉择,您能够将其利用到任何小部件。这里是所有动画的列表,其中有很多子点。 FadeIn AnimationsFadeInFadeInDown 摄影: FadeInDownFadeInDownBigFadeInUpFadeInUpBigFadeInLeft 左后方FadeInLeftBigFadeInRightFadeInRightBigFadeOut Animations 淡出动画FadeOut 淡出FadeOutDown 降落FadeOutDownBig 淡出FadeOutUp 淡出FadeOutUpBig 4. FadeOutUpBigFadeOutLeft 后退左转FadeOutLeftBig 淡出FadeOutRight 齐全隐没FadeOutRightBig 超级大BounceIn AnimationsBounceInDownBounceInUpBounceInLeft 右边BounceInRightElasticIn Animations ElasticIn 动画ElasticInElasticInDownElasticInUpElasticInLeft 右边ElasticInRightSlideIns Animations SlideIns 动画SlideInDown 滑下SlideInUpSlideInLeft 滑进右边SlideInRightFlipIn Animations Flipboard AnimationsFlipInXFlipInY 翱翔的Zooms 放大ZoomInZoomOutSpecialIn Animations 专题动画JelloIn 水母好吧,这是很多,但我只是想向你们展现这个包裹的可能性。正如我所说的,这个软件包简直是下一个应用程序的必需品。 MacOS UIhttps://pub.dev/packages/maco... 如果你已经应用 Flutter 为 macOS 开发过应用程序,你可能曾经留神到了。没有任何只实用于 macOS 的好小工具。这就是为什么有 macos ui。这个软件包能够让你轻松地创立与 Swift 齐全一样的应用程序。同样,这里有数量惊人的小部件和一个十分长的列表,但这次我不须要列出它们。 这只是泛滥可能性中的一个例子: Fluent UIhttps://pub.dev/packages/flue... ...

May 15, 2022 · 1 min · jiezi

关于flutter:10-个-Flutter-组件推荐-2

明天,咱们再次举荐 package。咱们次要解决用户界面和图标包,所以... 让咱们去和欢快的浏览! 原文https://tomicriedel.medium.co...注释swipe_tohttps://pub.dev/packages/swip... 如果你想给任何小工具增加简略的滑动手势,滑动到是一个很好的软件包。这个软件包的长处是用户不用点击动作,然而当滑动时动作会立刻执行。 这里有一个例子能够更好地了解它: 然而... ... 我怎样才能将这个令人难以置信的包集成到我的代码中呢? 好吧,这很简略: SwipeTo( child: Container( padding: const EdgeInsets.symmetric(vertical: 10.0, horizontal: 8.0), child: text(' Swipe me Left | YOU |Swipe me right '), ), onLeftSwipe: () {. print('Callback from Swipe To Left'); }, onRightSwipe: () { print('Callback from Swipe To Right'); },),看,一点都不难,对吧? renamehttps://pub.dev/packages/rename 当然,你心愿你的应用程序在公布之前有一个很酷的名字。然而,让咱们面对现实吧,如果您为每个平台手动执行这个过程,那么这个过程可能会十分苦楚。 这就是为什么存在着重命名。这个包容许你在几秒钟外在任何平台上重命名你的应用程序。以下是它的工作原理: 在命令行中执行这个命令:pub global activate rename当初执行这两个命令:pub global run rename --bundleId com.myDomain.myApppub global run rename --appname "MyApp"这两个命令的第一个设置你的应用程序的 BundleId。这是你的畛域,只不过是倒过去的。如果你没有域名,把它设置成你的名字或者你公司的名字。但无论如何,如果这个域名没有被占用,那将是无利的。 ...

May 14, 2022 · 2 min · jiezi

关于flutter:一起看-IO-Flutter-3-正式发布

作者 / Tim Sneath, Google Flutter 和 Dart 产品组产品经理 Flutter 3 实现了 Flutter 以挪动端为核心扩大到多平台的产品布局,并在往年 I/O 大会的主题演讲上正式公布,此次公布提供了对 macOS 和 Linux 桌面端的稳定版反对,同时包含 Firebase 集成的改良,减少了与生产力和性能相干的新个性,并对 Apple 芯片提供了反对。 Flutter 3 的演进创立 Flutter 的初衷是为了彻底改变利用开发:将 「Web 利用的迭代开发模式」与「硬件加速的图形渲染」和「像素级的管制」三者联合——之前只有游戏能力这么做。自 Flutter 1.0 Beta 版公布以来的四年里,咱们逐步在这些根底上倒退,减少了新的框架性能和新的 widget,与底层平台进行了更深刻的整合,还退出了丰盛的 package 库,此外还进行了许多性能和工具等方面的改良。 随着 Flutter 逐步产品走向成熟,越来越多的人开始用它来构建利用。明天,有超过 50 万个利用应用 Flutter 公布。来自 data.ai 等钻研公司的剖析以及公众的评估都能够表明,Flutter 正被许多细分畛域的客户所应用。其应用场景十分宽泛,从微信 (WeChat) 等社交利用,到 Betterment 和 Nubank 等金融和银行类利用,再到 SHEIN 和 trip.com 等商旅利用以及 Fastic、Tabcorp 等生存形式类的利用,还有 My BMW 此类的硬件连贯类利用,最初是巴西政府等公共机构的官网利用等等,都有 Flutter 在大放异彩。 当初已有超过 50 万个利用应用 Flutter 构建。开发者通知咱们,Flutter 帮忙他们在更多的平台上更快地构建出了精美的利用。咱们最新的用户钻研也表明: ...

May 13, 2022 · 2 min · jiezi

关于flutter:前车之鉴聊聊钉钉-Flutter-落地桌面端踩过的坑-Dutter

作者:刘太举(驽良) 《Dutter 系列文章》将论述钉钉基于 Flutter 构建的跨四端利用框架(代号 Dutter)的技术实际与踩坑教训,共分为上、下两篇,上篇内容可点击 Dutter | 钉钉 Flutter 跨四端方案设计与技术实际,本文为下篇,感激浏览。本文次要介绍一下钉钉 Flutter 业务灰度过程中,在桌面端遇到并解决过的几个 FlutterEngine 层面的 Bug。具体蕴含: Mac 端:FlutterEngine 退出之后内存透露问题;FlutterEngine shutdown 阶段死锁问题;低版本 macOS OpenGL 析构阶段 Crash 问题;Windows 端:Win7 设施渲染模块「Crash + 残影」问题;FlutterPlugin 注册阶段野指针 Crash;Flutter Window 可见性变动之后页面白屏。上面来为大家别离介绍一下。 FlutterEngine Mac 端问题1.1 FlutterEngine 退出之后内存透露问题问题背景Mac 端 FlutterViewController 在销毁之后,其开拓的内存并未并理论开释,会呈现内存透露问题。此问题在 Flutter issue 中有一些探讨,但始终未有明确定位。在钉钉 Mac 端 Flutter 业务灰度过程中也遇到此问题,如无奈解决将间接影响 Dutter 在 Mac 端落地的可行性: 定位剖析一句话起因: Mac 端 FlutterEngine 实现中对 weak property 应用不合理导致。FlutterViewController 强持有 FlutterEngine,后者持有一个指向 FlutterViewController 的 weak property。FlutterViewController 在 dealloc 流程中尝试开释 FlutterEngine,然而此时 FlutterEngine 中持有的 weak property 曾经无奈正确拜访(nil),导致开释流程未能失常执行,呈现透露。 ...

May 12, 2022 · 3 min · jiezi

关于flutter:它来了Flutter30发布全解析

本文转载自公众号:群英传作者:徐宜生咱们在手机、桌面和网络上进行多平台UI开发的历程达到了高峰。 咱们很快乐地发表,作为谷歌I/O主题演讲的一部分,咱们明天推出了Flutter 3。Flutter 3实现了咱们从以挪动为核心到多平台框架的路线图,提供了对macOS和Linux桌面利用的反对,以及对Firebase集成的改良,新的生产力和性能个性,并反对Apple Silicon。 The journey to Flutter 3咱们开办Flutter的初衷是试图彻底改变利用开发:将网络的迭代开发模式与硬件加速图形渲染和像素级管制相结合,而这在以前是游戏的专利。自Flutter 1.0测试版以来的四年里,咱们逐步在这些根底上倒退,减少了新的框架性能和新的小工具,与底层平台更深刻的整合,丰盛的包库和许多性能和工具的改良。 随着产品的成熟,越来越多的人开始用它构建应用程序。明天,有超过50万个应用程序是用Flutter建设的。来自data.ai等钻研公司的剖析,以及公众的评估,表明Flutter被许多细分畛域的客户所应用:从微信等社交利用到Betterment和Nubank等金融和银行利用;从SHEIN和trip.com等商务利用到Fastic和Tabcorp等生存形式利用;从My BMW等伴侣利用到巴西政府等公共机构。 明天,有超过50万个应用程序应用Flutter构建。开发人员通知咱们,Flutter有助于在更多的平台上更快地构建丑陋的应用程序。在咱们最新的用户钻研中。 91% 的开发者认为 Flutter 缩短了构建和公布应用程序的工夫。85%的开发者认为Flutter使他们的应用程序比以前更丑陋。85%的人认为Flutter使他们的利用比以前能在更多的平台上公布。在Sonos最近的一篇博客文章中,探讨了他们革新后的设置体验,他们强调了其中的第二个问题。 "毫不夸大地说,[Flutter]开释了一种与咱们团队之前交付的任何货色都不同的 "高级 "水平。对咱们的设计师来说,最重要的是,能够轻松地构建新的UI,这意味着咱们的团队花在对规格说 "不 "的工夫更少,花在迭代上的工夫更多。如果这听起来值得,咱们会举荐你试一试Flutter--咱们很快乐这样做。"Introducing Flutter 3明天,咱们推出Flutter 3,这是咱们填补Flutter所反对的平台的旅程的低潮。有了Flutter 3,您能够从一个代码库中为六个平台构建更好的体验,为开发者提供无可比拟的生产力,并使初创企业从第一天起就能将新的想法带到残缺的可触达市场。 在以前的版本中,咱们用网络和Windows反对来补充iOS和Android,当初Flutter 3减少了对macOS和Linux利用的稳固反对。减少平台反对须要的不仅仅是渲染像素:它包含新的输出和交互模型、编译和构建反对、可拜访性和国际化,以及特定平台的整合。咱们的指标是让你可能灵便地充分利用底层操作系统,同时尽可能多地分享你抉择的用户界面和逻辑。 在macOS上,咱们曾经反对英特尔和苹果Silicon,并提供通用二进制反对,使应用程序可能打包可执行文件,在两种架构上原生运行。在Linux上,Canonical和谷歌曾经单干为开发提供了一个高度集成的、最好的抉择。 Superlist是Flutter如何实现漂亮的桌面体验的一个很好的例子,它明天推出了测试版。Superlist提供了超强的合作,通过一个新的应用程序,将列表、工作和自在模式的内容联合在一起,成为待办事项和集体打算的新形式。Superlist团队抉择Flutter是因为它可能提供疾速、高度品牌化的桌面体验,咱们认为他们迄今为止的停顿证实了为什么它被证实是一个平凡的抉择。 Flutter 3还对许多基本要素进行了改良,进步了性能,反对Material You,并更新了生产力。 除了上述工作外,在这个版本中,Flutter能够齐全原生在苹果芯片上进行开发。尽管Flutter自公布以来始终与M1驱动的苹果设施兼容,但Flutter当初充分利用了Dart对苹果芯片的反对,在M1驱动的设施上实现了更快的编译,并反对macOS应用程序的通用二进制文件。 在这个版本中,咱们为Material Design 3所做的工作根本实现,使开发者可能利用一个适应性强、跨平台的设计零碎,提供动静的色调计划和更新的视觉组件。 咱们具体的技术博文论述了这些以及Flutter 3的许多其余新性能。 Flutter由Dart驱动,这是一种用于多平台开发的高生产力、可移植的语言。咱们在这个周期中对Dart的工作包含缩小模板和帮忙可读性的新语言性能,实验性的RISC-V反对,降级的linter和新的文档。对于Dart 2.17中所有新改良的进一步细节,请查看专用博客:https://medium.com/dartlang。 Firebase and Flutter当然,建设一个应用程序不仅仅是一个UI框架。应用程序发布者须要一套全面的工具来帮忙你构建、公布和经营你的应用程序,包含认证、数据存储、云性能和设施测试等服务。有多种服务反对Flutter,包含Sentry、AppWrite和AWS Amplify。 谷歌提供的应用服务是Firebase,SlashData的开发者基准钻研显示,62%的Flutter开发者在其利用中应用Firebase。因而,在过来的几个版本中,咱们始终在与Firebase单干,以扩充和更好地将Flutter作为一个一流的集成。这包含将Flutter的Firebase插件进步到1.0,减少更好的文档和工具,以及像FlutterFire UI这样的新部件,为开发者提供可重用的auth和profile界面的UI。 明天,咱们发表Flutter/Firebase的整合将成为Firebase产品中齐全反对的外围局部。咱们将源代码和文档转移到Firebase的主仓库和网站中,你能够指望咱们与Android和iOS同步倒退Firebase对Flutter的反对。 此外,咱们还进行了重大改良,以反对应用Crashlytics的Flutter应用程序,这是Firebase风行的实时解体报告服务。随着Flutter Crashlytics插件的更新,你能够实时跟踪致命的谬误,为你提供与其余iOS和Android开发者雷同的功能集。这包含重要的警报和指标,如 "无解体用户",帮忙你放弃你的应用程序的稳定性。Crashlytics剖析管道曾经降级,以改善Flutter解体的聚类,使其更快地分流、优先解决和修复问题。最初,咱们简化了插件的设置过程,因而只须要几个步骤就能够应用Crashlytics,并从你的Dart代码中开始运行。 Flutter Casual Games Toolkit对于大多数开发者来说,Flutter是一个应用程序框架。然而,围绕休闲游戏开发的社区也在一直壮大,利用Flutter提供的硬件加速图形反对和Flame等开源游戏引擎。咱们心愿让休闲游戏开发者更容易上手,所以在明天的I/O大会上,咱们发表了休闲游戏工具包,它提供了一个模板和最佳实际的入门套件,以及广告和云服务的良好体验。 尽管Flutter并不是为高强度的3D动作游戏而设计的,但即便是一些游戏也转向Flutter的非游戏UI,包含像PUBG Mobile这样领有数亿用户的风行游戏。而对于I/O,咱们想看看咱们能把技术推到什么水平,所以咱们发明了一个乏味的弹球游戏,它由Firebase和Flutter的网络反对提供反对。I/O弹球游戏提供了一个围绕谷歌最喜爱的四个吉祥物设计的定制桌子。Flutter的Dash、Firebase的Sparky、Android机器人和Chrome的恐龙,并让你与别人竞争高分。咱们认为这是一种展现Flutter多功能性的乏味形式。 Sponsored by Google, powered by community咱们喜爱Flutter的一点是,它不仅仅是谷歌的产品--它是一个 "所有人 "的产品。开源意味着咱们都能够参加其中,并与它的胜利非亲非故,无论是通过奉献新的代码或文档,创立赋予外围框架新的超能力的包,编写教诲别人的书籍和培训课程,还是帮忙组织流动和用户组。 ...

May 12, 2022 · 1 min · jiezi

关于flutter:10-个-Flutter-优秀组件

明天咱们再次探讨对于 UI 和 Widgets 的优良软件包。所以... ... 让咱们开始欢快的浏览吧! 原文https://tomicriedel.medium.co...注释YaruFlutter 反对许多平台,其中包含 Linux。当初,如果你开发了一个丑陋的 Ubuntu 格调的应用程序,它可能会变得复杂。这就是亚鲁存在的起因。这使您可能应用各种各样的组件,从按钮和查看到进度条,而无需编写简单的代码。 Aesthetic 对话对话是平凡的创造。它们被用在简直每一个应用程序中,并且看起来十分棒。然而,创立如此美好的对话框须要工夫。出于这个起因,有一个包叫做 aesthetic_dialogs。这为您提供了许多定制选项,但依然非常容易应用。 Swipable Stackswipable_stack 你可能想要创立一个 Tinder 的克隆,或者一个齐全不同的利用,然而它也有相熟的 swipecards。当然,你能够本人增加整个应用程序,然而为什么要让它变得不必要的艰难呢?你应该应用 swipable_stack。有了这个软件包,你能够很容易地创立这些卡片,并通过一些代码线取得用户输出。你的应用程序能够是这样的: Animated Toggle Switch 动画切换开关animated_toggle_switch 动画切换开关为您提供了一个不同的抉择,不仅仅是 2 个抉择不同的开关。解释这个概念最简略的办法是应用 gif: 自定义导航栏custom_navigation_bar 自定义导航栏为你提供了创立简略的动画导航栏的可能性。这个导航条适宜任何看起来很时尚的应用程序,肯定会吸引用户的眼球! 自定义计时器Custom Timer 定制计时器让你有可能在你的应用程序中创立一个非常简单的计时器,然而这是十分可定制的。这个软件包非常容易应用,并且能够在任何一个静止和时钟应用程序中找到应用办法: Flash 闪光flash 揭示对话框是很棒的,然而有时候写这么多代码并自定义整个事件会有点烦人。这就是 flash 发挥作用的中央。这是一个非常容易应用的可定制的警报库。 ScribbleScribble Scribble 是一个图书馆,让你在 Flutter 应用程序中绘制根本的办法。你能够应用橡皮擦,应用不同厚度的钢笔,甚至是不同的色彩。对于具备小型绘图性能的应用程序,这个库是相对举荐的。 Water Drop 导航杆library 这个导航栏有很多精彩的动画。正如这个library的名字所暗示的那样,它看起来就像一滴水滴落在选定的图标上。上面是一个例子: Glass 玻璃成果glassmorphism 玻璃态势是一个微小的用户界面趋势,但并不总是容易实现。这就是为什么有这样一个 glassmorphism ,它容许您轻松地创立 Glasmorphic UI。 end. 祝你明天欢快! ...

May 11, 2022 · 1 min · jiezi

关于flutter:钉钉-Flutter-跨四端方案设计与技术实践-Dutter

《Dutter 系列文章》将论述钉钉基于 Flutter 构建的跨四端利用框架(代号 Dutter)的技术实际与踩坑教训,共分为上、下两篇,本文为上篇,本周四将上线系列文章下篇《前事不忘;后事之师:聊聊钉钉 Flutter 落地桌面端踩过的“坑”》,欢送追更 & 浏览。作者:刘太举(驽良) 本文次要介绍钉钉基于 Flutter 构建的跨四端利用框架(代号 Dutter),内容次要蕴含方案设计、最佳实际以及局部 FlutterEngine 层面的问题定位等。心愿能通过本文的分享,为有相似诉求的团队提供肯定参考。 我的项目概述1.1 何为 DutterDutter 即 DingTalk Flutter,是钉钉内基于 Flutter 构建的跨四端研发框架。 Dutter 我的项目「起于 Flutter 但不止于 Flutter」。我的项目的次要指标是心愿可能借助 Flutter 跨平台能力,在不升高用户体验的前提下,晋升钉钉端侧研发效率,缓解钉钉端侧研发资源有余、各端人力不均衡的问题。 1.2 目前停顿目前 Dutter 运行框架已实现钉钉四端集成,并实现了一系列共创业务的灰度和试点。现阶段钉钉内基于 Flutter 研发业务有「日程签到」「+面板」以及局部外部灰度业务: 我的项目背景咱们抉择 Flutter 并启动 Dutter 我的项目次要有两方面的思考: 端侧研发提效;跟进 Flutter 技术。上面咱们针对这简略开展做一下阐明。 2.1 端侧研发提效随着钉钉倒退到第7个年头,客户端侧「业务需要」「研发资源」和「技术演进」这三者之间的矛盾愈发强烈: 业务产品同学有很多优良的想法,为将想法落地须要去寻找各端 TL 争取资源,且因为研发资源缓和需重复沟通其需要的业务价值;研发同学经常处于「1 vs N」的状态,业务需要、稳定性保障、技术支持、BugFix等,日常工作工夫根本趋于饱和;技术团队不只是要满足于当初,更要面向未来。在满足日常业务迭代同时,咱们还须要安顿局部资源投入到满足将来 3~5 年倒退的技术我的项目上。以上各点可汇总到一个问题:咱们技术研发资源有余。为解决上述问题,有两个路径:1. 持续扩充技术团队规模;2. 晋升团队研发效率。 以目前钉钉端侧将近150人的团队规模来看,总体量并不算小,持续扩招存在肯定难度。既然团队规模无奈有限扩张,咱们就须要在研发效率上开掘晋升空间: 端侧技术同学被宰割到5个平台,宰割之后每个平台上上人力并不算短缺;不同平台下的同学技术栈上根本处于「断绝」状态,不同平台下的同学无奈互相补位;任何业务需要须要须要 4+ 端以上的研发资源投入,任何一端人力欠缺都可能造成无奈落地;一份逻辑多份实现,很难导致完全一致,时常会呈现不同平台业务体现不统一的状况,返工对焦进一步影响效率;业务上线之后不同平台别离保护,在日常技术支持、BugFix 等场景下须要多份投入。由此可见,如果咱们能借助于跨平台技术,使技术同学能够通过「一份代码实现笼罩所有端」,将原来一个需要须要多个平台、多个同学别离做的事件收敛到 1~2 个同学上,即可极大的进步咱们的研发效率。 2.2 跟进 Flutter 技术钉钉内曾经有「小程序」「H5」等跨端技术,咱们须要提效是否能够间接应用现有技术栈来达成指标?对于钉钉端侧团队来说,选基于 Web 的计划来做跨平台实践上可行,然而理论很难达到预期成果。次要起因在于两方面: ...

May 11, 2022 · 3 min · jiezi

关于flutter:4个非常有用的-Flutter-技巧

明天我将向您展现 4 个十分有用的 Flutter 技巧,您能够立刻利用到您的我的项目。我不会向您展现任何包或扩大,就像我通常做的那样,然而非常简单,然而十分有用的提醒! 原文https://tomicriedel.medium.co...注释明天我将向您展现 4 个十分有用的 Flutter 技巧,您能够立刻利用到您的我的项目。我不会向您展现任何包或扩大,就像我通常做的那样,然而非常简单,然而十分有用的提醒! 简化 Assert 治理治理 Assert 可能十分艰难。如果你想在你的应用程序中屡次应用一个图像,你必须一次又一次地指定门路。然而有一个简略得多的解决方案。创立一个 App Assets 类,用于存储所有的 App Assert。当初您能够轻松地应用 AppAssets.appLogo 或 AppAssets.noConnection 调用 Assert。 更容易 imports在一个文件的结尾看到和治理成千上万的导入真的很烦人。这就是为什么我要向你们展现一种轻松缩小进口的办法。 假如你有一个文件夹叫做 Constants, 外面的文件包含 app_colors.dart, app_fonts.dart, app_theme.dart, app_constants and app_assets.dart are. 在这个文件夹中,您当初创立一个名为 constant.dart 的新文件。 在这里,您为每个文件编写一个导出语句。当初你能够通过简略的导入 constant.dart 来拜访你的每个文件: 从按钮上移除飞溅成果 当你点击一个按钮时,每个人都晓得这种飞溅成果,我一点也不喜爱。 所以我将向你们展现如何用一条线打消这种成果。 为此你必须应用 splashFactory: 当初你的按钮在按下的时候看起来像这样: (我始终在点击按钮) 更简略的平台小工具每个 Flutter 开发人员可能都晓得当你查问用户是 iOS 还是 Android 时的状况。因而,您而后显示一个特定的 wdiget,例如 Switch 或 CupertinoSwitch。然而如果我通知你,你不须要一个查问,也不须要两个小工具呢?怎么做到的?这就是我当初要展现给你们的: ...

May 11, 2022 · 1 min · jiezi

关于flutter:Dart-语言的7个很酷的特点

原文https://betterprogramming.pub...参考https://dart.dev/guides/langu...注释明天的文章简短地揭示了 Dart 语言所提供的很酷的个性。更多时候,这些选项对于简略的应用程序是不必要的,然而当你想要通过简略、清晰和简洁来改良你的代码时,这些选项是一个救命稻草。 思考到这一点,咱们走吧。 Cascade 级联Cascades (.., ?..) 容许你对同一个对象进行一系列操作。这通常节俭了创立长期变量的步骤,并容许您编写更多晦涩的代码。 var paint = Paint();paint.color = Colors.black;paint.strokeCap = StrokeCap.round;paint.strokeWidth = 5.0;//above block of code when optimizedvar paint = Paint() ..color = Colors.black ..strokeCap = StrokeCap.round ..strokeWidth = 5.0;Abstract 抽象类应用 abstract 修饰符定义一个 _abstract 抽象类(无奈实例化的类)。抽象类对于定义接口十分有用,通常带有一些实现。 // This class is declared abstract and thus// can't be instantiated.abstract class AbstractContainer { // Define constructors, fields, methods... void updateChildren(); // Abstract method.}Factory constructors 工厂建造者在实现不总是创立类的新实例的构造函数时应用 factory 关键字。 ...

May 8, 2022 · 2 min · jiezi

关于flutter:Flutter-状态管理框架-Provider-和-Get-分析

文/ Nayuta,CFUG 社区 状态治理始终是 Flutter 开发中一个炽热的话题。谈到状态治理框架,社区也有诸如有以Get、Provider为代表的多种计划,它们有各自的优缺点。面对这么多的抉择,你可能会想:「我须要应用状态治理么?哪种框架更适宜我?」本文将从作者的理论开发教训登程,剖析状态治理解决的问题以及思路,心愿能帮忙你做出抉择。 为什么须要状态治理?首先,为什么须要状态治理?依据笔者的教训,这是因为 Flutter 基于申明式 构建 UI ,应用状态治理的目标之一就是解决「申明式」开发带来的问题。 「申明式」开发是一种区别于传原生的形式,所以咱们没有在原生开发中听到过状态治理,那如何了解「申明式」开发呢? 「申明式」VS「命令式」剖析以最经典的的计数器例子剖析: 如上图所示:点击右下角按钮,显示的文本数字加一。Android 中能够这么实现:当右下角按钮点中时,拿到 TextView 的对象,手动设置其展现的文本。 实现代码如下: // 一、定义展现的内容private int mCount =0; // 二、两头展现数字的控件 TextViewprivate TextView mTvCount; // 三、关联 TextView 与 xml 中的组件mTvCount = findViewById(R.id.tv_count) // 四、点击按钮管制组件更新private void increase( ){ mCount++; mTvCounter.setText(mCount.toString()); }而在 Flutter 中,咱们只须要使变量减少之后调用 setState((){}) 即可。setState 会刷新整个页面,使得两头展现的值进行变更。 // 一、申明变量int _counter =0; // 二、展现变量 Text('$_counter')// 三、变量减少,更新界面setState(() { _counter++; });能够发现,Flutter 中只对 _counter 属性进行了批改,并没有对 Text 组件进行任何的操作,整个界面随着状态的扭转而扭转。 所以在 Flutter 中有这么一种说法: UI = f(state): ...

May 6, 2022 · 4 min · jiezi

关于flutter:浅谈-Flutter-编译原理

前言纯熟应用 Flutter 开发 app 的人员,对各种 widget 的应用必定曾经信手拈来了,但往往对 Flutter 是如何编译、相应产物是什么却知之甚少。 本文就来理解一下 Flutter 编译的相干常识 一、Flutter 架构层 Flutter 架构次要分为三层: 1. Framework 层基于 Dart 实现,次要蕴含 Material Design(Google),Cupertino (iOS)两种格调的 Widgets。文本/图片/按钮 等 Widgets。渲染/动画/绘制/手势 等 Widgets。外围根底类/办法,次要指 Flutter 仓库下的 Flutter package,以及 sky_engine 仓库下的 io、async、ui(dart:ui 库提供了 Flutter 框架和引擎之间的接口) 等 package。2. Engine 层基于 C++ 实现,次要蕴含 Skia 开源的二维图形库,提供了实用于多种软硬件平台的通用 API。Dart 次要蕴含 Dart Runtime,Garbage Collection(GC),如果是 Debug 模式的话,还包含 JIT ( Just In Time )反对。Release 和 Profile 模式下,是 AOT(Ahead Of Time)编译成了原生的 arm 代码,并不存在 JIT 局部。Text 文本渲染,其渲染档次如下:衍生自 minikin 的 libtxt 库(用于字体抉择,分隔行);HartBuzz 用于字形抉择和成型;Skia 作为渲染 / GPU 后端,在 Android 和 Fuchsia 上应用 FreeType 渲染,在 iOS 上应用 CoreGraphics 来渲染字体。3. Embedder 层Embedder 是一个嵌入层,即把 Flutter 嵌入到各个平台下来,这里做的次要工作包含渲染Surface 设置,线程设置,以及插件等。从这里能够看出,Flutter 的平台相干层很低,平台(如 iOS)只是提供一个画布,残余的所有渲染相干的逻辑都在 Flutter 外部,这就使得它具备了很好的跨端一致性。 ...

May 5, 2022 · 3 min · jiezi

关于flutter:17-个提高性能的-Flutter-最佳实践

与其余混合平台相比, Flutter 性可能快吗?答案是必定的,然而出于这种思考,让咱们来看看一些令人惊叹的性能和优化实际。 原文https://inficial.medium.com/f...参考https://api.flutter.dev/flutt...https://blog.codemagic.io/how...https://pub.dev/packages/nilhttps://medium.com/flutter-co...https://dart.dev/guides/langu...https://dart-lang.github.io/l...https://itnext.io/comparing-d...https://iisprey.medium.com/ge...注释1. 应用 Widgets 代替函数不要这样用它 Widget _buildFooterWidget() { return Padding( padding: const EdgeInsets.all(8.0), child: Text('This is the footer '), );}.像这样应用它 class FooterWidget extends StatelessWidget { @override Widget build(BuildContext context) { return Padding( padding: const EdgeInsets.all(8.0), child: Text('This is the footer '), ); }}如果一个函数能够做同样的事件,Flutter 就不会有 StatelessWidget。 相似地,它次要是针对公共 widgets 的,这些 widgets 能够重复使用。私人函数只能应用一次并不重要ーー只管意识到这种行为依然是好的。 应用函数而不是类之间有一个重要的区别,那就是: 框架不晓得函数,然而能够看到类。 思考上面的“ widget”函数: Widget functionWidget({ Widget child}) { return Container(child: child);}这样应用: functionWidget( child : functionWidget())而且它是等价的: ...

April 27, 2022 · 4 min · jiezi

关于flutter:Dart-Constructors-构造函数使用技巧整理

原文https://itnext.io/deep-dive-i...参考https://dart.dev/guides/langu...https://www.freecodecamp.org/...https://stackoverflow.com/que...https://dash-overflow.net/art...https://flutterigniter.com/de...https://dart.dev/guides/langu...注释这篇文章是探讨下 Dart 构造函数的一些应用技巧 首先 什么是构造函数? 构造函数是用于初始化对象的非凡办法。在创立类的对象时调用构造函数。默认状况 final ehe = MyClass(); // Creates an instanceclass MyClass { MyClass(); // Fires immediately when created (this guy is cons.)}在构造函数中只有一个规定 也就是说; 与它的类名一样命名它! !好的,咱们晓得了! 然而.. 咱们具体有哪些类型的构造函数类型? 缺省构造函数 ー Class() // Default Constructor// 默认什么都不做class User { String name = 'ehe'; User();}///////////////////// Constructor with parameters// 结构时初始变量class User { String name; User(this.name);}///////////////////// Constructor with the initial method// 构造函数内写入你的逻辑class User { String name; User(this.name) { // do some magic }}/////////////////// Constructor with assertion// 应用 Asserts 去查看你的规定class User { String name; User(this.name) : assert(name.length > 3);}////////////////// Constructor with initializer// 初始化你的变量class User { static String uppercase(String e) => e.toUpperCase(); String name; User(name) : name = yell(name); static String yell(String e) => e.toUpperCase();}/////////////////////// Constructor with super()// override 变量class Person { String id; Person(this.id);}class User extends Person { String name; User(this.name, String id) : super(id);}/////////////////////// Constructor with this()// 命名构造函数class User { String name; int salary; User(this.name, this.salary); User.worker(String name) : this(name, 10); User.boss(String name) : this(name, 9999999);}公有构造函数ー Class._() ...

April 26, 2022 · 2 min · jiezi

关于flutter:邀请你参与字节跳动-UME-插件开发竞赛

UME 是由字节跳动 Flutter Infra 团队出品和保护的 Flutter 利用内调试工具。通过在 Flutter 利用中退出 UME 工具,开发者们能够间接在利用内查看调试信息,而无需应用 IDE 和 Flutter DevTools 等工具。这将不便开发者们间接在利用内获取有用信息,进一步晋升外部 Flutter 团队的研发、调试与验收效率。 截至目前,UME 曾经在字节跳动外部应用近两年工夫,助力外部二十多个业务线应用 Flutter 晋升开发效率。去年 7 月底,UME 正式开源,提供了十个调试插件,笼罩 UI 查看、性能工具、代码查看、日志查看等性能。 作为一个开源我的项目,UME 的代码奉献来自字节跳动公司外部以及来自社区的开发者们。最新版本的 UME 共集成了 22 款插件,新退出性能和调试插件包含:插件间通信、疾速接入嵌套的第三方调试工具、全屏布局边界查看性能,以及来自社区奉献的 cyclop 拾色工具插件、touch_indicator 触摸标识器和 dio_inspector 申请查看工具。 为了更好地帮忙更多的开发者们通过利用内调试晋升 Flutter 利用开发效率,字节跳动 Flutter Infra 团队于本月初 开启了基于 UME 的插件开发比赛,邀请社区的开发者们基于 UME 工具进行调试插件的开发。 参赛须知提交作品须要合乎「无效作品规范」,对不符合标准的参赛作品将无资格参加评奖;若须要批改 flutter_ume 代码以反对插件能力,请复刻 (Fork) flutter_ume GitHub 仓库、批改代码,并向 flutter_ume 仓库提交拉取申请 (Pull Request),在提交作品的邮件注释中增加拉取申请的 URL 地址;对于存在代码类似、创意雷同、性能相似的参赛作品,以提交工夫为评比根据;较量组委会将在参赛作品评比完结后通过邮件分割参赛选手,请务必放弃邮箱畅通;本次作品须要通过邮件模式提交,开发者将最终作品以压缩包以附件的模式,发送至:ume-kits-competition@bytedance.com无效作品规范参赛作品压缩包中必须具备 pubspec.yaml、README.md 文件与 lib、test、screenshots 目录,若为 plugin 则还包含对应平台的 native 代码目录;参赛作品代码须要 反对空平安,最低反对 Flutter 2.0 版本,必须蕴含 test 单元测试;在提交作品前,请务必在 flutter_ume 的 example 工程中将参赛作品接入测试,并胜利运行 example 工程,插件性能失常应用;参赛作品须要在作品提交阶段内 (5 月 30 日 23:59 之前) 发送到参赛专用邮箱 ume-kits-competition@bytedance.com,以参赛邮箱接管到邮件的工夫为准,不在流动提交工夫内提交的作品有效;参赛作品一旦发送到参赛邮箱,即 认同该代码将以 MIT 协定开源,并奉献至 flutter_ume 开源仓库;参赛选手对参赛作品代码版权负责,对代码可能导致的版权、开源协定危险承担责任。参赛步骤参考创立插件包 flutter create -t <package 或 plugin> name_of_kit;在创立进去的包中,依赖 flutter_ume 进行开发;开发实现后充沛自测,在 test 目录中增加单元测试;将插件演示成果截图或录屏保留到插件的 screenshots 目录下;将 pubspec.yaml、README.md 文件与 lib、test、screenshots 目录(若为 plugin 则还包含对应平台的 native 代码目录,如 ios、android、web、windows、macos、linux 等)一起压缩至 zip 压缩包,并以你的作品名称命名,如 name_of_kit.zip;在 README.md 中编写文档;将压缩包以附件的模式,发送至邮箱 ume-kits-competition@bytedance.com,题目为:"ume-kits-competition"。流动评奖及奖品设置依照参赛作品品质,较量组委会将在全副无效作品中选出二十名优秀作品,颁予处分,并设置参加奖五十名: ...

April 22, 2022 · 1 min · jiezi

关于flutter:在-Flutter-添加页面过渡动画

原文https://medium.com/@aayushked...参考https://pub.dev/packages/page...注释大家好,在这篇文章中,咱们将学习如何增加动画,同时从一个页面到其余在 Flutter。咱们将笼罩不同类型的动画和实现根本动画 Flutter 应用包页动画过渡。 page_animation_transition 引言动画在晋升用户体验方面起着至关重要的作用,但动画到底是什么呢? 设计语言,例如 Material,定义了在路线(或屏幕)之间转换时的规范行为。不过,有时候,自定义屏幕之间的转换能够使应用程序更加独特。 在本教程中,咱们将应用包页面 page_animation_transition 来简化在页面上增加转换。 应用插件摸索不同的转换 第一步: 在 pubspec.yaml 中增加页面动画转换page_animation_transition 步骤 2: 在 PageOne 上导入库假如您正在从 PageOne 过渡到 PageTwo 以下是图书馆反对的动画类型: _BottomToTopTransitionTopToBottomTransitionRightToLeftTransitionLeftToRightTransitionFadeAnimationTransitionScaleAnimationTransitionRotationAnimationTransitionTopToBottomFadedTransitionBottomToTopFadedTransitionRightToLeftFadedTransitionLeftToRightFadedTransition_ 底到上转换到底转换右转移左/右转变淡化动画/转换标量动画/转换转动/动画/转变上到下到过渡底部/上部/下部/上部/下部/上部/下部/上部/下部/上部/下部/上部/右转到/ftfaded/transition左/右/插入/转换 步骤 3: 增加以下导航代码行Navigator.of(context).push(PageAnimationTransition(page: const PageTwo(), pageAnimationType: BottomToTopTransition()));对于预约义的路由: onGenerateRoute: (settings) { switch (settings.name) { case '/pageTwo': return PageAnimationTransition(child: PageTwo(), pageAnimationType: LeftToRightFadedTransition()); break; default: return null; } }Navigator.pushNamed(context, '/pageTwo'); Pushnamed (context,’/pageTwo’) ; Output: 输入: 其余类型转换的残缺代码:import 'package:page_animation_transition/animations/bottom_to_top_faded_transition.dart';import 'package:page_animation_transition/animations/bottom_to_top_transition.dart';import 'package:page_animation_transition/animations/fade_animation_transition.dart';import 'package:page_animation_transition/animations/left_to_right_faded_transition.dart';import 'package:page_animation_transition/animations/left_to_right_transition.dart';import 'package:page_animation_transition/animations/right_to_left_faded_transition.dart';import 'package:page_animation_transition/animations/right_to_left_transition.dart';import 'package:page_animation_transition/animations/rotate_animation_transition.dart';import 'package:page_animation_transition/animations/scale_animation_transition.dart';import 'package:page_animation_transition/animations/top_to_bottom_faded.dart';import 'package:page_animation_transition/animations/top_to_bottom_transition.dart';import 'package:page_animation_transition/page_animation_transition.dart';import 'page_two.dart';import 'package:flutter/material.dart';class PageOne extends StatelessWidget { const PageOne({Key? key}) : super(key: key);[@override](http://twitter.com/override) Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Page Animation Transition'), centerTitle: true, ), body: SizedBox( width: MediaQuery.of(context).size.width, child: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ ElevatedButton( onPressed: () { Navigator.of(context).push(PageAnimationTransition( page: const PageTwo(), pageAnimationType: BottomToTopTransition())); }, child: const Text('Bottom To Top')), ElevatedButton( onPressed: () { Navigator.of(context).push(PageAnimationTransition( page: const PageTwo(), pageAnimationType: TopToBottomTransition())); }, child: const Text('Top to bottom')), ElevatedButton( onPressed: () { Navigator.of(context).push(PageAnimationTransition( page: const PageTwo(), pageAnimationType: RightToLeftTransition())); }, child: const Text('Right To Left')), ElevatedButton( onPressed: () { Navigator.of(context).push(PageAnimationTransition( page: const PageTwo(), pageAnimationType: LeftToRightTransition())); }, child: const Text('Left to Right')), ElevatedButton( onPressed: () { Navigator.of(context).push(PageAnimationTransition( page: const PageTwo(), pageAnimationType: FadeAnimationTransition())); }, child: const Text('Faded')), ElevatedButton( onPressed: () { Navigator.of(context).push(PageAnimationTransition( page: const PageTwo(), pageAnimationType: ScaleAnimationTransition())); }, child: const Text('Scale')), ElevatedButton( onPressed: () { Navigator.of(context).push(PageAnimationTransition( page: const PageTwo(), pageAnimationType: RotationAnimationTransition())); }, child: const Text('Rotate')), ElevatedButton( onPressed: () { Navigator.of(context).push(PageAnimationTransition( page: const PageTwo(), pageAnimationType: TopToBottomFadedTransition())); }, child: const Text('Top to Bottom Faded')), ElevatedButton( onPressed: () { Navigator.of(context).push(PageAnimationTransition( page: const PageTwo(), pageAnimationType: BottomToTopFadedTransition())); }, child: const Text('Bottom to Top Faded')), ElevatedButton( onPressed: () { Navigator.of(context).push(PageAnimationTransition( page: const PageTwo(), pageAnimationType: RightToLeftFadedTransition())); }, child: const Text('Right to Left Faded')), ElevatedButton( onPressed: () { Navigator.of(context).push(PageAnimationTransition( page: const PageTwo(), pageAnimationType: LeftToRightFadedTransition())); }, child: const Text('Left to Right Faded')), ], ), ), ); }}输入: ...

April 21, 2022 · 2 min · jiezi

关于flutter:如何测试-Flutter-应用-ー-单元测试

原文https://medium.com/@sanketsma...参考https://docs.flutter.dev/cook...注释大家好! 首先让咱们理解一下为什么在应用程序还处于开发阶段时,咱们须要对其执行自动化测试。 自动化测试是一种应用自动化工具测试工具在软件应用程序上编写和运行测试用例套件的办法。 如果咱们在开发阶段测试应用程序,咱们能够通过应用自动化测试来检测可能导致呈现例行更改的新谬误,从而节省时间。 Flutter 自动测试的几种类型: Unit Test 单元测试Widget Test 小部件测试Integration Test 综合测试留神: 咱们只在本文中探讨单元测试。什么是单元测试和测试用例? 单元测试用于验证单个函数、办法或类的正确性。要测试此函数、办法或类,必须编写测试用例。为了验证预期输入而必须满足的条件称为测试用例。 施行程序:在本文中,咱们将为登录页面运行测试用例,该页面有两个字段: email id 和 password。 步骤 1: 确保在 pubspec yaml 文件中存在 flutter_test 依赖项。dev_dependencies: flutter_test: sdk: flutter步骤 2: 创立验证器类。咱们所有的验证办法都将在这个类中编写。这些办法将用于咱们的登录页面(在 email 和明码 textformfield 验证器参数中)和 login_unit_test 类中。 明码 TextFormField\_TextFormField( validator: Validators.validatePwd,)Validator Class Validator 类 步骤 3: 在测试目录中创立 login_unit_test 类,并为 Login 编写测试用例。当初,咱们曾经到了编写测试用例的阶段。 void main() { test('Verify invalid email address', () { String emailId = 'abc@gmail'; var result = Validators._validateEmailId_(emailId); expect(result, 'Enter valid Email ID.'); }); test('Verify valid password', () { String pwd = 'Qwe@12345'; var result = Validators._validatePwd_(pwd); expect(result, null); });}咱们应用 test 函数来定义测试用例。咱们必须在这个函数中提供两个强制参数。第一个参数是一个字符串值,即(对特定状况的形容) ,第二个参数是一个函数,咱们在其中验证测试用例。 ...

April 21, 2022 · 1 min · jiezi

关于flutter:Flutter-应用程序创建一个扩展面板列表

原文https://medium.flutterdevs.co...参考https://api.flutter.dev/flutt...注释理解如何在您的 Flutter 应用程序创立一个扩大面板列表 在本文中,咱们将探讨 ExpansionPanelList In Flutter. 。咱们将施行一个扩大面板列表演示程序,并学习如何自定义其格调与不同的属性在您的 Flutter 应用程序。 Expansion Panel List:它是一个相似于 listView 的实质性 Flutter 小部件。它能够只有扩大面板作为儿童。在某些状况下,咱们可能须要显示一个列表,其中子元素能够开展/折叠以显示/暗藏一些具体的数据。为了显示这样的列表 flutter,提供了一个名为 ExapansionPanelList 的小部件。 在这个列表中,每个子元素都是 expsionpanel 小部件。在这个列表中,咱们不能应用不同的窗口小部件作为子窗口。咱们能够借助于 expsioncallback 属性来解决事物的状态调整(扩大或解体)。 演示模块: 这个演示视频显示了如何在一个 Flutter 扩大面板清单。它显示如何扩大面板列表将工作在您的 Flutter 应用程序。它显示了一个列表,在这个列表中孩子们能够开展/折叠以显示/暗藏一些详细信息。它会显示在你的设施上。 Constructor:要应用 ExpansionPanelList,须要调用上面的构造函数:const ExpansionPanelList({ Key? key, this.children = const <ExpansionPanel>[], this.expansionCallback, this.animationDuration = kThemeAnimationDuration, this.expandedHeaderPadding = _kPanelHeaderExpandedDefaultPadding, this.dividerColor, this.elevation = 2,})Properties:ExpansionPanelList 的一些属性如下:> children: 此属性用于扩大面板 List 的子元素。它们的布局相似于[ListBody]。> expansionCallback: 此属性用于每当按下一个开展/折叠按钮时调用的回调。传递给回调的参数是按下的面板的索引,以及面板以后是否开展。> animationDuration: 这个属性用于开展或折叠时,咱们能够察看到一些动画在肯定工夫内产生。咱们能够通过应用扩大面板 List 的 animationDuration 属性来更改持续时间。咱们只须要提供以微秒、毫秒或分钟为单位的持续时间值。> expandedHeaderPadding: 此属性用于开展时围绕面板标头的填充。默认状况下,16px 的空间是在扩大期间垂直增加到题目(下面和上面)。> dividerColor: 当[ expsionpanel.isexpanded ]为 false 时,此属性用于定义分隔符的色彩。如果‘ dividerColor’为空,则应用[ DividerThemeData.color ]。如果为 null,则应用[ ThemeData.dividerColor ]。> elevation: 此属性用于在扩大时定义[ expsionpanel ]的晋升。这应用[ kElevationToShadow ]来模仿暗影,它不应用[ Material ]的任意高度个性。默认状况下,仰角的值为 2。如何实现 dart 文件中的代码:你须要别离在你的代码中实现它: ...

April 19, 2022 · 3 min · jiezi

关于flutter:Dependabot-开始支持-pub-package-版本检测

今年年初,咱们公布了 Flutter 2022 产品路线图,其中「基础设施建设」这部分提到:2022 年 Flutter 团队将减少对供应链的平安的投入,目标是达到合乎基础设施 SLSA 4 级别中形容的要求。 供应链平安大多数开源我的项目依赖了数百个开源依赖项[[1]](https://go2.gdsub.com/ospd "GitHub 文档 - 供应链平安: 大多数开源我的项目依赖了数百个开源依赖项"),随着更多开源我的项目被更宽泛地应用,这些依赖项给其使用者们带来了安全隐患:如果咱们应用的开源我的项目的依赖项受到攻打和毁坏该怎么办?这将让你的间接用户 (软件的最终使用者) 遭受供应链攻打带来的危险。 供应链攻打是一种新兴的、针对软件开发者和供应商的平安威逼[[2]](https://go2.gdsub.com/scad "Microsoft 文档 - 供应链攻打: 供应链攻打是一种新兴的、针对软件开发者和供应商的平安威逼"),攻击者会通过寻找不平安的网络协议、不受爱护的服务器以及不平安的代码等安全漏洞并更改代码,导致应用它的程序在构建和更新的过程中被退出暗藏的恶意代码。 为了确保依赖项供应链的安全性,开发者们须要确保所有依赖项和工具定期更新到最新稳固版本,因为这些新的版本通常会蕴含最新性能和已知破绽的平安修补程序。依赖项包含依赖的代码、应用的二进制文件、应用的工具以及其余组件等[[3]](https://docs.microsoft.com/zh... "Microsoft 文档 - 对于安全软件供应链的最佳做法")。在 GitHub 上托管的开源代码能够应用 GitHub 提供的代码扫描性能来查找我的项目中的安全漏洞和谬误,并应用 Dependabot 保护我的项目的依赖项,以确保我的项目自动更新到依赖项的最新版本。 启用 package 版本检测对 Dart package 的反对能够回溯至 19 年 4 月初,过后的 Flutter 刚刚公布到 v1.2 稳定版;同年 5 月,Dependabot 被 GitHub 收买并收费为开发者提供服务。有一位社区成员在 dependabot-core#2166 这个议题 (issue) 中发动发问,心愿 Dependabot 退出对 Flutter / Dart 的反对。通过 Dependabot 与 Dart 团队的共同努力,包含前期为 Flutter 命令行工具退出了一些对 package 版本检测等性能,最初在往年 3 月 22 日开启关闭测试,并于 4 月 5 日进行公开的 beta 测试。 ...

April 19, 2022 · 1 min · jiezi

关于flutter:使用Flutter我写了一个开源版本的HandShaker

前言去年八月份,因为开发须要,我尝试在Mac电脑上寻找一款相似Windows上手机助手的利用,几经辗转之下找到了HandShaker,十分好用,可却常常奔溃,尝试了各种形式,奔溃仍然一直产生。这款产品来自锤子科技,在18年曾经进行了保护,呈现这种状况也难能可贵。 但这么好的我的项目就这样失落了,切实有点惋惜。于是,我决定仿造一个进去,一方面满足本人的须要,另一方面思考到Mac平台与Linux平台始终没有一个很好的安卓手机助手利用,冀望它能够成为一个全能的安卓手机助手,不仅仅是HandShaker。 选型因为我的次要工作平台是macOS,首先必须反对的肯定是macBook,因而,我首先思考应用Swift进行开发。于是,我叫来了我在高灯安卓团队的一个小伙伴,也算是我的一个学生,跟他说了我的想法。 他倡议应用Flutter,理由是他想学学Flutter。我细推敲了一下,Flutter确实是一个不错的抉择,在过后,Flutter曾经反对了桌面平台,只是处于Beta阶段。当然当初仍然Beta阶段,只是Windows平台反对曾经来到了稳定版。 说干就干,因为我本人对Flutter的理解也简直为0,其实走了不少弯路。过后思考手机端和电脑端都应用Flutter进行开发,进行过程中发现,应用Flutter进行手机端开发反而会减少工作量,Flutter在很多中央的反对力度远远比不上原生。 思考再三,只管过后手机端曾经应用Flutter开发了肯定的性能,我还是决定齐全放弃掉,转而应用相熟的Kotlin进行从新开发。 而在桌面端,其实也走了不少弯路,在设计通信的时候,开始思考了TCP,前面发现TCP解决开发工作量过于费时,在中途又颠覆,转而应用http,而TCP只用于解决心跳服务。 在这两头,因为对Flutter的不相熟,也因为对这种工具类型产品的不相熟,走了不少弯路,这里就不赘述了,置信大家也不敢趣味。 命名命名是一个令人头疼的问题,过后拉了几个小伙伴一起头脑风暴,后果没有一个我称心的。最初,我思考应用EasyHandler这个名字。 这个名字始终连续到产品公布后期,思前想后,还是感觉太土。于是决定仿造苹果AirDrop取一个相似的名字。因而,AirController这个名字就来了。 Any way,接下来隆重地为大家介绍AirController这款产品。。 产品介绍这个产品的用法跟HandShaker简直是齐全一样的,然而暂不反对通过数据线连贯间接应用,目前只反对无线连接通信。 因而,咱们须要首先在手机端装置AirController利用。 1)关上以下链接,下载apk文件并装置: https://github.com/air-controller/air-controller-mobile/releases/latest 接下来装置桌面端AirController利用。 2)同样地,关上以下链接,下载对应平台安装包并装置: https://github.com/air-controller/air-controller-desktop/releases/latest 具体装置办法,如有疑难,可参考以下文档: https://github.com/air-controller/air-controller-desktop 3)最初,将手机与电脑连贯至同一网络,并在手机端关上AirController利用。 第一次关上会提醒获取一些权限,全副通过即可,该利用齐全开源,不必放心任何后门操作。 接下来,电脑端关上AirController就能够看到一个闪动的手机图标指向你以后的手机。 留神:这里的图标会闪动,这是为了定期检查手机端是否在线。 点击上方连贯按钮即可进入治理页面。 双击某一图片,可查看图片详情。 滑动鼠标滚轮,可放大或放大图片,应用键盘左右方向键可切换前/后一张图片,也可按Delete键删除以后图片。 在视频页面,双击某视频,会关上浏览器间接播放该视频 留神:这里对Safari浏览器的反对不太好,举荐应用Chrome浏览器。 在文件治理页面,能够抉择网格模式或列表模式查看文件列表,同样提供了丰盛的操作,请大家自行体验。 后记截止发稿当天,该产品桌面端最新版本0.2.2。目前,还处于比拟初期阶段,还有不少新性能正在布局中,冀望大家报以宽容的心态来对待这样一个产品,也心愿大家在我的项目页点击star反对我。 而如果你对我的项目原理感兴趣,欢送增加我的项目探讨群,一起来欢快地游玩。 交换QQ群: 329673958 微信公众号:欧阳锋工作室 Github:https://github.com/air-controller/air-controller-desktop

April 18, 2022 · 1 min · jiezi

关于flutter:淘特-Flutter-流畅度优化实践-二期

作者:谢伟(韦圣) 在上一篇《淘特 Flutter 晦涩度优化实际》中说到,尽管一期成果较为显著,但间隔极致的用户体验仍有不小的差距。去年,淘特端架构联结业务团队独特发动“根底链路极致体验优化”的我的项目,指标在时长与晦涩度方面取得极致体验,本文将为大家具体解析淘特 Flutter 晦涩度优化实际二期局部。优化成果首先,咱们简略回顾上一期优化后的成果, 在一期中,次要的优化措施集中在“业务最佳实际”,不须要改Engine、不须要造轮子,仍然获得不错的优化成果。证实Flutter在面对简单的业务场景时, 只有把握好足够的实践经验,仍然能放弃较好的性能体现。 但随着淘特的优化进入深水区,源自对极致用户体验的谋求及Native性能数据的赛跑,让咱们开始疾速从团体、业界排汇优良前辈的教训并自我冲破。最终,在实现了“Hummer引擎降级”、“自研ExternalImage图片库”、“自研FlowView高性能流式容器”等多项重点技术冲破后,获得的二期成绩如下: 注:晦涩度随着业务迭代、测试口径的变动存在肯定稳定。以上数据来自:淘特4.14.0 双端慢滑测试口径(滑动速率参考下方录屏) 从体感录屏来看有两大晋升: 晦涩度再度晋升,双端慢滑根本无卡顿毁灭iOS大卡顿问题Android录屏比照(右边优化前、左边优化后) 查看视频请点击:淘特 Flutter 晦涩度优化实际 · 二期iOS录屏比照(右边优化前、左边优化后) 查看视频请点击:淘特 Flutter 晦涩度优化实际 · 二期优化过程中关键技术引擎降级 Hummer置信不少同学都听过Hummer引擎(UC Flutter定制引擎),得益于UC丰盛的渲染性能优化教训及AliFlutter社区生态,淘特在充沛调研后决定接入Hummer,但同时接入的过程中,淘特又与Hummer遇见了很多简单场景须要解决的晦涩度、加载耗时、内存等各方面的问题。 首先降级Hummer引擎带来的晦涩度优化次要在以下4个方面,具体原理参考Hummer引擎介绍,本文偏重讲淘特理论解决的问题与解法,及降级的比照成果。 上面是引擎降级的最终成果: 淘特Android4.4.0基线 淘特iOS4.6.0基线 双端在帧率、卡顿率都有了显著的晋升,尤其是iOS端解决了Feeds流在iPhone6下容易大卡顿的问题。而降级引擎对淘特影响最大的就是外接图片库的降级。 Flutter图片库比照以晦涩度为例, 图片库的抉择是至关重要的。因为Hummer引擎中迁徙原有CDNImage(旧引擎耦合Engine的外接图片库计划)的老本过大,这迫使淘特寻找新的“非侵入引擎的图片库计划”。 最开始咱们尝试用NetworkImage拿到了第一手的体验数据。晦涩度晋升非常明显,但NetworkImage的有余只能满足短期疾速灰度,此时FImage(外接纹理的图片库计划)呈现在咱们背后,无疑是一个十分高效的解决方案,但实测后发现低端机晦涩度较之前略有下滑,这让咱们开始探寻更适宜淘特的图片库计划。 最终自研ExternalImage, 在晦涩度和加载耗时比照中均获得超过CDNImage的成果。 以下是团体Flutter次要的图片库计划比照: 以下为Hummer下ExternalImage与外接纹理计划帧耗时性能图,咱们发现外接纹理计划的Raster线程帧耗时会显著高于原生Image组件计划,起因初步剖析是过多的Texture使低端机Raster耗时负载过大, 而因为frame_time近似等于max(ui,raster), 所以当raster帧耗时超过16ms也会造成理论体感FPS的升高。于是就有了下一节的ExternalImage图片库。 淘特ExternalImage图片库 下面是一张ExternalImage的总体架构图, 其基于FFI形式加载来自Native的像素数据,从官网Image组件登程,经Provider发动Channel调用,拿到图片返回后果后触发decode、setState等流程, 绿色代表申请链路,黄色代表回传链路。 核心技术点如下: 淘特Flow-View轻量级流式容器列表滚动始终是Flutter晦涩度优化的重点场景,在未取得Hummer引擎优化前, 晦涩度优化一度遇到瓶颈。在Flutter官网流式容器设计理念中,在列表滚动时, Element被视为十分轻量级的组件,没有反对复用。在列表增减元素时,Widget被认为十分轻量, 未做部分刷新。这在淘特理论简单的Feeds业务场景下,受到了严厉挑战。咱们联合业务个性,自研了一套轻量级流式容器计划Flow-View。 次要反对2个个性: 部分刷新, 将使分页加载更多无需反复build已有的itemWidget;Element/RenderObject复用, 将使滚动插入新元素时效率更高。FlowView部分刷新 咱们首先看上图右侧示意图,在部分刷新场景下,右边未优化前增加新元素将setState触发整个列表Rebuild。左边优化后将只对新增的2个元素执行插入操作,已有的元素无需Rebuild。 左侧为源码细节,通过在SliverMultiBoxAdaptorElement.update办法中,通过滚动到底部,且newDelegate.childCount>oldDelegate判断为加载更多场景执行部分刷新(即插入新的元素)。 FlowView Element、RenderObject复用 同样先看上图右侧示意图,在滚动场景下,当新的元素12、13行将入屏时, 右边未优化前将创立全新的Element、RenderObject。左边优化后新元素12、13将复用顶部移出的0、1元素的Element、RenderObject。做到循环利用,效率更高。 左侧为源码细节,当获取新插入的item时,通过在SliverMultiBoxAdaptorElement.createChild办法中,未优化前_childElements[index]=null将触发Element、RenderObjec新建,优化后将先依据新元素的类型找是否有可复用的元素,再触发updateChild, 若缓存不为空,则会执行didUpdateWidget逻辑。 ...

April 6, 2022 · 1 min · jiezi

关于flutter:在-Flutter-和-Dart-中取消-Future-的-3-种方法

作者:坚果 公众号:"大前端之旅" 华为云享专家,InfoQ签约作者,阿里云专家博主,51CTO博客首席体验官,开源我的项目GVA成员之一,专一于大前端技术的分享,包含Flutter,小程序,安卓,VUE,JavaScript。 本文将疏导您理解在 Flutter 和 Dart 中勾销 future 的 3 种不同办法。 应用异步包(举荐)async包由 Dart 编程语言的作者开发和公布。它提供了dart:async格调的实用程序来加强异步计算。能够帮忙咱们勾销Future的是CancelableOperation类: var myCancelableFuture = CancelableOperation.fromFuture( Future<T> inner, { FutureOr onCancel()? })// call the cancel() method to cancel the futuremyCancelableFuture.cancel();为了更分明,请参阅上面的理论示例。 残缺示例利用预览 咱们要构建的应用程序有一个浮动按钮。按下此按钮时,将开始异步操作(这须要 5 秒能力实现)。按钮的背景从靛蓝变为红色,其标签从“开始”变为“勾销”,当初您能够应用它来勾销Future。 如果您在Future实现前 5 秒内点击勾销按钮,屏幕将显示“Future已被勾销”。如果您什么都不做,则 5 秒后屏幕将显示“Future completed”。一个演示价值超过一千字: 代码1.通过执行以下操作装置异步包: flutter pub add async而后运行: flutter pub get2.main.dart 中的残缺源代码(附解释): // main.dartimport 'package:flutter/material.dart';import 'package:async/async.dart';void main() { runApp(const MyApp());}class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return MaterialApp( // Remove the debug banner debugShowCheckedModeBanner: false, title: '大前端之旅', theme: ThemeData( primarySwatch: Colors.indigo, ), home: const HomePage()); }}class HomePage extends StatefulWidget { const HomePage({Key? key}) : super(key: key); @override _HomePageState createState() => _HomePageState();}class _HomePageState extends State<HomePage> { // this future will return some text once it completes Future<String?> _myFuture() async { await Future.delayed(const Duration(seconds: 5)); return 'Future completed'; } // keep a reference to CancelableOperation CancelableOperation? _myCancelableFuture; // This is the result returned by the future String? _text; // Help you know whether the app is "loading" or not bool _isLoading = false; // This function is called when the "start" button is pressed void _getData() async { setState(() { _isLoading = true; }); _myCancelableFuture = CancelableOperation.fromFuture( _myFuture(), onCancel: () => 'Future has been canceld', ); final value = await _myCancelableFuture?.value; // update the UI setState(() { _text = value; _isLoading = false; }); } // this function is called when the "cancel" button is tapped void _cancelFuture() async { final result = await _myCancelableFuture?.cancel(); setState(() { _text = result; _isLoading = false; }); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('大前端之旅')), body: Center( child: _isLoading ? const CircularProgressIndicator() : Text( _text ?? 'Press Start Button', style: const TextStyle(fontSize: 28), ), ), // This button is used to trigger _getDate() and _cancelFuture() functions // the function is called depends on the _isLoading variable floatingActionButton: ElevatedButton( onPressed: () => _isLoading ? _cancelFuture() : _getData(), child: Text(_isLoading ? 'Cancel' : 'Start'), style: ElevatedButton.styleFrom( padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 30), primary: _isLoading ? Colors.red : Colors.indigo), ), ); }}应用 timeout() 办法这种办法既疾速又简略。然而,它不是很灵便。 ...

April 5, 2022 · 3 min · jiezi

关于flutter:Flutter接入字节跳动穿山甲小说视频内容合作

最近字节凋谢了内容输入sdk,能够间接在利用中插入小说、视频内容。应小伙伴的需要开发了flutter_pangrowth插件,不便在flutter中间接应用字节提供的小说、视频等内容。 体验demo仓库地址 阐明应用flutter_pangrowth插件,必须先接入穿山甲广告插件flutter_unionad,不然无奈显示广告 接入文档Androidios本地环境[✓] Flutter (Channel stable, 2.5.0, on macOS 11.6 20G165 darwin-x64, locale zh-Hans-CN)[✓] Android toolchain - develop for Android devices (Android SDK version 30.0.3)[✓] Xcode - develop for iOS and macOS[✓] Chrome - develop for the web[✓] Android Studio (version 2020.3)[✓] VS Code (version 1.60.1)[✓] Connected device (4 available)集成步骤1、pubspec.yamlflutter_pangrowth: ^1.0.0//或者2、引入import 'package:flutter_pangrowth/flutter_pangrowth.dart';应用1、SDK初始化⚠️留神 :初始化sdk前,必须先调用用flutter_unionad的初始化办法,不然无奈加载广告 await PangrowthNovel.registerNovel( //接入小说SDK的App的英文名 必填 appName: "appName", ////接入小说SDKApp的版本名称 必填 appVersionName: "1.0.0", //接入小说SDK App的版本号 必填 appVersionCode: 1, //埋点上传时的渠道号维度。开发者自定义字符串即可(倡议不要蕴含test)。选填 channel: "test", ////appid 必填 andoridAppId: "302043", iosAppId: "299886", //是否显示日志 debug: true, );2、关上小说主页await PangrowthNovel.openNovelPage();3、NovelEntity阐明{ "code": 0,//1胜利 0失败 "msg": "",//谬误提醒 "data": [//返回小说数组 { "bookId": "6806002909138914318",//小说id "bookName": "",//小说名字 "readUrl": "",//浏览地址 "thumbUrl": "",//小说封面 "novelDetail": ""//小说具体信息json(因为android、ios数据格式、后续跳转所需参数等都不雷同,所以不做解决间接返回json数据,开发者可依据需要在我的项目中自行解析) } ]}4、获取浏览历史NovelEntity novel = await FlutterPangrowth.getNovelHistory();5、获取启动举荐书籍列表NovelEntity novel = await FlutterPangrowth.getNovelRecommendV1( size: 10,//返回数据数量 )6、获取Feed举荐书籍列表NovelEntity novel = await FlutterPangrowth.getNovelRecommendFeed( size: 10,//返回数据数量 )7、小说显示上报await PangrowthNovel.reportRecentNovelShow( type: result.type,//NovelEntity 中type字段 book: result.novelDetail,//NovelEntity 中novelDetail字段);8、关上小说页面await PangrowthNovel.openNovelPageWithConfig( type: result.type,//NovelEntity 中type字段 book: result.novelDetail,//NovelEntity 中novelDetail字段);9、获取当日浏览时长单位:毫秒 ...

April 2, 2022 · 1 min · jiezi

关于flutter:Nginx部署Flutter-Web

创立我的项目关上Andorid Studio创立一个flutter我的项目 打包我的项目flutter build web执行实现后在build文件下会生成一个web文件夹, 应用Nginx部署我的项目上传生成的web文件夹到服务器html目录下,并且配置config文件 server { listen 443 ssl; server_name gsou.gstory.cn; ssl_certificate /ssl/gsou.gstory.cn_bundle.crt; ssl_certificate_key /ssl/gsou.gstory.cn.key; ssl_session_timeout 5m; ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4; ssl_protocols TLSv1.2 TLSv1.3; ssl_prefer_server_ciphers on; location / { root /usr/share/nginx/html/gsou; index /index.html index.htm; }}重启nginx失效 nginx -s reload//dockerdocker restart nginx这个时候就能够通过本人的域名或者ip拜访到部署到服务端的Flutter web了。 示例分享一个flutter开发动态导航网站 GSou

April 2, 2022 · 1 min · jiezi

关于flutter:Flutter插件上传失败

最近公布插件发现因为墙的起因导致插件始终上传失败,分享一下解决方案。我应用的是ss,在ss选项设置里勾选本地代理并查看端口号比方我的端口是1080 window在终端中应用以下命令 set http_proxy=http://127.0.0.1:1080set http_proxys=http://127.0.0.1:1080如果不想应用,应用以下命令去掉终端代理 set http_proxy=set http_proxys=mac在终端中应用以下命令 export http_proxy=http://127.0.0.1:1080export http_proxys=http://127.0.0.1:1080如果不想应用,应用以下命令去掉终端代理 export http_proxy=export http_proxys=验证是否代理胜利curl -v http://www.google.com从新公布测试 flutter packages pub publish --server=https://pub.dartlang.org --dry-run公布 flutter packages pub publish --server=https://pub.dartlang.org

April 2, 2022 · 1 min · jiezi

关于flutter:Flutter应用集成头条穿山甲广告

近期我的项目中须要用到穿山甲广告,看了几个插件,发现满足不了本人的需要,我的项目中须要用到的广告都须要应用原生view做嵌入。所以本人写了一个插件来实现相干的广告。我的项目仓库flutter_unionad 集成步骤1、SDK初始化await FlutterUnionad.register( androidAppId: "5098580", //穿山甲广告 Android appid 必填 iosAppId: "5098580", //穿山甲广告 ios appid 必填 useTextureView: true, //应用TextureView控件播放视频,默认为SurfaceView,当有SurfaceView抵触的场景,能够应用TextureView 选填 appName: "unionad_test", //appname 必填 allowShowNotify: true, //是否容许sdk展现告诉栏提醒 选填 allowShowPageWhenScreenLock: true, //是否在锁屏场景反对展现广告落地页 选填 debug: true, //是否显示debug日志 supportMultiProcess: true, //是否反对多过程,true反对 选填 directDownloadNetworkType: [ FlutterUnionadNetCode.NETWORK_STATE_2G, FlutterUnionadNetCode.NETWORK_STATE_3G, FlutterUnionadNetCode.NETWORK_STATE_4G, FlutterUnionadNetCode.NETWORK_STATE_WIFI ]); //容许间接下载的网络状态汇合 选填 2、获取SDK版本await FlutterUnionad.getSDKVersion();3、申请权限 FlutterUnionad.requestPermissionIfNecessary( callBack: FlutterUnionadPermissionCallBack( notDetermined: () { print("权限未确定"); }, restricted: () { print("权限限度"); }, denied: () { print("权限回绝"); }, authorized: () { print("权限批准"); }, ), );Android获取定位、照片权限,只返回胜利 ...

April 2, 2022 · 3 min · jiezi

关于flutter:Flutter-Provider状态管理框架

一、简介在Flutter开发中,或多或少的都会设计到页面的多状态治理,如果大家对Flutter技术比拟相熟的话,那么应该晓得上面的一些状态治理框架,像Bloc,Getx我都用过,整体来说再状态治理不是很简单的状况下还是能够的。 接下来,咱们来看一下Flutter官网举荐的状态治理框架Provider是如何应用的。Flutter 针对不同类型对象提供了多种不同的 Provider;Provider 也是借助了 InheritWidget,将共享状态放到顶层 MaterialApp 之上; setState能刷新widget子树,刷新范畴太大,并且须要把数据对象传递到子类。InheritedWidget不必传递数据对象,通过context.dependOnInheritedWidgetOfExactType<ShareDataWidget>();获取父类的数据。然而刷新范畴大,只能由上而下传递。Provider能够实现部分刷新。只有数据对象扭转,UI能主动变动,实现响应式编程。屏蔽刷新逻辑,实现响应式数据与UI的绑定。无论是子类或父类扭转数据都能刷新绑定的UI。 二、根本应用应用之前,须要先在pubspec.yaml增加provider dependencies: flutter: sdk: flutter provider: ^6.0.22.1 Provider根本应用Provider是一款基于数据流的观察者模式,应用的第一步就是新建一个继承自ChangeNotifier的数据管理类。上面,咱们来看一下官网的例子应用Provider形式如何实现。 import 'package:flutter/cupertino.dart';class CountProviderModel extends ChangeNotifier { int _count = 0; int get count => _count; void increment() { print("increment"); _count++; notifyListeners(); }}在CountProviderModel类中,咱们定义了有一个数据减少的办法,最初还调用notifyListeners发送告诉。接着,咱们新建一个测试页面,该页面的根部应用ChangeNotifierProvider组件进行包裹,须要刷新的中央应用Consumer组件进行包裹,用于生产 import 'package:flutter/cupertino.dart';import 'package:flutter/material.dart';import 'package:provider/provider.dart';import 'count_provider.dart';class ProviderPage extends StatelessWidget { const ProviderPage({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return ChangeNotifierProvider<CountProviderModel>( create: (_) => CountProviderModel(), builder: (context, child) { return Scaffold( appBar: AppBar( title: const Text("ProviderPage"), ), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ const Text('You have pushed the button this many times:'), Consumer<CountProviderModel>( builder: (context, notifier, child) { return Text("${notifier.count}",style: const TextStyle( fontSize: 24, ), ); }, ), ], ), ), floatingActionButton: FloatingActionButton( onPressed: () => context.read<CountProviderModel>().increment(), tooltip: 'Increment', child: const Icon(Icons.add), ), ); }, ); }}最初,咱们批改一下Flutter我的项目的入口main文件。 ...

March 30, 2022 · 4 min · jiezi

关于flutter:Flutter-正在被悄悄放弃吗

恰恰相反,不论在国外还是国内,Flutter正被越来越多的企业和开发者所承受。 在国外Github Stack Overflow 不论在Github还是Stack Overflow,显著能看到Flutter的热度在晋升,也有泛滥的硅谷大厂在热烈拥抱flutter。 在国内国内也是如此,从大厂到中小企业,越来越多的企业和开发者开始学习、应用flutter,并且曾经有一部分开始从RN转到了flutter。 在大公司,应用flutter的产品有: 淘宝闲鱼微信同花顺百度网盘WPS Office等等等等... ...在飞援上,越来越多的中小客户找到咱们,寻找可能近程兼职的flutter开发者,或者外包flutter开发我的项目。 正所谓春江水暖鸭先知,飞援上的客户需要趋势和开发者趋势通知咱们,Flutter正在被宽泛承受,进入了更大的空间。

March 30, 2022 · 1 min · jiezi

关于flutter:在-Flutter-使用-GetX-对话框

在 Flutter 应用 GetX 对话框 原文https://medium.flutterdevs.co...参考https://pub.dev/packages/get注释理解如何在您的 Flutter 应用程序应用 GetX 创立一个对话框 在 Flutter 应用 GetX 对话框 是挪动应用程序的根本组成部分。他们帮忙传递正告和重要信息,以及做具体的流动。当 Flutter 开发人员在 Flutter 制作一个对话框时,它利用上下文和生成器制作一个对话框。然而,对于开发人员来说,利用上下文和构建器来造就 Dialogs 是不适合的。 在本文中,咱们将摸索在 Flutter 应用 GetX 的对话框。咱们还将实现一个演示程序,并理解如何应用您的 Flutter 应用程序的获取包创立对话框。 获取 | Flutter PackageGetX 是一个超轻和弱小的解决方案 Flutter 。它联合了高性能的状态治理,智能.. https://pub.dev/packages/get Introduction:简介:当咱们须要显示任何相似表单的内容时,咱们能够创立这个对话框,它波及 Flutter 的 GetX 库。咱们能够使对话框利用 GetX 的根本代码和非常简单的使一个对话框。它没有利用上下文和生成器来创立对话框。 是 Flutter 问题的附加轻量强解。它退出了精英的性能状态治理、智能依赖注入治理和路由治理。 演示模块: 这个演示视频展现了如何在 Flutter 中创立一个对话框,并展现了如何应用您的 Flutter 应用程序中的 get 包来工作,以及应用不同的属性。它会显示在你的设施上。 Constructor:要应用 Get.defaultDialog () ,须要调用上面的构造函数:Future<T?> defaultDialog<T>({ String title = "Alert", EdgeInsetsGeometry? titlePadding, TextStyle? titleStyle, Widget? content, EdgeInsetsGeometry? contentPadding, VoidCallback? onConfirm, VoidCallback? onCancel, VoidCallback? onCustom, Color? cancelTextColor, Color? confirmTextColor, String? textConfirm, String? textCancel, String? textCustom, Widget? confirm, Widget? cancel, Widget? custom, Color? backgroundColor, bool barrierDismissible = true, Color? buttonColor, String middleText = "Dialog made in 3 lines of code", TextStyle? middleTextStyle, double radius = 20.0, List<Widget>? actions, WillPopCallback? onWillPop, GlobalKey<NavigatorState>? navigatorKey,})Properties:有一些 Get.defaultDialog ()的属性:> title: 此属性用于对话框的题目。默认状况下,题目为“ Alert”。> titleStyle: 此属性用于应用 TextStyle 给题目文本赋予的款式。> content: 在这个属性中用于给出对话框的内容,并且应该应用 Widget 给出内容。> middleText: 此属性用于对话框的两头文本。如果咱们也利用内容,那么内容小部件数据将被收获。> barrierDismissible: 如果咱们想通过单击对话框内部来敞开对话框,那么这个属性的值应该为 true else false。默认状况下,它的值为 true。> middleTextStyle: 此属性用于应用 TextStyle 给两头文本赋予的款式。> radius: 在此属性中应用的是提供的对话框的半径。默认状况下,它的值为 20。> backgroundColor: 在这个属性中用作对话框的背景色彩。Implementation:第一步: 增加依赖项将依赖项增加到 pubspec ー yaml 文件。dependencies: flutter: sdk: flutter get: ^4.6.1第二步: 导入import 'package:get/get.dart';第三步: 在应用程序的根目录中运行 flutter 软件包。如何实现 dart 文件中的代码:你须要别离在你的代码中实现它: ...

March 28, 2022 · 3 min · jiezi

关于flutter:一个编译问题带你了解-Flutter-Web-的打包构建和分包实现

Flutter Web 作为 Flutter 框架中最非凡的平台,因为 Web 平台的特殊性,它默认就具备了两种不同的渲染引擎: html : 通过平台的 canvas 和 Element 实现布局绘制;canvaskit : 通过 Webassembly + Skia 绘制控件;尽管都晓得 canvavskit 更靠近 Flutter 的设计理念,然而因为它构建的 wasm 文件大小和字体加载等问题带来的老本思考,业界个别会选用更轻量化的 html 引擎,而明天的问题也是基于 html 引擎来开展。 一、deferred-components咱们都晓得 Flutter Web 打包构建后的 main.dart.js 文件会很大,所以个别都会采纳一些办法来对包大小进行优化,而其中最罕用的形式之一就是应用 deferred-components 。 对于 deferred-components 官网起初次要是用于反对 Android App Bundle 上的动静公布,而通过适配后这项能力被很好地拓展到了 Web 上,通过 deferred-components 能够不便地依据需要来拆分 main.dart.js 文件的大小。 当然这里并不是介绍如何应用 deferred-components ,而是在应用 deferred-components 时,遇到了一个对于 Flutter Web 在打包构建上的神奇问题。 首先,代码如下图所示,能够看到,这里次要是通过 deferred as 关键字将一个一般页面变成 deferred-components ,而后在路由关上时通过 libraryFuture 加载后渲染页面。 这里省略了无关的 yaml 文件代码,那么上述简略的代码,大家感觉有没有什么问题 ? ...

March 26, 2022 · 2 min · jiezi

关于flutter:Flutter事件响应源码分析

Flutter作为一个UI框架,自身也有本人的事件处理形式,本文次要论述触摸事件从native传递到Flutter后是如何被widget辨认以及散发的。至于native零碎是如何监听触摸事件以及传递事件到Flutter,感兴趣的能够本人去理解下不同的宿主零碎解决的形式也是不同的。 事件处理流程Flutter中对触摸事件的解决大抵能够分为以下几个阶段: 监听事件的到来对widget是否能响应事件进行命中测试将事件分发给通过命中测试的widget后续将触摸事件间接称为event 监听事件event是由native零碎通过音讯通道传递到Flutter中的,因而Flutter必然会有对应的监听办法或者回调,从Flutter启动流程的源码中能够在mixin GestureBinding查看到上面代码: @override void initInstances() { super.initInstances(); _instance = this; window.onPointerDataPacket = _handlePointerDataPacket; } 其中window.onPointerDataPacket正是监听event的回调,window是 Flutter 连贯宿主操作系统的接口,其中蕴含了以后设施和零碎的一些信息以及Flutter Engine的一些回调,上面展现了其局部属性。其余属性能够自行查看官网文档,留神这里的window不是dart:html规范库里window 类。 class Window { // 以后设施的DPI,即一个逻辑像素显示多少物理像素,数字越大,显示成果就越精密保真。 // DPI是设施屏幕的固件属性,如Nexus 6的屏幕DPI为3.5 double get devicePixelRatio => _devicePixelRatio; // Flutter UI绘制区域的大小 Size get physicalSize => _physicalSize; // 以后零碎默认的语言Locale Locale get locale; // 以后零碎字体缩放比例。 double get textScaleFactor => _textScaleFactor; // 当绘制区域大小扭转回调 VoidCallback get onMetricsChanged => _onMetricsChanged; // Locale发生变化回调 VoidCallback get onLocaleChanged => _onLocaleChanged; // 零碎字体缩放变动回调 VoidCallback get onTextScaleFactorChanged => _onTextScaleFactorChanged; // 绘制前回调,个别会受显示器的垂直同步信号VSync驱动,当屏幕刷新时就会被调用 FrameCallback get onBeginFrame => _onBeginFrame; // 绘制回调 VoidCallback get onDrawFrame => _onDrawFrame; // 点击或指针事件回调 PointerDataPacketCallback get onPointerDataPacket => _onPointerDataPacket; // 调度Frame,该办法执行后,onBeginFrame和onDrawFrame将紧接着会在适合机会被调用, // 此办法会间接调用Flutter engine的Window_scheduleFrame办法 void scheduleFrame() native 'Window_scheduleFrame'; // 更新利用在GPU上的渲染,此办法会间接调用Flutter engine的Window_render办法 void render(Scene scene) native 'Window_render'; // 发送平台音讯 void sendPlatformMessage(String name, ByteData data, PlatformMessageResponseCallback callback) ; // 平台通道音讯解决回调 PlatformMessageCallback get onPlatformMessage => _onPlatformMessage; ... //其它属性及回调 } 当初咱们有了event在Flutter端的入口函数 _handlePointerDataPacket,通过这个函数咱们能够查看Flutter接管到event后是如何操作的,比较简单咱们间接看下代码。 ...

March 23, 2022 · 5 min · jiezi