重庆分公司,新征程启航
为企业提供网站建设、域名注册、服务器等服务
Divider的构造方法
成都创新互联公司网站建设由有经验的网站设计师、开发人员和项目经理组成的专业建站团队,负责网站视觉设计、用户体验优化、交互设计和前端开发等方面的工作,以确保网站外观精美、成都做网站、成都网站制作、成都外贸网站建设易于使用并且具有良好的响应性。
可以看出Divider组件只有5个属性,一目了然,使用也非常简单
indent: 起点缩进距离
endIndent: 终点缩进距离
color: 分割线颜色
height: 分割线区域的高度,并非分割线的高度
thickness: 分割线的厚度,真正的分割线的高度
注意:
1.当height为null的时候会去查看 DividerThemeData.space的高度,如果同样为null,则默认分割线区间为16
2.如果不设置thickness的高度,分割线默认为1px且居中显示
3.如果想设置真实的分割线高度,需要把height和thickness设置为一样高即可。
4.flutter还提供了竖直方向上的分割线组件VerticalDivider,用法一至,不在赘述。
Demo
Dart的 IO 库包含了文件读写的相关类,它属于 Dart 语法标准的一部分,所以通过 Dart IO 库,无论是 Dart VM 下的脚本还是 Flutter,都是通过 Dart IO 库来操作文件的,不过和 Dart VM 相比,Flutter 有一个重要差异是文件系统路径不同,这是因为Dart VM 是运行在 PC 或服务器操作系统下,而 Flutter 是运行在移动操作系统中,他们的文件系统会有一些差异。
Android 和 iOS 的应用存储目录不同, PathProvider 插件提供了一种平台透明的方式来访问设备文件系统上的常用位置。该类当前支持访问两个文件系统位置:
File代表一个整体的文件,他有三个构造函数,分别是:
文件读取本身有两种形式,一种是文本,一种是二进制。
2.2.1 读取文本内容
如果是文本文件,File提供了readAsString、readAsLines、readAsStringSync、readAsLinesSync方法,读取文本内容
readAsString 一次性读取所有文本
readAsLines 一行行的读取文本
结果返回的是一个List,list中表示文件每行的内容
readAsStringSync、readAsLinesSync同步读取文本
2.2.2 读取二进制内容
如果文件是二进制,那么可以使用readAsBytes或者同步的方法readAsBytesSync:
dart中表示二进制有一个专门的类型叫做Uint8List,他实际上表示的是一个int的List。
上面提到的读取方式,都是一次性读取整个文件,缺点就是如果文件太大的话,可能造成内存空间的压力。
所以File为我们提供了另外一种读取文件的方法,流的形式来读取文件.
示例
dart提供了open和openSync两个方法来进行随机文件读写:
写入和文件读取一样,可以一次性写入或者获得一个写入句柄,然后再写入。
一次性写入的方法有四种,分别对应字符串和二进制
句柄形式可以调用openWrite方法,返回一个IOSink对象,然后通过这个对象进行写入:
默认情况下写入是会覆盖整个文件的,但是可以通过下面的方式来更改写入模式:
虽然dart中所有的异常都是运行时异常,但是和java一样,要想手动处理文件读写中的异常,则可以使用try,catch:
我们还是以计数器为例,实现在应用退出重启后可以恢复点击次数。 这里,我们使用文件来保存数据:
1.引入PathProvider插件;在pubspec.yaml文件中添加如下声明:
执行 flutter pub get
2.实现如下
参考:
listview三种构造方法
直接添加子控件
//题外话,有关itemBuilder可以采用变量widget传入
在Tree中从上往下高效传递数据的基类widget , 定义为:abstract class InheritedWidget extends ProxyWidget
Flutter的响应式开发与React类似,数据都是自顶向下的。
假设有祖先组点A,中间经过结点B, C,然后到结点D,D需要从A中获取数据f,那按照自顶向下数据流转,f需要依次传递给B及C,最后才到C。这样开发极为不灵活,成本也比较高。所有Flutter需要有跨结点(只能是祖先后代节点,不能跨兄弟节点)高效传递数据的方案。
大体意思如下:
InheritedWidget 是在树中高效向下传递信息的基类部件;
调用[BuildContext.inheritFromWidgetOfExactType]方法可以从 BuildContext 中获取到最近的 InheritedWidget 类型的实例;
在 InheritedWidget 类型的控件被引用,也就是调用过 inheritFromWidgetOfExactType 方法后,当 InheritedWidget 自身状态改变时,会导致引用了 InheritedWidget 类型的子控件重构(rebuild)。
这里随便定义一个人 Person 类。
创建一个类继承 InheritedWidget,并实现 updateShouldNotify 方法。
之前说到调用[BuildContext.inheritFromWidgetOfExactType]方法可以从 BuildContext 中获取到最近的 InheritedWidget 类型的实例,所以此处定义一个静态的 of 方法,通过传入的 context 获取到最近的 InheriedDataWidget 实例。
1.定义数据模型
这里随便定义一个 Person 类。
2.自定义 InheritedWidget 控件类
创建一个类继承 InheritedWidget,并实现 updateShouldNotify 方法。
之前说到调用[BuildContext.inheritFromWidgetOfExactType]方法可以从 BuildContext 中获取到最近的 InheritedWidget 类型的实例,所以此处定义一个静态的 of 方法,通过传入的 context 获取到最近的 InheriedDataWidget 实例。
3.InheriedDataWidget 的使用
InheriedDataWidget 使用起来也很简单,它本身也是一个控件,只要在任意一个页面的子控件调用其构造方法就行,这里我们定义一个形如的 Widget 树。
WidgetA 是一个 StatefulWidget 类型的控件,可以调用 setState 刷新,如果是继承人 Stateless 类型的控件,那我们也可以通过 Stream 或者其他方式刷新数据,感兴趣的请看[什么是 Stream? Dart
WidgetA1_1 类
WidgetA1_2 类
WidgetA1_3 类
当我们点击 floatingActionButton 的时候,WidgetA1, WidgetA1_1, WidgetA1_2 的控件都会更新 Person 的信息,而且每点 floatingActionButton 一次, 当我们点击 floatingActionButton 的时候,WidgetA1, WidgetA1_1, WidgetA1_2 的控件都会更新 Person 的信息,而且每点 floatingActionButton 一次,都会输出:
如果我们试图在和 WidgetA 的同一层级的兄弟节点去访问 InheriedDataWidget 的 Person 数据,是不行的,因为父节点中并没有插入 InheriedDataWidget。
把 WidgetB 和 WidgetA 保持同一节点
这也体现了 Inheried(遗传) 这一单词的特性,遗传只存在于父子。兄弟不存在遗传的关系。
这种数据共享的方式在某些场景还是很有用的,就比如说全局主题,字体大小,字体颜色的变更,只要在 App 根层级共享出这些配置数据,然后在触发数据改变之后,所有引用到这些共享数据的地方都会刷新,这换主题,字体是不是就很轻松,事实上 Theme.of(context).primaryColor 之流就是这么干的。
以上就是有关InheritedWidget的使用。
自己也是从事Android开发5年有余了;整理了一些Android开发技术核心笔记和面经题纲,有关更多Android开发进阶技术资料、面经题纲、核心技术笔记; 想要进阶自己、拿高薪的同学请私信我回复“核心笔记”或“面试”领取!
Flutter中Widget,State和BuildContext的概念是每个Flutter开发人员需要完全理解的最重要概念之一。这里先讲解一下Widget以及Widget。三者之间的关系会在最后一篇总结一下。
Widget类在Flutter中是非常重要的,继承自Widget类的有PreferredSizeWidget、ProxyWidget、RenderObjectWidget、StatefulWidget、StatelessWidget。我们日常使用的绝大部分widget都是继承自Widget类,查看Widget类源码,内部实现非常简单,构造函数如下:
在flutter中构建APP是由widget树构建起来的,所以这个key的作用是用来控制在widget树中替换widget的时候使用的。其中Key类是Widget、Element以及SemanticsNode的唯一标识符,继承自Key的还有LocalKey以及GlobalKey。详细可以去framework.dart文件查看相关源码及说明。
在Flutter中,我们平时自定义的widget,一般都是继承自StatefulWidget或StatelessWidget(并不是只有这两种),这两种widget也是目前最常用的两种。如果一个控件自身状态不会去改变,创建了就直接显示,不会有色值、大小或者其他属性的变化,这种widget一般都是继承自StatelessWidget,常见的有Container、ScrollView等。如果一个控件需要动态的去改变或者相应一些状态,例如点击态、色值、内容区域等,那么一般都是继承自StatefulWidget,常见的有CheckBox、AppBar、TabBar等。两者的差别在于是否有状态。
对于StatelessWidget,build方法会在如下三种情况下调用:
我们在创建State的时候可以看到和StatefulWidget相似的build方法,也就是说我们也可以获得一个BuildContext,在使用StatefulWidget.createState创建它们之前以及在调用initState之前,框架将State对象与BuildContext关联起来,该关联是永久的:State对象永远不会改变它的BuildContext(但是BuildContext本身可以在控件树中移动)。后面讲解一下这个BuildContext对象在整个程序中什么角色
State的作用有两点:
State的生命周期有四种状态:
完整生命周期如下:
当控件的配置被更改时会调用State.didUpdateWidget方法,此时框架会重新绘制控件。你也可以使用State.setState方法在状态发生变化时通知框架,告诉框架该对象的内部状态已经改变,框架接到通知后也会重新绘制控件。
State中比较重要的一个方法是setState,当修改状态时,widget会被更新。比方说点击CheckBox,会出现选中和非选中状态之间的切换,就是通过修改状态来达到的。查看setState源码,在一些异常的情况下将会抛出异常:
markNeedsBuild内部,则是通过标记element为diry,在下一帧的时候重建(rebuild)。可以看出setState并不是立即生效,它只是将widget进行了标记,真正的rebuild操作,则是等到下一帧的时候才会去进行。
StatefulWidget的两个主要类别:
在我的小部件的生命周期中,我是否需要考虑一个将要更改的变量,何时更改,将强制重建小部件?
如果问题的答案是肯定的,那么您需要一个有状态的小部件,否则,您需要一个无状态小部件。
比如:
当我们同时为手机和平板适配编写 app 针对不同屏幕尺寸进行 UI 布局或当用户偏好设置较大字号或是想要最大限度等减少动画等;此时就需要 MediaQuery 来帮我们获取所用设备的信息以及用户设置的偏好信息;
MediaQuery 一直存在于 WidgetsApp 和 MaterialApp 中, MediaQuery 继承自 InheritedWidget 是一个单独的 Widget ,但一般通过 MediaQuery.of(context) 来获取相关信息;
当相关信息发生变化,例如屏幕旋转等时,屏幕中 Widget 会重新构建,以保持最新状态;我们可以通过 MediaQuery 构造函数和提供的静态方法手动设置对应的相关信息;
MediaQueryData 包含关于媒介的相关信息;一般通过 MediaQuery.of(context) 获取;
size 为媒介的尺寸大小,以逻辑像素为单位;
devicePixelRatio 为像素密度;与设备物理像素有关,与横竖屏等无关;
orientation 为横竖屏, Orientation.landscape 为横屏, Orientation.portrait 为竖屏;
textScaleFactor 为
每个逻辑像素的字体像素数,小菜理解为字体的像素比;注意,小菜设置了默认字体像素密度为标准的 1.2 倍之后调整设备系统字号,其 1.2 倍依旧是以标准字号为基础扩大 1.2 倍;
platformBrightness 为当前设备的亮度模式;注意调整屏幕亮度并不会改变该模式,与当前系统支持的黑暗模式和明亮模式相关;
alwaysUse24HourFormat 为当前设备是否为 24 小时制;
accessibleNavigation 为是否使用 TalkBack 或 VoiceOver 之类的辅助功能与应用程序进行交互,用以辅助视力障碍人群;
invertColors 为是否使用颜色反转,主要用于 iOS 设备;
highContrast 为用户是否要求前景与背景之间的对比度高,主要用于 iOS 设备;
disableAnimations 为平台是否要求禁用或减少动画;
boldText 为平台是否要求使用粗体;
padding 为屏幕内边距,一般是刘海儿屏或异形屏中被系统遮挡部分边距;
viewInsets 为键盘弹出时等遮挡屏幕边距,其中 viewInsets.bottom 为键盘高度;
systemGestureInsets 为手势边距,如 Android Q 之后添加的向左滑动关闭页面等;
viewPadding 小菜理解为视图内边距,为屏幕被刘海儿屏或异形屏中被系统遮挡部分,从 MediaQuery 边界的边缘计算;此值是保持不变;例如,屏幕底部的软件键盘可能会覆盖并占用需要底部填充的相同区域,因此不会影响此值;
physicalDepth 为设备物理层级,小菜暂时还未想到对应的应用场景;
小菜在尝试获取其他子 Widget Size 时,有两点需要注意,首先要设置一个全局的 GlobalKey 来获取当前位置, key 需要为唯一的;第二通过 GlobalKey().currentContext 获取 BuildContext 上下文环境,从而获取对应尺寸;
MediaQuery 案例尝试
小菜对于部分 MediaQueryData 的应用和理解还不够深入;如有错误请多多指导!