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

Flutter笔记:使用Flutter构建响应式PC客户端/Web页面-案例

Flutter笔记
使用Flutter构建响应式PC客户端/Web页面-案例

作者李俊才 (jcLee95):https://blog.csdn.net/qq_28550263
邮箱 :291148484@163.com
本文地址:https://blog.csdn.net/qq_28550263/article/details/134339945


【简介】也不需要什么简介,使用 Flutter 框架完成下面的响应式PC/Web端效果,你会怎么做呢:
在这里插入图片描述
本文就是介绍相关响应式上的一些工具和实践。


1. Flutter框架中的尺寸工具

Flutter 中,你可以使用 MediaQueryLayoutBuilderAspectRatio 等Widget实现 尺寸测量与约束,进而创建响应式UI。例如,你可以使用 MediaQuery 来获取屏幕的尺寸和方向,然后根据这些信息来动态调整组件的布局和样式。你也可以使用 LayoutBuilder 来根据父组件的尺寸来调整子组件的布局。

1.1 MediaQuery

MediaQuery 组件可以获取当前媒体(例如屏幕)的一些属性,如尺寸、方向、亮度等。你可以使用 MediaQuery.of(context) 来获取一个 MediaQueryData 对象,然后通过这个对象来获取媒体的属性。

例如,你可以使用以下代码来获取屏幕的宽度和高度:

double screenWidth = MediaQuery.of(context).size.width;
double screenHeight = MediaQuery.of(context).size.height;

你也可以使用以下代码来判断当前是否为横屏:

bool isLandscape = MediaQuery.of(context).orientation == Orientation.landscape;

1.2 LayoutBuilder

LayoutBuilder 组件可以根据父组件的约束来生成不同的布局。

LayoutBuilder 的构造函数接受一个回调函数,这个回调函数有两个参数:BuildContextBoxConstraints。 其中 BoxConstraints 对象描述了父组件对子组件的约束,如最大/最小宽度和高度。

例如,你可以使用以下代码来创建一个宽度为父Widget一半的子组件:

LayoutBuilder(builder: (BuildContext context, BoxConstraints constraints) {return Container(width: constraints.maxWidth / 2,child: ...,);},
)

LayoutBuilderMediaQuery 都是 Flutter 中用于获取和处理布局信息的工具,但它们的用途和工作方式有所不同:

  • MediaQuery 主要用于获取媒体(通常是屏幕)的信息,如尺寸、方向、亮度等。你可以使用 MediaQuery 来创建响应式布局,即根据屏幕的尺寸和方向来调整布局。例如,你可以使用 MediaQuery 来获取屏幕的宽度,然后根据宽度来决定显示一个列布局还是行布局;

  • LayoutBuilder主要用于获取父组件对子组件的约束,如最大/最小宽度和高度。你可以使用 LayoutBuilder 来创建自适应布局,即根据父组件的约束来调整子组件的布局。例如,你可以使用 LayoutBuilder来获取父组件的最大宽度,然后根据最大宽度来决定子组件的宽度。

  • MediaQuery 获取的是一个 静态的快照,它获取的屏幕信息在获取时就已经固定,不会随着屏幕尺寸的变化而变化。如果你需要响应屏幕尺寸的变化,你需要在屏幕尺寸变化时重新获取MediaQuery的信息。相比之下, LayoutBuilder 则是动态的,它会在父组件的约束变化时重新构建。这意味着如果父 组件 的尺寸变化了,LayoutBuilder 会自动重新获取约束并重新构建子组件。

可见,如果你需要创建一个能够响应屏幕尺寸变化的布局,你可能需要使用 LayoutBuilder。如果你只需要获取屏幕的信息,并不需要响应屏幕尺寸的变化,那么 MediaQuery 可能更适合你;反之,则需要使用 LayoutBuilder

1.3 AspectRatio

AspectRatio 用于强制子组件具有特定的宽高比。AspectRatio 的构造函数接受一个 aspectRatio参数,这个参数表示宽度和高度的比例。比如:

AspectRatio(aspectRatio: 16 / 9,child: ...,
)

2. 实践:构建响应式Header

我们实现响应式Header的基本思路是,根据屏幕的宽度来选择显示不同的顶部导航栏。整体上,依据这个

class ResponsiveHeaderNavbar extends StatelessWidget {const ResponsiveHeaderNavbar({Key? key}) : super(key: key);Widget build(BuildContext context) {return LayoutBuilder(builder: (context, constraints) {// 使用LayoutBuilder来获取父Widget的尺寸约束// 如果最大宽度小于800像素,返回垂直布局的顶部导航栏if (constraints.maxWidth < 800) {return const VerticalTopNav();} // 否则,返回原始的顶部导航栏else {return const OriginalTopNav();}},);}
}

在这个组件中,LayoutBuilder被用来获取父Widget的尺寸约束,然后根据最大宽度来选择显示哪种顶部导航栏。如果最大宽度小于800像素,就显示垂直布局的顶部导航栏;否则,就显示原始的顶部导航栏。这样,无论屏幕的尺寸如何变化,都能保证顶部导航栏的布局适应屏幕尺寸。

接下来,我们该具体实现 VerticalTopNavOriginalTopNav了。

先看 OriginalTopNav 部分:

class OriginalTopNav extends StatelessWidget {const OriginalTopNav({super.key});Widget build(BuildContext context) {return Container(color: Colors.black,child: const Row(mainAxisAlignment: MainAxisAlignment.spaceEvenly,children: [HoverTextWidget(66),HoverTextWidget(66),HoverTextWidget(66),HoverTextWidget(66),Spacer(),HoverTextWidget(66),],),);}
}

其中的文本组件HoverTextWidget代码为:

class HoverTextWidget extends StatefulWidget {const HoverTextWidget(this.width, {Key? key}) : super(key: key);final double width;State<HoverTextWidget> createState() => _HoverTextWidgetState();
}class _HoverTextWidgetState extends State<HoverTextWidget> {// 定义一个状态变量,用于记录鼠标是否悬停在该组件上bool isHovered = false;// 定义一个方法,用于更新isHovered状态void onHover(bool hover) {setState(() {isHovered = hover;});}Widget build(BuildContext context) {return MouseRegion(// 当鼠标进入该组件时,调用onHover方法并传入trueonEnter: (_) => onHover(true),// 当鼠标离开该组件时,调用onHover方法并传入falseonExit: (_) => onHover(false),// 根据isHovered状态来改变鼠标光标,如果isHovered为true,光标为click,否则为basiccursor: isHovered ? SystemMouseCursors.click : SystemMouseCursors.basic,child: GestureDetector(child: Container(height: 40,alignment: Alignment.center,// 根据isHovered状态来改变背景颜色,如果isHovered为true,背景颜色为grey,否则为blackcolor: isHovered ? Colors.grey : Colors.black,width: widget.width,child: Text('链接',style: TextStyle(// 根据isHovered状态来改变文字颜色,如果isHovered为true,文字颜色为black,否则为whitecolor: isHovered ? Colors.black : Colors.white,),),),),);}
}

在这里插入图片描述

似乎没什么难点需要说明的,那就接着 VelticalTopNav 部分:

class VelticalTopNav extends StatelessWidget {const VelticalTopNav({super.key});Widget build(BuildContext context) {// return const LinkedTabGroup(Axis.vertical);return ExpansionTile(// title: Text(''),title: SvgPicture.asset('/assets/svgs/jcstudio-v2-color.svg',width: 50, // 设置宽度height: 50,),leading: const Icon(Icons.menu, color: Colors.amber),backgroundColor: Colors.black,collapsedBackgroundColor: Colors.black,collapsedIconColor: Colors.amber,collapsedTextColor: Colors.amber,children: [ListTile(title: const Text('链接',style: TextStyle(color: Colors.white),),onTap: () {// 处理子菜单项点击},),ListTile(title: const Text('链接',style: TextStyle(color: Colors.white),),onTap: () {// 处理子菜单项点击},),ListTile(title: const Text('链接',style: TextStyle(color: Colors.white),),onTap: () {// 处理子菜单项点击},),ListTile(title: const Text('链接',style: TextStyle(color: Colors.white),),onTap: () {// 处理子菜单项点击},),],);}
}

这样就完成了整体效果中的Header效果,它将在后面被我们的响应式页面所调用。

在这里插入图片描述

在这里插入图片描述

4. 实践:完成一个响应式Web骨架

同样的思路,我们可以用以完成页面主体部分。

class ExampleHomePage extends StatelessWidget {final String url = '/windows_page_view_2';const ExampleHomePage({super.key});Widget build(BuildContext context) {return Scaffold(body: Column(children: [// 调用上一节写好的 Header(appbar)部分const ResponsiveHeaderNavbar(),Expanded(child: CustomScrollView(slivers: [SliverAppBar(automaticallyImplyLeading: false,pinned: true,snap: false,floating: false,expandedHeight: 460.0,flexibleSpace: FlexibleSpaceBar(background: Image.asset('assets/images/it_curtoon_1.png',fit: BoxFit.cover,),title: const Text('flutter-online.top'),),),// 同样的思路在这里再来一次SliverToBoxAdapter(child: LayoutBuilder(builder: (context, constraints) {if (constraints.maxWidth < 800) {// 当屏幕宽度小于800像素时,改为上下布局return const Column(children: [Part1(),Part2(),],);} else {// 屏幕宽度大于等于800像素时,保持原有布局return Column(children: [Container(padding: const EdgeInsets.only(left: 100, right: 100, top: 30),child: const Row(children: [Expanded(child: Part1(),),SizedBox(width: 260,child: Part2(),),],),),],);}},),),],),),],),);}
}

效果如开头我所展示的那样:
在这里插入图片描述

相关文章:

Flutter笔记:使用Flutter构建响应式PC客户端/Web页面-案例

Flutter笔记 使用Flutter构建响应式PC客户端/Web页面-案例 作者&#xff1a;李俊才 &#xff08;jcLee95&#xff09;&#xff1a;https://blog.csdn.net/qq_28550263 邮箱 &#xff1a;291148484163.com 本文地址&#xff1a;https://blog.csdn.net/qq_28550263/article/detai…...

聊聊LogbackMDCAdapter

序 本文主要研究一下LogbackMDCAdapter MDCAdapter org/slf4j/spi/MDCAdapter.java public interface MDCAdapter {/*** Put a context value (the <code>val</code> parameter) as identified with* the <code>key</code> parameter into the cur…...

spring命名空间注入和XML自动装配、引入外部配置文件

Spring p命名空间注入util命名空间注入基于XML的自动装配根据名称自动装配 Spring引入外部属性配置文件 p命名空间注入 作用&#xff1a;简化配置。 使用p命名空间注入的前提条件包括两个&#xff1a; ● 第一&#xff1a;在XML头部信息中添加p命名空间的配置信息&#xff1a…...

【2024年11月份--2024精灵云校招C++笔试题】

​ 考试形式 笔试考了三道算法题&#xff0c;笔试形式为阅读题目&#xff0c;然后用中文给出算法思路&#xff0c;最后给出算法例程&#xff0c;分数各占一半&#xff0c;简单&#xff0c;中等&#xff0c;复杂各一道题。我看9月份有人也是考这3道题&#xff0c;一模一样。 第…...

Visual Studio 2019下编译OpenCV 4.7 与OpenCV 4.7 contrib

一、环境 使用的环境是Win10,Visual Studio 2019,Cmake3.28,cdua 11.7&#xff0c;cudnn 8.5,如果只是在CPU环境下使用&#xff0c;则不用安装CUDA。要使用GPU处理&#xff0c;安装好CUDA之后&#xff0c;要测试安装的CUDA是否能用。不能正常使用的话&#xff0c;添加一下系统…...

【Linux网络】系统调优之聚合链路bonding,可以实现高可用和负载均衡

一、什么是多网卡绑定 二、聚合链路的工作模式 三、实操创建bonding设备&#xff08;mode1&#xff09; 1、实验 2、配置文件解读 3、查看bonding状态,验证bonding的高可用效果 三、nmcli实现bonding 一、什么是多网卡绑定 将多块网卡绑定同一IP地址对外提供服务&#xf…...

k8s持久化存储PV、PVC

容器磁盘上的文件的生命周期是短暂的&#xff0c;这就使得在容器中运行重要应用时会出现一些问题。首先&#xff0c;当容器崩溃时&#xff0c;kubelet 会重启它&#xff0c;但是容器中的文件将丢失——容器以干净的状态&#xff08;镜像最初的状态&#xff09;重新启动。其次&a…...

CocosCreator3.8原生引擎源码研究

1. Cocos Creator引擎架构图 2. 原始引擎源码流程图 下图中包含Android native层引擎到js适配层的启动和主循环的启用流程和必要说明&#xff0c;本猿比较懒&#xff0c;暂时不细述了&#xff0c;各位看官直接看图吧&#xff0c;还在细化扩充&#xff0c;后续逐渐更新。。。 版…...

高二英语上

unit 1 1.yarn三种意思 1.码&#xff1b; 2.庭院&#xff0c;天井&#xff1b; 3.花园&#xff1b;down**down 在这里是介词,也可以作副词&#xff0c;与 down 相对的是 up。请比较下列两句: 1.Look! Hes driving down the street . 2.Look! Hes driving up the street .这两例…...

JavaWeb Day10 案例 准备工作

目录​​​​​​​ 一、需求说明 二、环境搭建 &#xff08;一&#xff09;数据库 &#xff08;二&#xff09;后端 ①controller层 1.DeptController.java 2.EmpController.java ②mapper层 1.DeptMapper.java 2.EmpMapper.java ③pojo层 1.Dept.java 2.Emp.jav…...

Nginx:不同域名访问同一台机器的不同项目

Nginx很简单就可以解决同一台机器同时跑两个或者多个项目&#xff0c;而且都通过域名从80端口走。 以Windows环境下nginx服务为例&#xff0c;配置文件nginx.conf中&#xff0c;http中加上 include /setup/nginx-1.20.1/conf/conf.d/*.conf;删除server部分&#xff0c;完整如…...

C++(20):new数组时元素个数自动推到

C20在new数组时可以根据初始化列表&#xff0c;自动推到元素个数&#xff1a; #include <iostream> using namespace std;int main() {int *pd new int[]{1,2,3,4};for(auto i 0; i < 4; i){cout<<pd[i]<<endl;}return 0; }运行程序输出&#xff1a; 1…...

使用visualStudio发布可执行文件

编译成功后会在程序项目的路径下创建一个debug文件夹和一个release文件夹 文件夹中的具体文件入下所示 生成32位的可执行文件 32位的可执行文件可以在64位的计算机中执行&#xff0c;而64位的操作系统程序只能在64位的计算机中执行安装运行库的安装包根据电脑的版本选择合适的…...

yolo系列报错(持续补充ing)

文章目录 export GIT_PYTHON_REFRESHquiet解决 没有pt权重文件解决 python文件路径报错解决 读取文件列名报错解决 导入不同文件夹出错解决 megengine没有安装解决然后你发现它竟然还没有用 export GIT_PYTHON_REFRESHquiet 设置环境变量 GIT_PYTHON_REFRESH &#xff0c;这个…...

Technology Strategy Patterns 学习笔记9 - bringing it all together

1 Patterns Map 2 Creating the Strategy 2.1 Ansoff Growth Matrix 和owth-share Matrix 区别参见https://fourweekmba.com/bcg-matrix-vs-ansoff-matrix/ 3 Communicating...

Redis(12)| 过期删除策略和内存淘汰策略

Redis 是可以对 key 设置过期时间的&#xff0c;因此需要有相应的机制将已过期的键值对删除&#xff0c;而做这个工作的就是过期键值删除策略。 如何设置过期时间 先说一下对 key 设置过期时间的命令。 设置 key 过期时间的命令一共有 4 个&#xff1a; expire key n&#x…...

Go-服务注册和发现,负载均衡,配置中心

文章目录 什么是服务注册和发现技术选型 Consul 的安装和配置1. 安装2. 访问3. 访问dns Consul 的api接口go操作consulgrpc下的健康检查grpc的健康检查规范动态获取可用端口号 负载均衡策略1. 什么是负载均衡2. 负载均衡策略1. 集中式load balance2. 进程内load balance3. 独立…...

k8s-实验部署 1

1、k8s集群部署 更改所有主机名称和解析 开启四台实验主机&#xff0c;k8s1 仓库&#xff1b;k8s2 集群控制节点&#xff1b; k8s3 和k8s4集群工作节点&#xff1b; 集群环境初始化 使用k8s1作为仓库&#xff0c;将所有的镜像都保存在本地&#xff0c;不要将集群从外部走 仓库…...

Git的原理与使用(一)

目录 Git初始 Git安装 Git基本操作 创建git本地仓库 配置git 工作区,暂存区,版本库 添加文件,提交文件 查看.git文件 修改文件 版本回退 小结 Git初始 git是一个非常强大的版本控制工具.可以快速的将我们的文档和代码等进行版本管理. 下面这个实例看理解下为什么需…...

1204. 错误票据

题目&#xff1a; 1204. 错误票据 - AcWing题库 思路&#xff1a; 将输入的数据存入数组&#xff0c;从小到大排序后遍历&#xff0c;若 (a[i] a[i - 1])res1 a[i]--->重号;若(a[i] - a[i - 1] > 2)res2 a[i] - 1--->断号。 难点&#xff1a;题目只告诉我们输入…...

PIDtoolbox:工业控制系统PID参数优化的专业级黑盒分析工具

PIDtoolbox&#xff1a;工业控制系统PID参数优化的专业级黑盒分析工具 【免费下载链接】PIDtoolbox PIDtoolbox is a set of graphical tools for analyzing blackbox log data 项目地址: https://gitcode.com/gh_mirrors/pi/PIDtoolbox 在工业自动化、无人机飞控和机器…...

从POC到千万QPS:构建可审计、可回滚、可横向对比的大模型评估指标体系(含金融/医疗双行业基线数据)

第一章&#xff1a;从POC到千万QPS&#xff1a;构建可审计、可回滚、可横向对比的大模型评估指标体系&#xff08;含金融/医疗双行业基线数据&#xff09; 2026奇点智能技术大会(https://ml-summit.org) 在高合规性场景中&#xff0c;大模型评估不能止步于单次离线评测——它…...

nli-distilroberta-base生产环境:低延迟NLI服务在实时对话系统中的嵌入

nli-distilroberta-base生产环境&#xff1a;低延迟NLI服务在实时对话系统中的嵌入 1. 项目概述 nli-distilroberta-base是一个基于DistilRoBERTa模型的轻量级自然语言推理(NLI)服务&#xff0c;专门为生产环境优化设计。它能快速判断两个句子之间的逻辑关系&#xff0c;为实…...

从OBD到UDS:一文搞懂ISO14229 0x19服务中排放与非排放DTC的查询差异与实战

从OBD到UDS&#xff1a;深度解析ISO14229 0x19服务中排放与非排放DTC的差异化处理 在汽车电子控制单元&#xff08;ECU&#xff09;的开发与测试中&#xff0c;诊断故障码&#xff08;DTC&#xff09;的管理一直是工程师面临的核心挑战之一。特别是随着全球排放法规的日益严格&…...

【小白学习大模型】第一天,本地服务器部署大模型

目前部署的Qwen2.5最新结果&#xff1a;(llm_lab) yukeweiinin5880-Virtual-Machine:~/test_qwen$ /home/yukewei/miniconda3/envs/llm_lab/bin/python /home/yukewei/test_qwen/test_qwen2.5_basic.py 正在从本地加载模型&#xff0c;请耐心等待... Failed to load /home/yuke…...

2026年,这家大型快拼箱源头工厂直销厂家,究竟有何独特之处?

在快拼箱行业蓬勃发展的2026年&#xff0c;众多厂家如雨后春笋般涌现&#xff0c;但衡水贝客科技有限公司&#xff08;简称贝客房屋&#xff09;却凭借其独特的优势脱颖而出&#xff0c;成为行业内备受瞩目的大型快拼箱源头工厂直销厂家。接下来&#xff0c;让我们深入探究贝客…...

Qwen3-0.6B-FP8快速上手:用Chainlit打造专属聊天机器人实战

Qwen3-0.6B-FP8快速上手&#xff1a;用Chainlit打造专属聊天机器人实战 1. 准备工作与环境检查 1.1 了解Qwen3-0.6B-FP8模型 Qwen3-0.6B-FP8是Qwen系列最新一代的语言模型&#xff0c;采用FP8精度优化&#xff0c;在保持高性能的同时显著降低计算资源需求。这个60亿参数的模…...

论文AI率标准2026年大变化:各高校各平台最新红线全整理

2026年各高校和检测平台的AI率红线确实有了新的变化&#xff0c;整体趋势是要求越来越严。把目前能收集到的信息整理在一起&#xff0c;供参考。 注意&#xff1a;各高校政策更新比较快&#xff0c;以下信息以2026年初的公开要求为准&#xff0c;具体以所在学校最新通知为准。…...

终极免费学术论文获取指南:如何用Unpaywall一键解锁付费墙

终极免费学术论文获取指南&#xff1a;如何用Unpaywall一键解锁付费墙 【免费下载链接】unpaywall-extension Firefox/Chrome extension that gives you a link to a free PDF when you view scholarly articles 项目地址: https://gitcode.com/gh_mirrors/un/unpaywall-exte…...

5步实现Elsevier期刊审稿状态自动化追踪:告别手动刷新的终极方案

5步实现Elsevier期刊审稿状态自动化追踪&#xff1a;告别手动刷新的终极方案 【免费下载链接】Elsevier-Tracker 项目地址: https://gitcode.com/gh_mirrors/el/Elsevier-Tracker 你是否每天焦虑地刷新Elsevier投稿系统&#xff0c;只为查看审稿进度&#xff1f;Elsevi…...