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

🔥 本文由 程序喵正在路上 原创,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),
          ),
        ),
      ),
    ]);
  }
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

第十五届“北斗杯”全国青少年空天科技体验与创新大赛安徽赛区阜阳市解读会议

5月19日,第十五届“北斗杯”全国青少年空天科技体验与创新大赛安徽赛区阜阳解读活动在阜阳市图书馆隆重举行。共青团阜阳市委员会学少部副部长丁晓龙、阜阳市师范大学物理系副主任黄银生教授、安徽科技报阜阳站站长李伟、市人工智能学会秘书长郭广泽、“北斗杯”安徽…

牛客NC236 最大差值【simple 动态规划 Java/Go/PHP】

题目 题目链接: https://www.nowcoder.com/practice/a01abbdc52ba4d5f8777fb5dae91b204 思路 不难看出该题可以使用动态规划的方式解题。 在循环数组的过程中,记录截止到当前位置-1的最小值, 然后用当前的值去计算最大的差值。Java代码 im…

AI时代下对于bloger的影响

前言 AI已经不是一个新词儿了,相信能看到这篇文章的同学都使用AI工具。AI工具已经渗透各行各业了。今天简谈一下AI对我们技术bloger的影响。 文章的访问量变少了 文章的访问量主要是两个渠道,博客平台内部推送,搜索引擎推送。AI的兴起肯定会…

每日练习之深度优先搜索——最大的湖

最大的湖 题目描述 运行代码 #include<iostream> using namespace std; bool mp[102][102]; int sum,num; int N,M,K; int dfs(int x,int y ) {if( mp[x][y] ){mp[x][y]0;sum;dfs(x1,y);dfs(x-1,y);dfs(x,y1);dfs(x,y-1);}return 0; } int main() {cin>>N>>…

【B站 heima】小兔鲜Vue3 项目学习笔记Day02

文章目录 Pinia1.使用2. pinia-计数器案例3. getters实现4. 异步action5. storeToRefsx 数据解构保持响应式6. pinia 调试 项目起步1.项目初始化和git管理2. 使用ElementPlus3. ElementPlus 主题色定制4. axios 基础配置5. 路由设计6. 静态资源初始化和 Error lens安装7.scss自…

无人机+飞行服务:无人机飞防服务(打药+施肥+播种)技术详解

无人机飞防服务&#xff0c;结合了先进的无人机技术与农业实践&#xff0c;为现代农业提供了高效、精准的打药、施肥和播种解决方案。以下是对这些技术的详细解析&#xff1a; 一、无人机打药技术 无人机打药技术利用无人机搭载喷雾设备&#xff0c;对农田进行精准施药。通过…

【Numpy】深入解析numpy.mgrid()函数

numpy.mgrid()&#xff1a;多维网格生成与数值计算的利器 &#x1f308; 欢迎莅临我的个人主页&#x1f448;这里是我深耕Python编程、机器学习和自然语言处理&#xff08;NLP&#xff09;领域&#xff0c;并乐于分享知识与经验的小天地&#xff01;&#x1f387; &#x1f393…

vuejs路由和组件系统

前端路由原理 createRouter * hash* window.addEventListener(hashChange)* 两种实现路由切换的模式&#xff1a;UI组件&#xff08;router-link&#xff0c;router-view&#xff09;&#xff0c;Api&#xff08;push()方法&#xff09; * history * HTML5新增的API &#xff0…

Qt下使用QImage和OpenCV实现图像的拼接与融合

文章目录 前言一、使用QImage进行水平拼接二、使用OpenCV进行水平拼接三、使用OpenCV进行图像融合四、示例完整代码总结 前言 本文主要讲述了在Qt下使用QImage和OpenCV实现图像的拼接与融合&#xff0c;并结合相应的示例进行讲解&#xff0c;以便大家学习&#xff0c;如有错误…

分割文本文件

分割一个.txt文件&#xff0c;可以选择在命令行中使用split指令&#xff0c;或者编写一段脚本进行操作。以下是一个简单的Python脚本来分割文本文件&#xff1a; def split_file(file, lines):# Open source filewith open(file, r) as source:count 0atEOF Falsewhile not …

齐护K210系列教程(三十四)_视觉PID巡线小车

视觉PID巡线小车 1.前言2.简介3.代码讲解3.1初始化3.2.色块查找3.3色块分析3.3.1 区域13.3.2 区域2 3.4 侦测关键点部分3.4.1正常巡线3.4.2 右转路口 3.4.3十字路口3.4. PID计算 4.完整代码5.小车端程序6.参考程序联系我们 1.前言 本课程主要讲述如何使用AIstart_k210主板完成…

SpringMVC接收请求参数的方式:

接收简单变量的请求参数 直接使用简单变量作为形参进行接收&#xff08;这里简单变量名称需要与接收的参数名称保持一致&#xff0c;否则需要加上RequestParam注解&#xff09;&#xff1a; 细节&#xff1a; 1&#xff1a;SpringMVC会针对常见类型&#xff08;八种基本类型及…

【Crypto】一眼就解密

文章目录 前言一眼就解密解题感悟 前言 Basic写累了&#xff0c;写写别的 一眼就解密 一眼md5试一试 小小flag 拿下&#xff01; 解题感悟 30秒搞定

Python第三方包安装与配置教程

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一、Windows系统下的Python包安装 二、Linux系统下的Python包安装 三、配置Python环境 四…

打印9*9乘法表(递归或压缩矩阵)python

打印9*9表def print_multiplication_table(row, col):if row > 10:return # 递归结束条件if col row:print() # 换行print_multiplication_table(row 1, 1) # 递归调用下一行else:print(f"{row-1} * {col} {(row-1) * col}\t", end"") # 打印乘法…

Top3专业课150满分,怎么考的?

这个系列会邀请上岸学长学姐进行经验分享~ 今天经验分享的同学是小马哥上海交大819的全程班学员&#xff0c;专业课150分满分&#xff0c;这位同学也是819期末考试的第一名&#xff0c;非常厉害&#xff01;大家吸吸欧气&#xff01; 初试成绩单 前言 先介绍下自己&#xff0…

mysql binlog统一恢复误删数据库、表、数据(没有任何备份)

先将mysql文件夹中的my.ini进行设置 在 [mysqld]下边加上 # mysql-bin 是日志的基本名或前缀名&#xff0c;最后生成的日志文件是mysql-bin.000001类似&#xff0c;重启mysql数字会递增 log_binmysql-bin #binlog格式&#xff0c;statement&#xff0c;row&#xff0c;mixed可…

慢性乙型肝炎肝脏剪切波弹性成像的深度学习放射学显著改善了肝纤维化的诊断性能 | 文献速递-深度学习结合影像组学

慢性乙型肝炎肝脏剪切波弹性成像的深度学习放射学显著改善了肝纤维化的诊断性能 | 文献速递-深度学习结合影像组学 麦田医学 美好事物中转站 2024-05-21 11:03 Title 题目 Deep learning Radiomics of shear wave elastography significantly improved diagnostic performa…

【linux-kernel内核移植记录-踩坑以及注意事项】

目录 1. 环境介绍2.编译原厂的kernel2.1 通过tftp挂载原厂linux内核 3. 修改对应的驱动3.1 修改CPU频率3.2 修改MMC3.3 修改网络驱动 4. 总结 1. 环境介绍 ubuntu版本16.04I.MX6ULL开发板&#xff0c;阿尔法uboot正常启动&#xff0c;能ping通ubuntu&#xff0c;可通过tftpboo…

【0007day】总体标准差、样本标准差和无偏估计

文章目录 总体标准差和样本标准差无偏估计无偏性与无偏估计量 总体标准差和样本标准差 一些表示上的差别。 总体标准差 样本标准差 两者的区别 样本方差为什么除以n-1? 这主要是由于样本的方差会低估总体的方差&#xff08;抽样的过程中&#xff0c;按照概率来说&#xff0…