Flutter Web:根据浏览器窗口改变布局大小

简介: 之前我们通过flutter开发web应用,然后用electron打包成可执行文件在pc端使用,因为electron可以设置最小宽高,所以布局不会越界,但是如果直接在浏览器中打开,因为浏览器的大小无法控制,如果用户缩小浏览器会导致布局越界。根据大部分网站的经验来看,当窗口缩小到一定程度后,布局就不会再改变,反而是增加了滚动,这样就保证了布局的正确性,所以我们也打算这么做。

前言


之前我们通过flutter开发web应用,然后用electron打包成可执行文件在pc端使用,因为electron可以设置最小宽高,所以布局不会越界,但是如果直接在浏览器中打开,因为浏览器的大小无法控制,如果用户缩小浏览器会导致布局越界。根据大部分网站的经验来看,当窗口缩小到一定程度后,布局就不会再改变,反而是增加了滚动,这样就保证了布局的正确性,所以我们也打算这么做。


监听窗口改变


经过测试,当浏览器窗口改变的时候,并不会执行页面的重绘,所以我们需要想办法监听窗口的改变。

这就需要用到window,先引入


import 'dart:html';
复制代码


然后通过window的onResize来监听,如下:


window.onResize.listen((event) {
  ...
});
复制代码


这里我们实现了监听,但是如何获取窗口的大小,同样还是用window


window.innerWidth
window.innerHeight
复制代码


这样就得到了窗口的大小。


实现滚动布局


滚动布局很简单,通过SingleChildScrollView即可,但是因为可能是两个方向的滚动,所以需要两个SingleChildScrollView嵌套。


Scrollbar(
  isAlwaysShown: true,
  child: SingleChildScrollView(
    scrollDirection: Axis.horizontal,
    child: SingleChildScrollView(
      child: appContent,
    ),
  ),
)
复制代码


这里第一个SingleChildScrollView是横向滚动,并且在外层给它添加了一个滚动条(因为windows机器的鼠标可能不支持横向滚动),然后里面在嵌套一个竖向滚动,最里面就是页面布局。


这样有一个问题,因为两层滚动所以整个布局是无限大的,加载真正的页面的时候就会报错:

RenderSemanticsAnnotations object was given an infinite size during layout.


所以我们要为页面大小加上宽高限制,首先想到的就是在Container的constraints中加入minHeight和minWidth,这是我们的目的


Scrollbar(
  isAlwaysShown: true,
  child: SingleChildScrollView(
    scrollDirection: Axis.horizontal,
    child: SingleChildScrollView(
      child: Container(
        constraints: BoxConstraints(
          minHeight: 720,
          minWidth: 1280
        ),
        child: widget.content,
      ),
    ),
  ),
)
复制代码


但是结果还是报错,因为虽然限制了宽高的最小值,最大值依然是无限大。所以还要加上最大值的限制?


我们可以继续在BoxConstraints中加上maxHeight和maxWidth,但是因为两个SingleChildScrollView导致整个空间是无限大的,所以页面会一直保持maxHeight和maxWidth,这样即使我们缩小一点浏览器而空间依然足够的情况下,页面就会需要滚动而不是压缩排列。


最终我们决定,通过计算来获取宽高,整体代码如下:


class AppContent extends StatefulWidget{
  Widget content;
  AppContent(this.content);
  @override
  State<StatefulWidget> createState() {
    return _AppContent();
  }
}
class _AppContent extends State<AppContent>{
  @override
  Widget build(BuildContext context) {
    return Scrollbar(
      isAlwaysShown: true,
      child: SingleChildScrollView(
        scrollDirection: Axis.horizontal,
        child: SingleChildScrollView(
          child: Container(
            width: max(window.innerWidth.toDouble(), 1280),
            height: max(window.innerHeight.toDouble(), 720),
            child: widget.content,
          ),
        ),
      ),
    );
  }
  @override
  void initState() {
    window.onResize.listen((event) {
      setState(() {
      });
    });
  }
}
复制代码


可以看到,我们通过窗口大小与我们设置的最小尺寸进行比较取较大值,这样就保证了及时窗口很小页面也不会过小而引起越界,而且可以通过滚动来浏览整个页面。

然后我们在App中用AppContent包裹整个app的页面即可。


FittedBox替代


上面有两层滚动布局虽然可以实现我们的效果,但是在浏览器中实际效果不尽人意,因为两个方向上都有滚动,所以在操作时页面很容易移动,而且如果页面上有js拖动效果的(即在HtmlElementView中有一个div通过js实现拖动),在拖动div的同时页面也会跟着动,所以我尝试了更多的widget,最终决定用FittedBox替代,最终代码如下:


class AppContent extends StatefulWidget{
  Widget content;
  AppContent(this.content);
  @override
  State<StatefulWidget> createState() {
    return _AppContent();
  }
}
class _AppContent extends State<AppContent>{
  @override
  Widget build(BuildContext context) {
    return FittedBox(
      fit: BoxFit.cover,
      alignment: Alignment.topLeft,
      child: Container(
        width: max(window.innerWidth.toDouble(), 1280),
        height: max(window.innerHeight.toDouble(), 720),
        child: widget.content,
      ),
    );
  }
  @override
  void initState() {
    window.onResize.listen((event) {
      setState(() {
      });
    });
  }
}
复制代码


BoxFit.cover是按原尺寸填充,所以child可以超出FittedBox的范围。这样虽然不能滑动(如果窗口过小,即使可以滑动也不符合我们的业务需求,所以我们会建议用户全屏,这个仅仅是为了防止用户缩小窗口导致页面溢出错乱),但是页面不会出现溢出的现象。


替换成FittedBox后,滑动问题解决了。但是在浏览器中测试的实际效果与BoxFit.cover描述不太一致,当窗口缩小的时候,内部组件同步缩小了,当缩小到一定程度后才不会继续缩小,这时候页面才会开始显示部分。虽然与期望效果不一致,不过也无所谓,也算达到了需求要求。


目录
相关文章
|
10天前
|
编解码 前端开发 JavaScript
.NET_web前端框架_layui_栅格布局
【8月更文挑战第27天】
28 4
|
12天前
|
Web App开发 iOS开发
Web 浏览器
【8月更文挑战第27天】Web 浏览器。
27 2
|
7天前
|
前端开发 开发者 容器
【布局革命!】Flexbox与Grid双剑合璧:解锁Web设计新纪元,让响应式界面瞬间焕发光彩!
【9月更文挑战第1天】本文通过问答形式深入探讨了Flexbox和Grid布局的特点与应用场景。Flexbox专为单轴布局设计,适用于响应式导航栏和列表;Grid布局则适用于二维布局,可精确控制元素的位置和大小,适合构建复杂的内容区域和仪表板。文章还提供了示例代码,帮助读者更好地理解和应用这两种布局方式,以创建高效、美观的Web界面。
34 9
|
10天前
|
前端开发 开发者 容器
探索现代Web开发中的CSS Grid布局技术
【8月更文挑战第29天】在数字时代的浪潮中,网页设计不断进化以适应日新月异的用户需求。CSS Grid布局技术作为一项革新性的前端工具,为设计师和开发者提供了前所未有的布局能力。本文旨在通过深入浅出的方式介绍CSS Grid的核心概念、基本用法以及在实际项目中的应用,帮助读者快速掌握这一强大的网页布局工具。
33 3
|
13天前
|
前端开发 开发者 容器
【Web布局的革命】探索CSS Grid栅格系统,打造未来网页设计!
【8月更文挑战第25天】在网页设计领域,布局至关重要。传统的布局方法难以满足复杂需求,CSS Grid 栅格系统因此诞生。它是一种二维布局模式,能直接控制行和列,简化复杂网格的设计。通过定义 `display: grid;` 创建网格容器,并利用 `grid-template-columns` 和 `grid-template-rows` 设置行列尺寸,轻松实现响应式布局。此外,CSS Grid 支持高级功能,如网格区域划分和对齐设置,极大提升了布局的灵活性和创意空间。随着浏览器兼容性的增强,CSS Grid 必将成为未来网页设计的关键技术之一。
33 1
|
17天前
|
Dart 前端开发 Java
|
27天前
|
前端开发 开发者 容器
【布局革命!】Flexbox与Grid双剑合璧:解锁Web设计新纪元,让响应式界面瞬间焕发光彩!
【8月更文挑战第12天】面对复杂的网页布局需求,前端开发者需掌握Flexbox与Grid布局技术。Flexbox专为一维布局设计,适用于构建响应式导航栏或列表;Grid则是一种二维布局系统,适合精确控制复杂网格布局。本文通过问答形式深入讲解这两种布局方式的特点、应用场景及使用方法,并提供示例代码,帮助开发者构建高效美观的Web界面。
40 1
|
7天前
|
API UED 开发者
如何在Uno Platform中轻松实现流畅动画效果——从基础到优化,全方位打造用户友好的动态交互体验!
【8月更文挑战第31天】在开发跨平台应用时,确保用户界面流畅且具吸引力至关重要。Uno Platform 作为多端统一的开发框架,不仅支持跨系统应用开发,还能通过优化实现流畅动画,增强用户体验。本文探讨了Uno Platform中实现流畅动画的多个方面,包括动画基础、性能优化、实践技巧及问题排查,帮助开发者掌握具体优化策略,提升应用质量与用户满意度。通过合理利用故事板、减少布局复杂性、使用硬件加速等技术,结合异步方法与预设缓存技巧,开发者能够创建美观且流畅的动画效果。
26 0
|
15天前
|
前端开发 开发者 UED
Web前端布局的救赎:掌握清除浮动的艺术,告别布局混乱!
【8月更文挑战第23天】在Web前端开发中,浮动(float)是一种常用的CSS布局技术,但会导致父元素高度塌陷。清除浮动至关重要,常用方法包括:使用额外的清除元素、伪元素、`overflow`属性、`flexbox`布局、`grid`布局以及`clearfix`方法。每种方法各有优缺点,适用于不同场景。随着新技术的发展,开发者应持续学习,选择合适的方法以确保布局稳定性和提升用户体验。
24 0
|
15天前
|
前端开发 容器
揭秘Web前端布局秘籍:浮动,那个让你又爱又恨的布局神器,你真的了解它吗?
【8月更文挑战第23天】在Web前端设计中,浮动是一种关键布局技术,能让元素在文档流中灵活移动,实现文本环绕图片、多列布局等效果。元素通过CSS的 `float` 属性脱离正常文档流并移动到容器边缘,后续非浮动内容则围绕该元素排列。浮动可用于多列布局、导航菜单及图文混排。需注意清除浮动以避免布局问题,并处理可能导致的父元素高度塌陷。
29 0
下一篇
DDNS