本文主要介绍Flutter布局中的LimitedBox、Offstage、OverflowBox、SizedBox四种控件,详细介绍了其布局行为以及使用场景,并对源码进行了分析。

1. LimitedBox

A box that limits its size only when it's unconstrained.

1.1 简介

LimitedBox,通过字面意思,也可以猜测出这个控件的作用,是限制类型的控件。这种类型的控件前面也介绍了不少了,这个是对最大宽高进行限制的控件。

1.2 布局行为

LimitedBox是将child限制在其设定的最大宽高中的,但是这个限定是有条件的。当LimitedBox最大宽度不受限制时,child的宽度就会受到这个最大宽度的限制,同理高度。

1.3 继承关系

Object > Diagnosticable > DiagnosticableTree > Widget > RenderObjectWidget > SingleChildRenderObjectWidget > LimitedBox

1.4 示例代码

Row(
children: <Widget>[
Container(
color: Colors.red,
width: 100.0,
),
LimitedBox(
maxWidth: 150.0,
child: Container(
color: Colors.blue,
width: 250.0,
),
),
],
)

1.5 源码解析

const LimitedBox({
Key key,
this.maxWidth = double.infinity,
this.maxHeight = double.infinity,
Widget child,
})

1.5.1 属性解析

maxWidth:限定的最大宽度,默认值是double.infinity,不能为负数。

maxHeight:同上。

1.5.2 源码

先不说其源码,单纯从其作用,前面介绍的SizedBox、ConstrainedBox都类似,都是通过强加到child的constraint,来达到相应的效果。

我们直接看其计算constraint的代码

minWidth: constraints.minWidth,
maxWidth: constraints.hasBoundedWidth ? constraints.maxWidth : constraints.constrainWidth(maxWidth),
minHeight: constraints.minHeight,
maxHeight: constraints.hasBoundedHeight ? constraints.maxHeight : constraints.constrainHeight(maxHeight)

LimitedBox只是改变最大宽高的限定。具体的布局代码如下:

if (child != null) {
child.layout(_limitConstraints(constraints), parentUsesSize: true);
size = constraints.constrain(child.size);
} else {
size = _limitConstraints(constraints).constrain(Size.zero);
}

根据最大尺寸,限制child的布局,然后将自身调节到child的尺寸。

1.6 使用场景

使用场景是不可能清楚了,光是找例子,就花了不少时间。Flutter的一些冷门控件,真的是除了官方的文档,啥材料都木有。谷歌说这个很有用,还是一脸懵逼。这种控件,也有其他的替代解决方案,LimitedBox可以达到的效果,ConstrainedBox都可以实现。

2. Offstage

A widget that lays the child out as if it was in the tree, but without painting anything, without making the child available for hit testing, and without taking any room in the parent.

2.1 简介

Offstage的作用很简单,通过一个参数,来控制child是否显示,日常使用中也算是比较常用的控件。

2.2 布局行为

Offstage的布局行为完全取决于其offstage参数

  • 当offstage为true,当前控件不会被绘制在屏幕上,不会响应点击事件,也不会占用空间;
  • 当offstage为false,当前控件则跟平常用的控件一样渲染绘制;

另外,当Offstage不可见的时候,如果child有动画,应该手动停掉,Offstage并不会停掉动画。

2.3 继承关系

Object > Diagnosticable > DiagnosticableTree > Widget > RenderObjectWidget > SingleChildRenderObjectWidget > Offstage

2.4 示例代码

Column(
children: <Widget>[
new Offstage(
offstage: offstage,
child: Container(color: Colors.blue, height: 100.0),
),
new CupertinoButton(
child: Text("点击切换显示"),
onPressed: () {
setState(() {
offstage = !offstage;
});
},
),
],
)

当点击切换按钮的时候,可以看到Offstage显示消失。

2.5 源码解析

const Offstage({ Key key, this.offstage = true, Widget child })

2.5.1 属性解析

offstage:默认为true,也就是不显示,当为flase的时候,会显示该控件。

2.5.2 源码

我们先来看下Offstage的computeIntrinsicSize相关的方法:

@override
double computeMinIntrinsicWidth(double height) {
if (offstage)
return 0.0;
return super.computeMinIntrinsicWidth(height);
}

可以看到,当offstage为true的时候,自身的最小以及最大宽高都会被置为0.0。

接下来我们来看下其hitTest方法:

  @override
bool hitTest(HitTestResult result, { Offset position }) {
return !offstage && super.hitTest(result, position: position);
}

当offstage为true的时候,也不会去执行。

最后我们来看下其paint方法:

@override
void paint(PaintingContext context, Offset offset) {
if (offstage)
return;
super.paint(context, offset);
}

当offstage为true的时候直接返回,不绘制了。

到此,跟上面所说的布局行为对应上了。我们一定要清楚一件事情,Offstage并不是通过插入或者删除自己在widget tree中的节点,来达到显示以及隐藏的效果,而是通过设置自身尺寸、不响应hitTest以及不绘制,来达到展示与隐藏的效果。

2.6 使用场景

当我们需要控制一个区域显示或者隐藏的时候,可以使用这个场景。其实也有其他代替的方法,但是成本会高很多,例如直接在tree上插入删除,但是不建议这么做。

3. OverflowBox

A widget that imposes different constraints on its child than it gets from its parent, possibly allowing the child to overflow the parent.

3.1 简介

OverflowBox这个控件,允许child超出parent的范围显示,当然不用这个控件,也有很多种方式实现类似的效果。

3.2 布局行为

当OverflowBox的最大尺寸大于child的时候,child可以完整显示,当其小于child的时候,则以最大尺寸为基准,当然,这个尺寸都是可以突破父节点的。最后加上对齐方式,完成布局。

3.3 继承关系

Object > Diagnosticable > DiagnosticableTree > Widget > RenderObjectWidget > SingleChildRenderObjectWidget > OverflowBox

3.4 示例代码

Container(
color: Colors.green,
width: 200.0,
height: 200.0,
padding: const EdgeInsets.all(5.0),
child: OverflowBox(
alignment: Alignment.topLeft,
maxWidth: 300.0,
maxHeight: 500.0,
child: Container(
color: Color(0x33FF00FF),
width: 400.0,
height: 400.0,
),
),
)

当maxHeight大于height的时候,可以完全显示下来,当maxHeight小于height的时候,则不会会被隐藏掉

3.5 源码解析

构造函数如下:

const OverflowBox({
Key key,
this.alignment = Alignment.center,
this.minWidth,
this.maxWidth,
this.minHeight,
this.maxHeight,
Widget child,
})

3.5.1 属性解析

alignment:对齐方式。

minWidth:允许child的最小宽度。如果child宽度小于这个值,则按照最小宽度进行显示。

maxWidth:允许child的最大宽度。如果child宽度大于这个值,则按照最大宽度进行展示。

minHeight:允许child的最小高度。如果child高度小于这个值,则按照最小高度进行显示。

maxHeight:允许child的最大高度。如果child高度大于这个值,则按照最大高度进行展示。

其中,最小以及最大宽高度,如果为null的时候,就取父节点的constraint代替。

3.5.2 源码

OverflowBox的源码很简单,我们先来看一下布局代码:

if (child != null) {
child.layout(_getInnerConstraints(constraints), parentUsesSize: true);
alignChild();
}

如果child不为null,child则会按照计算出的constraints进行尺寸的调整,然后对齐。

至于constraints的计算,则还是上面的逻辑,如果设置的有的话,就取这个值,如果没有的话,就拿父节点的。

3.6 使用场景

有时候设计图上出现的角标,会超出整个模块,可以使用OverflowBox控件。但我们应该知道,不使用这种控件,也可以完成布局,在最外面包一层,也能达到一样的效果。具体实施起来哪个比较方便,同学们自行取舍。

4. SizedBox

A box with a specified size.

4.1 简介

比较常用的一个控件,设置具体尺寸。

4.2 布局行为

SizedBox布局行为相对较简单:

  • child不为null时,如果设置了宽高,则会强制把child尺寸调到此宽高;如果没有设置宽高,则会根据child尺寸进行调整;
  • child为null时,如果设置了宽高,则自身尺寸调整到此宽高值,如果没设置,则尺寸为0;

4.3 继承关系

Diagnosticable > DiagnosticableTree > Widget > RenderObjectWidget > SingleChildRenderObjectWidget > SizedBox

4.4 示例代码

Container(
color: Colors.green,
padding: const EdgeInsets.all(5.0),
child: SizedBox(
width: 200.0,
height: 200.0,
child: Container(
color: Colors.red,
width: 100.0,
height: 300.0,
),
),
)

4.5 源码解析

构造函数

const SizedBox({ Key key, this.width, this.height, Widget child })

4.5.1 属性解析

width:宽度值,如果具体设置了,则强制child宽度为此值,如果没设置,则根据child宽度调整自身宽度。

height:同上。

4.5.2 源码

SizedBox内部是通过RenderConstrainedBox来实现的。具体的源码就不解析了,总体思路是,根据宽高值算好一个constraints,然后强制应用到child上。

4.6 使用场景

这个控件,很多场景可以使用。但是,可以替代它的控件也有不少,例如Container、ConstrainedBox等。而且SizedBox就是ConstrainedBox的一个特例。还是那句话,精简啊,多提供一些常用的,不要提供一大堆重复的,场景很少的控件。

5. 后话

笔者建了一个Flutter学习相关的项目,Github地址,里面包含了笔者写的关于Flutter学习相关的一些文章,会定期更新,文章中的代码也在这个项目中,欢迎大家关注。

6. 参考

  1. LimitedBox class
  2. Offstage class
  3. OverflowBox class
  4. SizedBox class

Flutter 布局(五)- LimitedBox、Offstage、OverflowBox、SizedBox详解的更多相关文章

  1. [五]基础数据类型之Short详解

      Short 基本数据类型short  的包装类 Short 类型的对象包含一个 short 类型的字段      原文地址:[五]基础数据类型之Short详解   属性简介   值为  215-1 ...

  2. “全栈2019”Java异常第十五章:异常链详解

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java异 ...

  3. CSS布局之脱离文档流详解——浮动、绝对定位脱离文档流的区别

    1.代码 (1)示例代码1 <!DOCTYPE html> <html lang="zh"> <head> <meta charset=& ...

  4. Flutter之 LimitedBox、Offstage、OverflowBox、SizedBox详解

    1. LimitedBox A box that limits its size only when it's unconstrained. 1.1 简介 LimitedBox,通过字面意思,也可以猜 ...

  5. View绘制详解(五),draw方法细节详解之View的滚动/滑动问题

    关于View绘制系列的文章已经完成了四篇了,前面四篇文章主要带小伙伴们熟悉一下View的体系的整体框架.View的测量以及布局等过程,从本篇博客开始,我们就来看看View的绘制过程.View的绘制涉及 ...

  6. 第五章 MVC之Bundle详解

    一.简述 Bundle,英文原意就是捆.收集.归拢.在MVC中的Bundle技术,也就是一个对css和js文件的捆绑压缩的技术. 它的用处: 将多个请求捆绑为一个请求,减少服务器请求数 压缩javas ...

  7. Python 自动化测试全攻略:五种自动化测试模型实战详解

    随着移动互联网的发展,软件研发模型逐步完善,软件交付质量越来越受到软件公司的重视,软件测试技术特别是自动化测试技术开始在软件系统研发过程中发挥着越来越重要的作用. 与传统的手工测试技术相比,自动化测试 ...

  8. java基础(十五)----- Java 最全异常详解 ——Java高级开发必须懂的

    本文将详解java中的异常和异常处理机制 异常简介 什么是异常? 程序运行时,发生的不被期望的事件,它阻止了程序按照程序员的预期正常执行,这就是异常. Java异常的分类和类结构图 1.Java中的所 ...

  9. 微服务之SpringCloud实战(五):SpringCloud Eureka详解

    Eureka详解 在第三节高可用中,实际已经讲解了服务的注册,只不过注册的是Eureka本身,原理相同,通过这几篇文章我相信大家对Eureka有了一定的了解,三个核心角色:服务注册中心.服务提供者和服 ...

随机推荐

  1. Mac OS Eclipse 调试快捷键不好使(失效)的情况

    Eclipse调试使用的F5  F6  F8一直都好用,结果一次调试后忽然不好使. 问题原因,尚未知晓. 解决办法,重启机器.

  2. “五年经验”年薪50W分享Java程序员掌握什么技术才不会被淘汰

    在这个IT系统动辄就是上亿流量的时代,Java作为大数据时代应用最广泛的语言,诞生了一批又一批的新技术,包括HBase.Hadoop.MQ.Netty.SpringCloud等等 . 一些独角兽公司以 ...

  3. .NET Core 如何调用 WebService

    0.使用背景 因为现在的项目都是基于 .NET Core 的,但是某些需要调用第三方的 WebService 服务,故有了此文章.其基本思路是通过微软提供的 Svcutil 工具生成代理类,然后通过 ...

  4. odoo开发笔记--取消正在升级中模块

    场景描述: 开发过程中,有时候会遇到,模块安装的时候,一直卡着,走不过去:或者安装报错,导致进入了系统! 这个时候,怎么处理呢? 先简单说下,odoo中模块的升级有4个状态,模块相关的安装情况记录在表 ...

  5. Jenkins技巧:如何启动、停止、重启、重载Jenkins

    ----------------------------------------------------------------- 原创博文,如需转载请通知作者并注明出处! 博主:疲惫的豆豆 链接:h ...

  6. 《JavaScript总结》js模块化

    模块化开发,可以让代码易于扩展.便于日后维护. ES6中的模块化 我们先了解一下 export(导出) 和 import(导入) 这两个关键字. 新建一个文件a.js 并且导出变量test expor ...

  7. 1197多行事务要求更大的max_binlog_cache_size处理与优化

    1197多语句事务要求更大的max_binlog_cache_size报错   binlog_cache_size:为每个session 分配的内存,在事务过程中用来存储二进制日志的缓存,提高记录bi ...

  8. 逆向实战干货,植物大战僵尸快速定位自动捡阳光Call,或者标志

    逆向实战干货,快速定位自动捡阳光Call,或者标志 注意: 关于CE和OD的使用,这里不再多说,快速定位,默认大家已经有了CE基础,或者OD基础. 第一种方法,找Call 第一步,打开CE,搜索阳光值 ...

  9. 举个栗子看如何做MySQL 内核深度优化

    本文由云+社区发表 作者介绍:简怀兵,腾讯云数据库高级工程师,负责腾讯云CDB内核及基础设施建设:先后供职于Thomson Reuters和YY等公司,PTimeDB作者,曾获一项发明专利:从事MyS ...

  10. 1.Magicodes.NET框架之路——起航

    1.Magicodes.NET框架之路--起航 前言 从事开发也好几年了,并且最近一直在做架构搭建的工作.这些时间,最大的感悟就是: 只有自己理解了的才是自己的. 对架构这块,若欲立之,必先破之. 故 ...