【Flutter】线性布局弹性布局层叠布局

news2024/11/24 15:24:36

🔥 本文由 程序喵正在路上 原创,CSDN首发!
💖 系列专栏:Flutter学习
🌠 首发时间:2024年5月25日
🦋 欢迎关注🖱点赞👍收藏🌟留言🐾

目录

  • 线性布局
    • Row水平布局组件
    • Column垂直布局组件
    • double.infinity和double.maxFinite
  • 弹性布局
    • 水平弹性布局
    • 垂直弹性布局
    • 使用Row或Column结合Expanded实现案例
  • 层叠布局
    • Stack组件
    • Align组件
    • Positioned组件
    • MediaQuery获取屏幕宽度和高度
    • Stack结合Positioned固定导航案例

线性布局

Row水平布局组件

在这里插入图片描述

实现如下效果:

在这里插入图片描述

因为图中有3个差不多的盒子,都是一个盒子里面放一个图标,所以我们将其写成了一个类 IconContainer,以减少代码量

class MyHomePage extends StatelessWidget {
  const MyHomePage({super.key});

  
  Widget build(BuildContext context) {
    return Container(
      height: double.infinity, //无穷大
      width: double.infinity,
      color: Colors.white,
      child: Row(
        crossAxisAlignment: CrossAxisAlignment.center,
        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
        children: [
          IconContainer(Icons.home, color: Colors.red),
          IconContainer(Icons.search),
          IconContainer(Icons.send, color: Colors.orange),
        ],
      ),
    );
  }
}

class IconContainer extends StatelessWidget {
  Color color; //盒子颜色
  double iconSize; //图标大小
  IconData icon; //图标
  //盒子默认为蓝色,图标大小默认32
  IconContainer(this.icon,
      {super.key, this.color = Colors.blue, this.iconSize = 32});

  
  Widget build(BuildContext context) {
    return Container(
      height: 100,
      width: 100,
      color: color,
      //图标颜色默认为白色
      child: Center(child: Icon(icon, size: iconSize, color: Colors.white)),
    );
  }
}

Column垂直布局组件

在这里插入图片描述

实现如下效果:

在这里插入图片描述

将前面代码中的 Row 改成 Column 即可:

在这里插入图片描述

double.infinity和double.maxFinite

double.infinitydouble.maxFinite 可以让当前元素的 width 或者 height 达到父元素的尺寸

如下可以让Container铺满整个屏幕

class MyHomePage extends StatelessWidget {
  const MyHomePage({super.key});

  
  Widget build(BuildContext context) {
    return Container(
      height: double.infinity,
      width: double.infinity,
      color: Colors.white,
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.center,
        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
        children: [
          IconContainer(Icons.home, color: Colors.red),
          IconContainer(Icons.search),
          IconContainer(Icons.send, color: Colors.orange),
        ],
      ),
    );
  }
}

如下可以让Container的宽度和高度等于父元素的宽度高度

class MyHomePage extends StatelessWidget {
  const MyHomePage({super.key});

  
  Widget build(BuildContext context) {
    return Container(
      height: 500,
      width: 300,
      color: Colors.red,
      child: Container(
        height: double.maxFinite,
        width: double.infinity,
        color: Colors.yellow,
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.center,
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          children: [
            IconContainer(Icons.home, color: Colors.red),
            IconContainer(Icons.search),
            IconContainer(Icons.send, color: Colors.orange),
          ],
        ),
      ),
    );
  }
}

在这里插入图片描述

弹性布局

水平弹性布局

Flex 组件可以沿着水平或垂直方向排列子组件,如果你知道主轴方向,使用 RowColumn 会方便一些,因为 RowColumn 都继承自 Flex ,参数基本相同,所以能使用 Flex 的地方基本上都可以使用 RowColumnFlex 本身功能是很强大的,它也可以和 Expanded 组件配合实现弹性布局 。

实现如下效果:

在这里插入图片描述

class MyHomePage extends StatelessWidget {
  const MyHomePage({super.key});

  
  Widget build(BuildContext context) {
    return Flex(
      direction: Axis.horizontal, //水平方向
      children: [
        //flex: 占用多少位置
        Expanded(flex: 2, child: IconContainer(Icons.home, color: Colors.red)),
        Expanded(flex: 1, child: IconContainer(Icons.search))
      ],
    );
  }
}

class IconContainer extends StatelessWidget {
  Color color; //盒子颜色
  double iconSize; //图标大小
  IconData icon; //图标
  //盒子默认为蓝色,图标大小默认32
  IconContainer(this.icon,
      {super.key, this.color = Colors.blue, this.iconSize = 32});

  
  Widget build(BuildContext context) {
    return Container(
      height: 100,
      width: 100,
      color: color,
      //图标颜色默认为白色
      child: Center(child: Icon(icon, size: iconSize, color: Colors.white)),
    );
  }
}

因为 Row 继承自 Flex ,所以我们将代码中的 Flex 换成 Row,同样是可以的,而且我们还不用设置方向。当我们能确定主轴的方向时,推荐使用 RowColumn

class MyHomePage extends StatelessWidget {
  const MyHomePage({super.key});

  
  Widget build(BuildContext context) {
    return Row(
      children: [
        //flex: 占用多少位置
        Expanded(flex: 2, child: IconContainer(Icons.home, color: Colors.red)),
        Expanded(flex: 1, child: IconContainer(Icons.search))
      ],
    );
  }
}

垂直弹性布局

class MyHomePage extends StatelessWidget {
  const MyHomePage({super.key});

  
  Widget build(BuildContext context) {
    return Column(
      children: [
        //flex: 占用多少位置
        Expanded(flex: 2, child: IconContainer(Icons.home, color: Colors.red)),
        Expanded(flex: 1, child: IconContainer(Icons.search))
      ],
    );
  }
}

在这里插入图片描述

使用Row或Column结合Expanded实现案例

实现如下效果:

在这里插入图片描述

class MyHomePage extends StatelessWidget {
  const MyHomePage({super.key});

  
  Widget build(BuildContext context) {
    return ListView(
      children: [
        Container(
            width: double.infinity,
            height: 200,
            color: Colors.blue,
            child: Image.network(
                "https://xixi-web-tlias.oss-cn-guangzhou.aliyuncs.com/1.jpg",
                fit: BoxFit.cover)),
        const SizedBox(height: 10),
        Row(
          children: [
            Expanded(
                flex: 2,
                child: SizedBox(
                  height: 200,
                  child: Image.network(
                      "https://xixi-web-tlias.oss-cn-guangzhou.aliyuncs.com/2.jpg",
                      fit: BoxFit.cover),
                )),
            const SizedBox(width: 10),
            Expanded(
              flex: 1,
              child: SizedBox(
                height: 200,
                child: Column(
                  children: [
                    Expanded(
                      flex: 1,
                      child: SizedBox(
                        width: double.infinity,
                        child: Image.network(
                            "https://xixi-web-tlias.oss-cn-guangzhou.aliyuncs.com/3.jpg",
                            fit: BoxFit.cover),
                      ),
                    ),
                    const SizedBox(height: 10),
                    Expanded(
                      flex: 1,
                      child: SizedBox(
                        width: double.infinity,
                        child: Image.network(
                            "https://xixi-web-tlias.oss-cn-guangzhou.aliyuncs.com/4.jpg",
                            fit: BoxFit.cover),
                      ),
                    ),
                  ],
                ),
              ),
            ),
          ],
        ),
        const SizedBox(height: 10),
        Row(
          children: [
            Expanded(
              flex: 1,
              child: SizedBox(
                height: 200,
                child: Column(children: [
                  Expanded(
                    flex: 1,
                    child: SizedBox(
                      width: double.infinity,
                      child: Image.network(
                          "https://xixi-web-tlias.oss-cn-guangzhou.aliyuncs.com/5.jpg",
                          fit: BoxFit.cover),
                    ),
                  ),
                  const SizedBox(height: 10),
                  Expanded(
                    flex: 1,
                    child: SizedBox(
                      width: double.infinity,
                      child: Image.network(
                          "https://xixi-web-tlias.oss-cn-guangzhou.aliyuncs.com/6.jpg",
                          fit: BoxFit.cover),
                    ),
                  ),
                ]),
              ),
            ),
            const SizedBox(width: 10),
            Expanded(
              flex: 1,
              child: SizedBox(
                height: 200,
                child: Column(children: [
                  Expanded(
                    flex: 1,
                    child: SizedBox(
                      width: double.infinity,
                      child: Image.network(
                          "https://xixi-web-tlias.oss-cn-guangzhou.aliyuncs.com/7.jpg",
                          fit: BoxFit.cover),
                    ),
                  ),
                  const SizedBox(height: 10),
                  Expanded(
                    flex: 1,
                    child: SizedBox(
                      width: double.infinity,
                      child: Image.network(
                          "https://xixi-web-tlias.oss-cn-guangzhou.aliyuncs.com/8.jpg",
                          fit: BoxFit.cover),
                    ),
                  ),
                ]),
              ),
            ),
          ],
        ),
      ],
    );
  }
}

层叠布局

Stack组件

Stack 表示堆的意思,我们可以用 Stack 或者 Stack 结合 Align 或者 Stack 结合 Positiond 来实现页面的定位布局

属性说明
alignment配置所有子元素的显示位置
children子组件
class MyApp extends StatelessWidget {
  const MyApp({super.key});

  
  Widget build(BuildContext context) {
    return Center(
      child: Stack(
        alignment: Alignment.topLeft,
        children: [
          Container(
            height: 400,
            width: 300,
            color: Colors.blue,
          ),
          const Text(
            "我是一个文本",
            style: TextStyle(fontSize: 40, color: Colors.white),
          )
        ],
      ),
    );
  }
}

在这里插入图片描述

Align组件

Align 组件可以调整子组件的位置 , Stack 组件中结合 Align 组件也可以控制每个子元素的显示位置

属性说明
alignment配置所有子元素的显示位置
child子组件

Align结合Container的使用

我们先来看一个简单的例子:

FlutterLogoFlutter SDK 提供的一个组件,内容就是 Flutterlog

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  
  Widget build(BuildContext context) {
    return Container(
      height: 300,
      width: 300,
      color: Colors.blue.shade50,
      child: const Align(
        alignment: Alignment.topRight,
        child: FlutterLogo(
          size: 100,
        ),
      ),
    );
  }
}

在这里插入图片描述

Align结合Container的使用

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  
  Widget build(BuildContext context) {
    return Container(
      height: 300,
      width: 300,
      color: Colors.blue.shade50,
      child: const Align(
        alignment: Alignment(2, 0),
        child: FlutterLogo(
          size: 100,
        ),
      ),
    );
  }
}

在这里插入图片描述

Alignment Widget 会以矩形的中心点作为坐标原点,即 Alignment(0, 0) 。 x 、y 的值从 -1 到 1 分别代表矩形左边到右边的距离和顶部到底边的距离,因此 2 个水平(或垂直)单位则等于矩形的宽(或高),如 Alignment(-1, -1) 代表矩形的左侧顶点,而 Alignment(1, 1) 代表右侧底
部终点,而 Alignment(1, -1) 则正是右侧顶点,即 Alignment.topRight。为了使用方便,矩形的原点、四个顶点,以及四条边的终点在 Alignment 类中都已经定义为了静态常量。

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

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

其中 childWidth 为子元素的宽度, childHeight 为子元素高度。

现在我们再看看上面的示例,我们将 Alignment(2, 0) 带入上面公式, ( 2 × 300 / 2 + 300 / 2 , 0 × 300 / 2 + 300 / 2 ) (2 \times 300 / 2 + 300 / 2, 0 \times 300 / 2 + 300 / 2) (2×300/2+300/2,0×300/2+300/2) ,可得 FlutterLogo 的实际偏移坐标正是 (450,150)

Align结合Stack的使用

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  
  Widget build(BuildContext context) {
    return Center(
      child: Container(
        height: 400,
        width: 300,
        color: Colors.blue,
        child: const Stack(
          children: [
            Align(
              alignment: Alignment(1, -0.2),
              child: Icon(Icons.home, size: 40, color: Colors.white),
            ),
            Align(
              alignment: Alignment.center,
              child: Icon(Icons.search, size: 30, color: Colors.white),
            ),
            Align(
              alignment: Alignment.bottomRight,
              child: Icon(Icons.settings_applications,
                  size: 30, color: Colors.white),
            ),
          ],
        ),
      ),
    );
  }
}

在这里插入图片描述

Positioned组件

Stack 组件中结合 Positioned 组件也可以控制每个子元素的显示位置

属性说明
top子元素距离顶部的距离
bottom子元素距离底部的距离
left子元素距离左侧距离
right子元素距离右侧距离
child子组件
width组件的高度(注意:宽度和高度必须是固定值,不能使用 double.infinity
height子组件的高度
class MyApp extends StatelessWidget {
  const MyApp({super.key});

  
  Widget build(BuildContext context) {
    return Center(
      child: Container(
        height: 400,
        width: 300,
        color: Colors.blue,
        child: const Stack(
          children: [
            Positioned(
              left: 10,
              child: Icon(Icons.home, size: 40, color: Colors.white),
            ),
            Positioned(
              bottom: 0,
              left: 100,
              child: Icon(Icons.search, size: 30, color: Colors.white),
            ),
            Positioned(
              right: 0,
              child: Icon(Icons.settings_applications,
                  size: 30, color: Colors.white),
            ),
          ],
        ),
      ),
    );
  }
}

在这里插入图片描述

MediaQuery获取屏幕宽度和高度

前面说到 Positioned 组件的高度和宽度不能使用 double.infinity,在这种情况下,如果我们可以在组件的 build 方法中可以通过 MediaQuery.of(context).size; 来设置

final size = MediaQuery.of(context).size;
final width = size.width;
final height = size.height;

Stack结合Positioned固定导航案例

实现如下效果:

在这里插入图片描述

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  
  Widget build(BuildContext context) {
    final size = MediaQuery.of(context).size;

    return Stack(children: [
      ListView(
        padding: const EdgeInsets.only(top: 45),
        children: const [
          ListTile(
            title: Text("我是标题1"),
          ),
          ListTile(
            title: Text("我是标题2"),
          ),
          ListTile(
            title: Text("我是标题3"),
          ),
          ListTile(
            title: Text("我是标题4"),
          ),
          ListTile(
            title: Text("我是标题5"),
          ),
          ListTile(
            title: Text("我是标题6"),
          ),
          ListTile(
            title: Text("我是标题7"),
          ),
          ListTile(
            title: Text("我是标题8"),
          ),
          ListTile(
            title: Text("我是标题9"),
          ),
          ListTile(
            title: Text("我是标题10"),
          ),
          ListTile(
            title: Text("我是标题11"),
          ),
          ListTile(
            title: Text("我是标题12"),
          ),
          ListTile(
            title: Text("我是标题13"),
          ),
          ListTile(
            title: Text("我是标题14"),
          ),
          ListTile(
            title: Text("我是标题15"),
          ),
        ],
      ),
      Positioned(
        top: 0,
        left: 0,
        height: 40,
        width: size.width,
        child: Container(
          alignment: Alignment.center,
          color: Colors.blue,
          child: const Text(
            "二级导航",
            style: TextStyle(color: Colors.white),
          ),
        ),
      ),
    ]);
  }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1690851.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何修改WordPress网站的域名

我的网站用的是Hostease的虚拟主机,但是域名是之前在其他平台买的,而且已经快到期了,因为主机和域名在不同的平台上,管理不太方便,所以我又在Hostease重新注册了一个域名,然后把网站换成了新的域名&#xf…

【AJAX前端框架】Asynchronous Javascript And Xml

1 传统请求及缺点 传统的请求都有哪些? 直接在浏览器地址栏上输入URL。点击超链接提交form表单使用JS代码发送请求 window.open(url)document.location.href urlwindow.location.href url… 传统请求存在的问题 页面全部刷新导致了用户的体验较差。传统的请求导…

集中抄表电表是什么?

1.集中抄表电表:简述 集中抄表电表,又称为远程抄表系统,是一种现代化电力计量技术,为提升电力行业的经营效率和客户服务质量。它通过自动化的形式,取代了传统人工抄水表,完成了数据信息实时、精确、高效率…

小程序丨公告栏功能,自动弹出提醒

发布查询时,您是否遇到这样的困扰: 1、查询发布时间未到,学生进入查询主页后发现未发布任何查询,不断咨询原因。 2、有些重要事项需要进入查询主页就进行强提醒,确保人人可见,用户需要反馈“我知道了”才…

《拯救大学生课设不挂科第二期之Windows11下安装VC6.0(VC++6.0)与跑通Hello,World!程序教程》【官方笔记】

背景与目标人群: 大学第一次学C语言的时候,大部分老师会选择VC6这个编辑器。 但由于很多人是新手,第一次上大学学C语言。 老师要求VC6.0(VC6.0)写C语言跑程序可能很多人还是第一次接触电脑。 需要安装VC6这个编辑器…

如何零基础快速制作商业画册?这篇攻略帮你搞定

随着社会经济的发展,商业画册作为企业形象和产品介绍的重要载体,越来越受到重视。然而,很多企业和个人由于没有设计背景,在面对制作商业画册时往往感到困惑。本文将为你介绍零基础快速制作商业画册的攻略,让你轻松搞定…

嵌入式实时操作系统笔记1:RTOS入门_理解简单的OS系统

今日开始学习嵌入式实时操作系统RTOS:UCOS-III实时操作系统 本次目标是入门RTOS,理解多任务系统...... 本文只是个人学习笔记,基本都是对网上资料的整合...... 目录 STM32裸机与RTOS区别: 裸机中断示例: RTOS对优先级…

C语言 数组——数组的定义和初始化

目录 为什么使用数组(Array)? 一维数组的定义 一维数组的初始化 一维数组元素的访问 一维数组元素的赋值 数组的逻辑存储结构 数组的物理存储结构 二维数组的定义和初始化 为什么使用数组(Array)? 一维数组的定义 一维 数组的定义 int a[10]; 定义一个有 10 个 int 型元素的…

C++ 网络编程

一、Reactor 网络编程模型 reactor 是一个事件处理模型。网络处理:因为用户层并不知道 IO 什么时候就绪,所以将对 IO 的处理转化为对事件的处理。网络模型构成: 非阻塞 IO:操作 IO,如果 IO 未就绪,IO 函数会立刻返回。IO 多路复用:检测多路 IO 是否就绪。工作流程: 注册…

一文了解 FileBeat:诞生背景、发展历程与定义

🐇明明跟你说过:个人主页 🏅个人专栏:《洞察之眼:ELK监控与可视化》🏅 🔖行路有良友,便是天堂🔖 目录 一、引言 1、什么是ELK 2、FileBeat在ELK中的角色 3、File…

C++的数据结构(十八):并查集

并查集(Union-Find)是一种用于处理一些不交集(Disjoint Sets)问题的数据结构。它主要支持两种操作:合并集合(Union)和查找元素所属集合(Find)。在解决诸如连通性问题、网…

在XP/Vista系统下使用Node.js的babel-cli命令行工具转码ES6语法的js文件,让IE8浏览器也能运行

在XP系统下IE浏览器最高只能装到IE8,在Vista系统下最高只能装到IE9。 2015年以后,JavaScript新增了很多语法,比如class、extends,还有let和const等等,这些语法都是XP下的终端浏览器IE8所不支持的。要想让使用了这些新式…

[集群聊天服务器]----(五)User类、UserModel类

接着上文[集群聊天服务器]----(四)MySQL数据库模块,接下来我们对User类、UserModel类进行剖析,User表和UserModel类是项目最基本也是最重要的部分,通过它我们对用户的id,用户名,密码,状态相关信息进行存储&…

VSCode运行CMake教程

参考视频: https://www.youtube.com/watch?vm9HBM1m_EMU 首先下载&安装opencv包以及cmake包 接着配置环境变量 点击环境变量 ---下面系统变量的path 找对应路径 添加后三个: 确定即可 接着创建空目录 右击vscode打开 扩展中安装 c tools、cmake、cmake too…

华为芯片与系统详细梳理--Kirin麒麟 Ascend昇腾 Kunpeng鲲鹏 HarmonyOS鸿蒙 Euler欧拉

华为芯片与系统详细梳理--Kirin麒麟 & Ascend昇腾 & Kunpeng鲲鹏 & HarmonyOS鸿蒙 & Euler欧拉 1 概述2 芯片2.1 整体描述麒麟芯片(To C)【面向智能终端】昇腾芯片【面向AI计算】鲲鹏芯片【面向通用计算】 2.2 细分系列麒麟芯片&#xf…

基于UDP的tftp的文件传输

#define SER_PORT 69 #define SER_IP "192.168.125.71" #define CLT_PORT 6666 #define CLT_IP "192.168.125.158" int main(int argc, const char *argv[]) {//创建套接字文件描述符int cfd socket(AF_INET,SOCK_DGRAM,0);if(cfd -1){perror("sock…

Hadoop3:HDFS的Fsimage和Edits文件介绍

一、概念 Fsimage文件:HDFS文件系统元数据的一个永久性的检查点,其中包含HDFS文件系统的所有目 录和文件inode的序列化信息。 Edits文件:存放HDFS文件系统的所有更新操作的路径,文件系统客户端执行的所有写操作首先 会被记录到Ed…

掌握RESTful API:从入门到精通,全面解析Web开发的基石!

在现代Web开发中,API(应用程序编程接口)已经成为不同系统之间通信的重要手段。其中,RESTful API是一种基于HTTP协议的设计风格,它简洁、易用且高效。作为一个资深的技术人员,本文将全面详细地介绍RESTful A…

VM逆向,一篇就够了(下)

实战三 d3sky 这一题需要了解一些TLS相关知识 TLS回调函数 TLS(Thread Local Storage,线程局部存储)是各线程的独立的存储空间,TLS回调函数是指,每当创建或终止进程的线程时会自动调用执行的函数,且调用…

蓝桥杯Web开发【国赛】2022年真题

1.水果拼盘 目前 CSS3 中新增的 Flex 弹性布局已经成为前端页面布局的首选方案,本题可以使用 Flex 属性快速完成布局。 1.1 题目问题 建议使用 flex 相关属性完成 css/style.css 中的 TODO 部分。 禁止修改圆盘的位置和图片的大小。相同颜色的水果放在相同颜色的…