当前位置: 首页 > news >正文

Flutter(四)布局类组件

目录

  • 布局类组件简介
  • 布局原理与约束
  • 线性布局(Row和Column)
  • 弹性布局
  • 流式布局(Wrap、Flow)
  • 层叠布局(Stack、Positioned)
  • 对齐与相对定位(Align)
    • Align和Stack对比
    • Center组件
  • LayoutBuilder、AfterLayout
    • LayoutBuilder
    • AfterLayout

布局类组件简介

布局类组件就是指直接或间接继承(包含)SingleChildRenderObjectWidgetMultiChildRenderObjectWidget的Widget

它们一般都会有一个child或children属性用于接收子 Widget。

继承关系 Widget > RenderObjectWidget > (Leaf/SingleChild/MultiChild)RenderObjectWidget

RenderObjectWidget类中定义了创建、更新RenderObject的方法,子类必须实现他们

RenderObject:渲染UI界面的

布局原理与约束

BoxConstraints 是盒模型布局过程中父渲染对象传递给子渲染对象的约束信息,包含最大宽高信息,子组件大小需要在约束的范围内

const BoxConstraints({this.minWidth = 0.0, //最小宽度this.maxWidth = double.infinity, //最大宽度this.minHeight = 0.0, //最小高度this.maxHeight = double.infinity //最大高度
})

ConstrainedBox用于对子组件添加额外的约束

Widget redBox = DecoratedBox(decoration: BoxDecoration(color: Colors.red),
);ConstrainedBox(constraints: BoxConstraints(minWidth: double.infinity, //宽度尽可能大minHeight: 50.0 //最小高度为50像素),child: Container(height: 5.0, child: redBox ,),
)

SizedBox用于给子元素指定固定的宽高

SizedBox(width: 80.0,height: 80.0,child: redBox
)

任何时候子组件都必须遵守其父组件的约束,如果我们需要自定义约束必须通过UnconstrainedBox来 “去除” 父元素的限制

线性布局(Row和Column)

Row和Column都继承自Flex,类似Android 中的LinearLayout

线性布局有主轴和纵轴之分,
如果布局沿水平方向,那么主轴就是指水平方向,而纵轴即垂直方向
如果布局沿垂直方向,那么主轴就是指垂直方向,而纵轴就是水平方向

Row:水平
Column:垂直

//Row和Column的属性Key? key,MainAxisAlignment//主轴对齐方式//默认MainAxisSize.max:占满宽度,类似match_parent//MainAxisSize.min:子组件的宽度总和,类似wrap_contentMainAxisSizeCrossAxisAlignment //纵轴对齐方式TextDirection //从左往右还是从右往左排列,默认从左往右VerticalDirection//纵轴对齐方向TextBaseline//对齐文本的水平线List<Widget> children = const <Widget>[] //子组件数组

如果Row里面嵌套Row,或者Column里面再嵌套Column,那么只有最外面的Row或Column会占用尽可能大的空间里面Row或Column所占用的空间为实际大小,如果要让里面的Column占满外部Column,可以使用Expanded 组件

弹性布局

弹性布局允许子组件按照一定比例来分配父容器空间,Flutter 中的弹性布局主要通过Flex和Expanded来配合实现

Flex({...required this.direction, //弹性布局的方向, Row默认为水平方向,Column默认为垂直方向List<Widget> children = const <Widget>[],
})
const Expanded({int flex = 1, //比例系数,类似LinearLayout中的layout_weightrequired Widget child,
})

流式布局(Wrap、Flow)

Row 和 Colum ,如果子 widget 超出屏幕范围,则会报溢出错误
流式布局含义:超出屏幕自动换行
Flutter中通过Wrap和Flow来支持流式布局

Wrap({...spacing//主轴方向子widget的间距runSpacing//纵轴方向子widget的间距runAlignment//纵轴方向的对齐方式
})

Flow:Flow很少用,因为过于复杂,需要自己实现子 widget 的位置转换,在很多场景下首先要考虑的是Wrap是否满足需求。Flow主要用于一些需要自定义布局策略或性能要求较高(如动画中)的场景

Flow不能自适应子widget的大小,我们通过在getSize返回一个固定大小来指定Flow的大小

层叠布局(Stack、Positioned)

类似Android 中的 Frame,Flutter中使用Stack和Positioned这两个组件来配合实现绝对定位

Stack({this.alignment = AlignmentDirectional.topStart,//对齐方式this.textDirection,//子组件排列顺序,默认从左往右//此参数用于确定没有定位的子组件如何去适应Stack的大小。//StackFit.loose表示使用子组件的大小,//StackFit.expand表示扩伸到Stack的大小。this.fit = StackFit.loose,//此属性决定对超出Stack显示空间的部分如何剪裁,//Clip枚举类中定义了剪裁的方式,Clip.hardEdge 表示直接剪裁...this.clipBehavior = Clip.hardEdge,List<Widget> children = const <Widget>[],
})
//left、top 、right、 bottom分别代表离Stack左、上、右、底四边的距离
//width和height用于指定需要定位元素的宽度和高度
const Positioned({Key? key,this.left, this.top,this.right,this.bottom,this.width,this.height,required Widget child,
})

对齐与相对定位(Align)

如果我们只想简单的调整一个子元素在父元素中的位置的话,使用Align组件会更简单一些

Align({Key key,this.alignment = Alignment.center,//子组件在父组件中的起始位置this.widthFactor,//会分别乘以子元素的宽、高,最终的结果就是Align 组件的宽高this.heightFactor,//会分别乘以子元素的宽、高,最终的结果就是Align 组件的宽高Widget child,
})
//因为FlutterLogo的宽高为 60,则Align的最终宽高都为2*60=120。
Align(widthFactor: 2,heightFactor: 2,alignment: Alignment.topRight,child: FlutterLogo(size: 60,),
),

Alignment可以通过其坐标转换公式将其坐标转为子元素的具体偏移坐标:

(Alignment.x*childWidth/2+childWidth/2, Alignment.y*childHeight/2+childHeight/2)

FractionalOffset 继承自 Alignment,它和 Alignment唯一的区别就是坐标原点不同!FractionalOffset 的坐标原点为矩形的左侧顶点,FractionalOffset的坐标转换公式为:

实际偏移 = (FractionalOffse.x * childWidth, FractionalOffse.y * childHeight)

Align和Stack对比

Stack/Positioned定位的的参考系可以是父容器矩形的四个顶点;而Align则需要先通过alignment 参数来确定坐标原点.
Stack可以有多个子元素,并且子元素可以堆叠,而Align只能有一个子元素,不存在堆叠

Center组件

Center继承自Align,它比Align只少了一个alignment 参数

Center(widthFactor: 1,heightFactor: 1,child: Text("xxx"),),

LayoutBuilder、AfterLayout

LayoutBuilder

通过 LayoutBuilder,我们可以在布局过程中拿到父组件传递的约束信息,然后我们可以根据约束信息动态的构建不同的布局。
它主要有两个使用场景:

  • 可以使用 LayoutBuilder 来根据设备的尺寸来实现响应式布局。
  • LayoutBuilder 可以帮我们高效排查问题。比如我们在遇到布局问题或者想调试组件树中某一个节点布局的约束时 LayoutBuilder 就很有用

为了便于排错,我们封装一个能打印父组件传递给子组件约束的组件:

class LayoutLogPrint<T> extends StatelessWidget {const LayoutLogPrint({Key? key,this.tag,required this.child,}) : super(key: key);final Widget child;final T? tag; //指定日志tag@overrideWidget build(BuildContext context) {return LayoutBuilder(builder: (_, constraints) {// assert在编译release版本时会被去除assert(() {print('${tag ?? key ?? child}: $constraints');return true;}());return child;});}
}

我们就可以使用 LayoutLogPrint 组件树中任意位置的约束信息,比如:

LayoutLogPrint(child:Text("xx"))

控制台输出:

flutter: Text("xx"): BoxConstraints(0.0<=w<=428.0, 0.0<=h<=823.0)

可以看到 Text(“xx”) 的显示空间最大宽度为 428,最大高度为 823 。
我们的大前提是盒模型布局,如果是Sliver 布局,可以使用 SliverLayoutBuiler 来打印。

AfterLayout

  • 布局一结束就去获取大小和位置信息,笔者封装了一个 AfterLayout 组件,它可以在子组件布局完成后执行一个回调,并同时将 RenderObject 对象作为参数传递。
AfterLayout(callback: (RenderAfterLayout ral) {print(ral.size); //子组件的大小print(ral.offset);// 子组件在屏幕中坐标},child: Text('flutter@wendux'),
),

控制台输出:

flutter: Size(105.0, 17.0)
flutter: Offset(42.5, 290.0)

Text 文本的实际长度是 105,高度是 17,它的起始位置坐标是(42.5, 290.0)

  • 获取组件相对于某个父组件的坐标
    RenderAfterLayout 类继承自 RenderBox,RenderBox 有一个 localToGlobal 方法,它可以将坐标转化为相对与指定的祖先节点的坐标,比如下面代码可以打印出 Text(‘A’) 在 父 Container 中的坐标
Builder(builder: (context) {return Container(color: Colors.grey.shade200,alignment: Alignment.center,width: 100,height: 100,child: AfterLayout(callback: (RenderAfterLayout ral) {Offset offset = ral.localToGlobal(Offset.zero,// 传一个父级元素ancestor: context.findRenderObject(),);print('A 在 Container 中占用的空间范围为:${offset & ral.size}');},child: Text('A'),),);
}),

通过观察 LayoutBuilder 的示例,我们还可以发现一个关于 Flutter 构建(build)和 布局(layout)的结论:Flutter 的build 和 layout 是可以交错执行的,并不是严格的按照先 build 再 layout 的顺序

至此,布局类组件完结。

相关文章:

Flutter(四)布局类组件

目录布局类组件简介布局原理与约束线性布局&#xff08;Row和Column&#xff09;弹性布局流式布局&#xff08;Wrap、Flow&#xff09;层叠布局&#xff08;Stack、Positioned&#xff09;对齐与相对定位&#xff08;Align&#xff09;Align和Stack对比Center组件LayoutBuilder…...

【黑马】Java基础从入门到起飞目录合集

视频链接&#xff1a; Java入门到起飞&#xff08;上部&#xff09;&#xff1a;BV17F411T7AoJava入门到起飞&#xff08;下部&#xff09;&#xff1a;BV1yW4y1Y7Ms 学习时间&#xff1a; 2023/02/01 —— 2023/03/09断断续续的学习&#xff0c;历时大概37天&#xff0c;完结撒…...

PMP考前冲刺3.10 | 2023新征程,一举拿证

题目1-2&#xff1a;1.在最近的一次耗时四周的迭代中&#xff0c;赫克托尔所在的敏捷团队刚完成了10 个用户故事点的开发、测试和发布&#xff0c;那么团队的速度是&#xff1f;A. 10B. 4C. 5D.402.产品负责人奥佩&#xff0c;倾向于在短周期内看到工作产品的新版本&#xff0c…...

JavaScript Math常用方法

math是JavaScript的一个内置对象&#xff0c;它提供了一些数学属性和方法&#xff0c;可以对数字进行计算&#xff08;用于Number类型&#xff09;。 math和其他全局对象不同&#xff0c;它不是一个构造器&#xff0c;math的所有方法和属性都是静态的&#xff0c;直接使用并传入…...

【C++】模板进阶

文章目录一、非类型模板参数1、非类型模板参数2、C11 中的 array 类二、模板的特化1、模板特化的概念2、函数模板特化3、类模板特化3.1 全特化3.2 偏特化三、模板的分离编译四、模板总结一、非类型模板参数 1、非类型模板参数 模板参数分为类型形参与非类型形参&#xff0c;类…...

三板斧解决leetcode的链表题

在《波奇学单链表》中我们提到单链表的两个特点单向性。头节点尾节点的特殊性导致分类讨论的情况。如何看单链表&#xff1f;让我们简化成下图cur表示当前节点&#xff0c;下图表示cur移动&#xff0c;圆圈表示值用哨兵卫节点(新的头节点)和把尾节点看成NULL来把头尾节点一般化…...

全生命周期的云原生安全框架

本博客地址&#xff1a;https://security.blog.csdn.net/article/details/129423036 一、全生命周期的云原生安全框架 如图所示&#xff1a; 二、框架说明 在上图中&#xff0c;我们从两个维度描述各个安全机制&#xff0c;横轴是开发和运营阶段&#xff0c;细分为编码、测试…...

【本地网站上线】ubuntu搭建web站点,并内网穿透发布公网访问

【本地网站上线】ubuntu搭建web站点&#xff0c;并内网穿透发布公网访问前言1. 本地环境服务搭建2. 局域网测试访问3. 内网穿透3.1 ubuntu本地安装cpolar3.2 创建隧道3.3 测试公网访问4. 配置固定二级子域名4.1 保留一个二级子域名4.2 配置二级子域名4.3 测试访问公网固定二级子…...

电脑怎么重装系统?教你轻松掌握这些方法

重新安装计算机系统有两种原因&#xff1a;一种是计算机系统可以正常使用&#xff0c;但是电脑比较卡&#xff0c;为了提高它的运行速度&#xff0c;所以想要通过重新安装系统来解决这个问题;另一种原因是计算机系统文件丢失&#xff0c;系统出现蓝屏&#xff0c;或者黑屏的情况…...

leetcode-每日一题-2379(简单,字符串)

久违的简单题......给你一个长度为 n 下标从 0 开始的字符串 blocks &#xff0c;blocks[i] 要么是 W 要么是 B &#xff0c;表示第 i 块的颜色。字符 W 和 B 分别表示白色和黑色。给你一个整数 k &#xff0c;表示想要 连续 黑色块的数目。每一次操作中&#xff0c;你可以选择…...

SLF4J日志框架在项目中使用

介绍 SLF4J全称“Simple Logging Facade for Java”&#xff0c;作为各种日志框架的简单门面。例如&#xff1a; java.util.logging、logback 、 reload4j等。只需要切换日志框架的jar包依赖就可以切换日志框架。 SLF4J支持的日志框架包含如下&#xff1a; log4j&#xff1a…...

Spark MLlib 模型训练

Spark MLlib 模型训练决策树随机森林GBDTSpark MLlib 开发框架下 : 监督学习 : 回归 (Regression) , 分类 (Classification) , 协同过滤 (Collaborative Filtering)非监督学习 : 聚类 (Clustering) 、频繁项集 (Frequency Patterns) 例子分类 : 算法分类 : 算法分类算法子分类…...

Python中变量的作用域精讲

文章目录前言一、局部变量二、全局变量前言 变量的作用域是指程序代码能够访问该变量的区域&#xff0c;如果超出该区域&#xff0c;再访问时就会出现错误。在程序中&#xff0c;一般会根据变量的 “有效范围” 将变量分为 “全局变量” 和 “局部变量”。 一、局部变量 局部变…...

数据仓库工程师的工作职责的相关介绍

1. BI 开发工程师的工作内容是什么&#xff1f; BI开发工程师&#xff08;Business Intelligence Developer&#xff09;是负责设计和开发企业级BI系统的专业人员。他们的主要工作是从多个数据源中提取、转换、加载和分析数据&#xff0c;以支持企业决策。以下是BI开发工程师的…...

ESP UART 介绍

1 UART 介绍 UART 是一种以字符为导向的通用数据链&#xff0c;可以实现设备间的通信。异步传输的意思是不需要在发送数据上添加时钟信息。这也要求发送端和接收端的速率、停止位、奇偶校验位等都要相同&#xff0c;通信才能成功。 1.1 UART 通信协议 一个典型的 UART 帧开始…...

第十三届蓝桥杯省赛Python大学B组复盘

目录 一、试题B&#xff1a;寻找整数 1、题目描述 2、我的想法 3、官方题解 4、另解 二、试题E&#xff1a;蜂巢 1、题目描述 2、我的想法 3、官方题解 三、试题F&#xff1a;消除游戏 1、题目描述 2、我的想法&#xff08;AC掉58.3%&#xff0c;剩下全超时&#x…...

linux入门---vim的配置

这里写目录标题预备知识如何配置vimvim一键配置预备知识 在配置vim之前大家首先得知道一件事就是vim的配置是一人一份的&#xff0c;每个用户配置的vim都是自己的vim&#xff0c;不会影响到其他人&#xff0c;比如说用户xbb配置的vim是不会影响到用户wj的&#xff0c;虽然不同…...

Python简写操作(for、if简写、匿名函数)

Python简写操作&#xff08;for、if简写、匿名函数&#xff09;1. for 简写1.1 一层 for 循环1.2 两层 for 循环2. if 简写3. for 与 if 的结合简写4. 匿名函数 lambda1. for 简写 举个例子&#xff1a; y [1, 2, 3, 4, 5, 6] result [(i * 2) for i in y] print(result)# …...

毕业设计常用模块之温湿度模块DHT11模块使用

DHT11是一款可以测量温度数据和湿度数据的传感器 产品特点 暖通空调、除湿器、农业、冷链仓储、测试及检测设备、消费品、汽车、自动控制、数据记录器、气 象站、家电、湿度调节器、医疗、其他相关湿度检测控制 外形尺寸 第3管脚&#xff1a;NC 是没有用的 典型电路 通信方式…...

Cadence Allegro 导出Design Rules Net Shorts Check(DRC)Report报告详解

⏪《上一篇》   🏡《上级目录》   ⏩《下一篇》 目录 1,概述2,Design Rules Net Shorts Check(DRC)Report作用3,Design Rules Net Shorts Check(DRC)Report示例4,Design Rules Net Shorts Check(DRC)Report导出方法4.1,方法14.2,方法2...

3种激活方案:解决IDM弹窗问题的开源工具应用指南

3种激活方案&#xff1a;解决IDM弹窗问题的开源工具应用指南 【免费下载链接】IDM-Activation-Script IDM Activation & Trail Reset Script 项目地址: https://gitcode.com/gh_mirrors/id/IDM-Activation-Script 一、问题溯源&#xff1a;解析IDM激活弹窗的技术本质…...

零基础一键配置黑苹果:OpCore-Simplify智能工具让复杂变简单

零基础一键配置黑苹果&#xff1a;OpCore-Simplify智能工具让复杂变简单 【免费下载链接】OpCore-Simplify A tool designed to simplify the creation of OpenCore EFI 项目地址: https://gitcode.com/GitHub_Trending/op/OpCore-Simplify 还在为黑苹果配置时面对满屏代…...

三三复制系统模式介绍

三三复制系统模式介绍&#xff1a;从底层逻辑到合规落地在社交电商与团队裂变领域&#xff0c;三三复制系统凭借其低门槛、高稳定性的特点&#xff0c;成为企业实现用户快速增长与业绩倍增的重要工具。不同于传统多级分销的复杂层级&#xff0c;三三复制系统以“三”为核心基数…...

用51单片机+无源蜂鸣器播放《两只老虎》完整教程(附代码与乐理速成)

用51单片机驱动无源蜂鸣器演奏《两只老虎》全流程解析 第一次听到单片机播放音乐时&#xff0c;那种"机器唱歌"的奇妙感至今难忘。作为电子爱好者入门必备的趣味项目&#xff0c;用蜂鸣器演奏音乐不仅能巩固定时器、中断等核心知识&#xff0c;更能将枯燥的理论转化为…...

效率提升:基于快马平台快速集成openclaw开发局域网协作工具

最近在团队协作开发中遇到了一个痛点&#xff1a;每次新成员加入局域网时&#xff0c;都需要手动配置设备信息才能互相访问&#xff0c;文件共享和实时沟通也依赖第三方工具&#xff0c;效率很低。于是尝试用openclaw结合InsCode(快马)平台快速搭建了一套本地化协作工具&#x…...

AI 模型推理框架性能分析与对比

AI模型推理框架性能分析与对比 随着人工智能技术的快速发展&#xff0c;AI模型推理框架成为支撑各类应用落地的核心工具。无论是计算机视觉、自然语言处理还是推荐系统&#xff0c;高效的推理框架直接影响模型的响应速度、资源占用和部署成本。本文将从多个维度对比主流AI推理…...

3大核心步骤打造专属翻译引擎:Zotero PDF Translate高级扩展指南

3大核心步骤打造专属翻译引擎&#xff1a;Zotero PDF Translate高级扩展指南 【免费下载链接】zotero-pdf-translate 支持将PDF、EPub、网页内容、元数据、注释和笔记翻译为目标语言&#xff0c;并且兼容20多种翻译服务。 项目地址: https://gitcode.com/gh_mirrors/zo/zoter…...

如何用ABC系统三分钟搞定复杂电路优化:顺序逻辑综合与形式验证的完整指南

如何用ABC系统三分钟搞定复杂电路优化&#xff1a;顺序逻辑综合与形式验证的完整指南 【免费下载链接】abc ABC: System for Sequential Logic Synthesis and Formal Verification 项目地址: https://gitcode.com/gh_mirrors/ab/abc 在现代数字电路设计中&#xff0c;你…...

全能B站资源管理工具:BiliTools让视频下载与管理效率提升90%

全能B站资源管理工具&#xff1a;BiliTools让视频下载与管理效率提升90% 【免费下载链接】BiliTools A cross-platform bilibili toolbox. 跨平台哔哩哔哩工具箱&#xff0c;支持视频、音乐、番剧、课程下载……持续更新 项目地址: https://gitcode.com/GitHub_Trending/bili…...

别再手动折腾了!用Docker一键部署Oracle 11g开发环境(附阿里云镜像地址)

告别繁琐配置&#xff1a;Docker容器化Oracle 11g开发环境实战指南 每当新项目需要搭建Oracle开发环境时&#xff0c;开发者们总会面临相同的困境——数小时的安装配置、复杂的系统依赖、难以复现的环境问题。传统安装方式不仅消耗宝贵时间&#xff0c;更可能因系统差异导致团…...