Flutter - 布局Widget

ops/2025/3/4 2:42:15/

Flutter的布局主要分为 单子组件 和 多子组件 两大类:

Container、Padding、Align这些属于单子组件,而Row、Column、ListView这些则是多子组件。 

单子组件

Align组件

Align 是一个用于控制子组件位置的单子布局组件。它通过指定对齐方式(如居中、右上角、底部等)将子组件放置在可用空间内的特定位置,常用于精确控制子组件的布局。在 Android/iOS 中 align 只是一个属性,在 Flutter 中是一个组件。

    /*** Align 默认会填满父容器的可用空间,可以通过 widthFactor 和 heightFactor 按比例缩设置。*/Align(child: Icon(Icons.people, size: 36, color: Colors.blue),/*** 对齐方式,默认居中对齐 (子组件在父容器中的对齐位置)* 使用 Alignment(x, y) 或 AlignmentDirectional(start, y)(支持 RTL 布局)指定坐标*/alignment: Alignment.topCenter,/*** 按子组件的尺寸比例控制 Align 自身大小* Align 宽度为子组件的 3 倍,高度为子组件的 2 倍*/widthFactor: 3,heightFactor: 2);

Center组件

Center 是一个专门用于将子组件居中对齐的单子布局组件。Center 继承 Align,它是 Align 组件的简化版本,默认将子组件放置在父容器的中心位置,非常适合快速实现居中布局。

    // Center 不支持设置背景色Center(child: Icon(Icons.people, size: 36, color: Colors.blue),widthFactor: 3,heightFactor: 3);

Padding 组件

Padding 是一个用于为子组件添加内边距(即子组件与其父容器之间的空白区域)的布局组件。它是控制界面元素间距的核心工具之一,常用于优化视觉效果或避免内容紧贴容器边缘。

Padding 在Android/iOS 也是一个属性,在 Flutter 是一个组件。

    return Padding(// 通过 EdgeInsets 设置不同方向的内边距(如上下左右、对称或自定义)padding: EdgeInsets.all(16),child: Text("我在练习书法,但不是写在纸上,而是用心去感受每一个字的灵魂。这是一种玄学,也是一种艺术。",style: TextStyle(color: Colors.teal, fontSize: 18)));

Container 组件

Container 是最常用且功能最丰富的布局组件之一,可以用来设置边距(margin)、填充(padding)、背景颜色(color)、装饰(decoration)、变换(如旋转、缩放)等,可以快速实现复杂的视觉效果。类似于 Android 的 View,iOS 的 UIView,在开发中使用频率较高。

    /*** 注:容器的大小可以通过 width、height属性来指定,也可以通过 constraints 来指定,* 如果同时存在时,width、height优先。(Container内部会根据width、height来生成一个 constraints)* color和decoration是互斥的,当指定color时,Container内会自动创建一个 decoration.*/return Container(color: Colors.blueGrey,width: 240,height: 120,child: Text("我在练习书法,但不是写在纸上,而是用心去感受每一个字的灵魂。这是一种玄学,也是一种艺术。",overflow: TextOverflow.ellipsis),alignment: Alignment.center,padding: EdgeInsets.all(8),margin: EdgeInsets.all(20));

BoxDecoration 组件

BoxDecoration 是一个用于定义容器(如 ContainerDecoratedBox)视觉样式的类,支持设置背景色、边框、圆角、阴影、渐变等复杂装饰效果。它是构建精美 UI 的核心工具之一。

    return Container(width: 150,height: 150,child: Text("我在练习书法,但不是写在纸上,而是用心去感受每一个字的灵魂。这是一种玄学,也是一种艺术。"),margin: EdgeInsets.all(16),padding: EdgeInsets.all(12),decoration: BoxDecoration(// 背景颜色// color: Colors.blueGrey,// 边框样式(支持单边设置)border: Border.all(color: Colors.blue, width: 2),// 圆角半径(需与 shape 配合)borderRadius: BorderRadius.circular(10),// 阴影效果(支持多个叠加)boxShadow: [BoxShadow(color: Colors.red, blurRadius: 5)],// 渐变背景(与 color 互斥),只保留一个gradient: LinearGradient(colors: [Colors.blueGrey, Colors.grey])),);

多子组件

 在开发中经常需要将多个 Widget 放在一起进行布局,比如水平方向、垂直方向排列,甚至有时候需要他们进行层叠,比如图片上面放一段文字等;
这个时候我们需要使用多子布局组件(Multi-child layout widgets)

Flex 组件

Flex 组件是用于创建灵活布局的核心组件,支持通过主轴和交叉轴方向控制子组件的排列方式。它与 Row 和 Column 密切相关(实际上 Row 和 Column 是 Flex 的子类),但 Flex 提供了更底层的控制能力,允许开发者自定义布局方向和其他高级行为。

  • Flex组件和Row、Column属性主要的区别就是多一个direction。
  • 当direction的值为Axis.horizontal的时候,则是Row。
  • 当direction的值为Axis.vertical的时候,则是Column。

    Flex(direction: Axis.vertical,// direction: Axis.horizontal,children: [Icon(Icons.add),Icon(Icons.remove),Icon(Icons.center_focus_strong),],);
特性FlexRow/Column
方向灵活性✅ 可动态切换 horizontal/vertical❌ 固定方向(Row 水平,Column 垂直)
代码复杂度❌ 需手动指定方向✅ 直接使用 Row 或 Column
适用场景需要动态布局方向时明确方向时优先使用

Row 组件

Row 是一个用于水平排列子组件的多子布局组件,属于 Flex 布局的子类(相当于 Flex(direction: Axis.horizontal) 的简化版本)。它通过灵活的主轴和交叉轴对齐方式,实现复杂的水平布局需求。

    Row(children: [Container(color: Colors.redAccent,width: 40,height: 40),Container(color: Colors.blueGrey,width: 80,height: 80),Container(color: Colors.green,width: 60,height: 60),Container(color: Colors.orange,width: 100,height: 100)],// 主轴(水平方向)对齐方式(如 spaceBetween、start、center)mainAxisAlignment: MainAxisAlignment.spaceEvenly,// 交叉轴(垂直方向)对齐方式(如 stretch、baseline、end)crossAxisAlignment: CrossAxisAlignment.end,// 主轴的尺寸策略:MainAxisSize.max(填满父容器宽度) MainAxisSize.min(包裹子组件宽度)mainAxisSize: MainAxisSize.max);

Column 组件

Column 是一个用于垂直排列子组件的多子布局组件,属于 Flex 布局的子类(相当于 Flex(direction: Axis.vertical) 的简化版本)。它通过主轴(垂直方向)和交叉轴(水平方向)控制子组件的排列方式,适用于表单、列表、卡片内容等垂直布局场景。

    /*** Column的宽度是由子 Widget的最大宽度决定的* Column的所有子 Widget必须有一个明确的高度, 否则会报 hasSize的错误* Expanded 或 Flexible 处理动态高度分配。* 通过 crossAxisAlignment.stretch 实现水平拉伸效果。*/Column(children: [// Expanded 强制子组件填满剩余垂直空间(按 flex 权重分配) Flexible按比例分配空间,但不强制填满剩余高度Expanded(child: Container(color: Colors.redAccent, width: 40, height: 40),flex: 1,),Container(color: Colors.blueGrey, width: 80, height: 80),Container(color: Colors.green, width: 60, height: 60),Expanded(child: Container(color: Colors.orange, width: 100, height: 100),flex: 2,)],// 交叉轴(垂直方向)对齐方式(如 stretch、baseline、end)crossAxisAlignment: CrossAxisAlignment.end);

Stack 组件

Stack 是一个用于层叠排列子组件的多子布局组件,允许子组件通过绝对或相对定位覆盖在彼此之上。它常用于实现悬浮按钮、对话框、图片叠加文字等需要视觉层叠的场景。

 Positioned组件只能在Stack中使用

    Stack(children: [Container(color: Colors.black54, width: 300, height: 300),Positioned(child: Icon(Icons.ac_unit, size: 48)),Positioned(child: Text("1234567890",style: TextStyle(fontSize: 20, color: Colors.green),))],);

ListView

ListView 是最常用的滚动列表组件,用于展示垂直或水平方向的可滚动数据集合。

    ListView(children: [Padding(padding: EdgeInsets.all(8),child: Text('应龙:有翼的龙,曾帮助黄帝战胜蚩尤。它也是传说中的一种祥瑞之物。')),Padding(padding: EdgeInsets.all(8),child: Text('烛龙:又称为“烛阴”,人面蛇身,全身赤红,住在章尾山,眼睛竖立,睁开眼就是白天,闭上眼就是黑夜。')),Padding(padding: EdgeInsets.all(8),child: Text('青鸾:与凤凰同类,羽毛五彩斑斓,常被描述为神仙的坐骑或信使。'))]);
ListTile

在开发中,经常见到一种列表,有一个图标或图片(Icon),有一个标题(Title),有一个子标题(Subtitle),还有尾部一个图标(Icon)。系统有提供类似布局组件 ListTile。

注:通过构造函数中 children 传入 Widget 有性能问题,如果有 10W 条数据怎么办?

可以通过 ListView.builder 来构建子Widget,该构造函数将创建子Widget交给了一个抽象的方法,交给 ListView 进行管理,ListView 会在真正需要的时候去创建子Widget,而不是一开始就全部初始化好。

ListView.builder

    ListView.builder(// 表示列表项的数量,如果为空,则表示ListView为无限列表itemCount: 1000,itemBuilder: (BuildContext context, int index) {return Padding(padding: EdgeInsets.all(8),child: Text('$index 应龙:有翼的龙...'));});
ListView.separated

istView.separated可以生成列表项之间的分割器,它比ListView.builder多了一个separatorBuilder参数,该参数是一个分割器生成器。

    return ListView.separated(itemCount: 1000,itemBuilder: (BuildContext context, int index) {return Padding(padding: EdgeInsets.all(8),child: Text('$index 应龙:有翼的龙...'));},separatorBuilder: (BuildContext context, int index){return Divider(color: Colors.red);});


http://www.ppmy.cn/ops/162931.html

相关文章

DeepSeek与人工智能的结合:探索搜索技术的未来

云边有个稻草人-CSDN博客 目录 引言 一、DeepSeek的技术背景 1.1 传统搜索引擎的局限性 1.2 深度学习在搜索中的优势 二、DeepSeek与人工智能的结合 2.1 自然语言处理(NLP) 示例代码:基于BERT的语义搜索 2.2 多模态搜索 示例代码&…

Qt显示一个hello world

一、显示思路 思路一:通过图形化方式,界面上创建出一个控件显示。 思路二:通过编写C代码在界面上创建控件显示。 二、思路一实现 点开 Froms 的 widget.ui,拖拽 label 控件,显示 hello world 即可。 qmake 基于 .…

BUG日志:使用热点或免费加速器时git链接github出现端口22拒绝访问的解决方法

问题描述 现象:git 连接 GitHub 时,报错 Connection refused on port 22。触发条件: 使用移动热点或免费加速器时必现。使用正常 Wi-Fi 时不出现。 解决步骤 临时切换为 HTTPS 协议(绕过 22 端口): git r…

【深度学习】—— 深入 Keras:从基础到实战的深度学习指南 第1~4章 共12章

《深入 Keras:从基础到实战的深度学习指南》 文章目录 《深入 Keras:从基础到实战的深度学习指南》第1章:Keras简介1.1 Keras的诞生与发展1.1.1 Keras出现的背景与深度学习发展需求1.1.2 版本迭代历程与重大更新 1.2 Keras的设计理念与特点1.…

【前端框架】vue2和vue3的区别详细介绍

Vue 3 作为 Vue 2 的迭代版本,在性能、语法、架构设计等多个维度均有显著的变革与优化。以下详细剖析二者的区别: 响应式系统 Vue 2 实现原理:基于 Object.defineProperty() 方法实现响应式。当一个 Vue 实例创建时,Vue 会遍历…

【GB28181】 SIP信令服务器

概述 本文仅总结关于GB28181下的注册、心跳维持等与推流拉流相配合的SIP信令,主要基于eXosip库实现;其中搭建信令服务器参考了开源代码以及B站up北小菜,文章结尾有链接 主要逻辑梳理 配置自身SIP服务器,同时配置自己想要访问的SI…

【人工智能】数据挖掘与应用题库(201-300)

1、在LetNet5网络中,卷积核的大小是? 答案:5*5 2、LeNet5网络参数的数量约为? 答案:6万 3、AlexNet与LeNet5相比,使用了哪些机制来改进模型的训练过程? 答案: 数据增广Dropout抑制过拟合ReLU激活函数CUDA加速神经网络训练4、VGGNet使用的卷积核的大小是? 答案:…

Conda 全面使用指南:从基础操作到高级优化

一、Conda 简介 Conda 是一个开源的包、依赖项和环境管理系统,可在 Windows、macOS 和 Linux 上运行。它最初是为 Python 程序创建的,但可以打包和分发任何语言的软件。Conda 有 Anaconda 和 Miniconda 两种发行版,Anaconda 包含大量常用的数…