简介

我们在flutter中使用layout的时候需要经常对组件进行一些大小的限制,这种限制就叫做constraints,用来控制layout中的组件大小。

掌握了constraints才算对layout有了真正的了解,但是flutter中的constraints和我们熟悉的HTML中的constraints区别比较大,所以我们还是需要深入了解flutter中contraints的特性。

Tight和loose constraints

对于constraints来说,只有四个属性,分别是最小width,最大width,最小height和最大height。这四个属性所能限制的就是宽度和高度的范围。

根据这两个属性的范围不同,constraints可以分为tight constraints和loose constraints。

那么tight和loose有什么区别呢?

对于tight来说,它的 maximum width = minimum width, 并且maximum height = minimum height, 也就是说为width和height提供了一个特定的值。

具体而言,可以看下BoxConstraints的tight实现:

BoxConstraints.tight(Size size)
: minWidth = size.width,
maxWidth = size.width,
minHeight = size.height,
maxHeight = size.height;

和tight相对应的就是loose,在loose中我们设置了最大的width和height,但是希望widget越小越好,这样对应width和height的最小值为0,同样以BoxConstraints为例看下它的定义:

BoxConstraints.loose(Size size)
: minWidth = 0.0,
maxWidth = size.width,
minHeight = 0.0,
maxHeight = size.height;

理解constraints的原则

前面我们讲到了constraints的分类,这里我们会讲一下constraints的基本原则。

通常来说,在flutter中,一个widget的constraints是从它的parent继承而来的。然后这个widget会将constraints告诉他的子widget.

子widget会有自己定义的大小,那么子widget会根据自己定义的大小来设置自己的大小,并将结果反馈跟父widget,父widget会最终根据所有子widget的大小来设置自己的大小。

所以总结而言就是,constraints是向下传递的,而size是向上传递的。

可能大家还不太明白是什么意思,没关系,接下来我们用具体的例子来说明。

首先,我们使用BoxConstraints.tightFor来创建一个尽可能大的width和height的Constraints,然后在这个constraint内部新建widget来观察他们的表现。

ConstrainedBox(
constraints: const BoxConstraints.tightFor(
width: double.infinity, height: double.infinity),
child: exampleWidget)

通过替换上面的exampleWidget,我们来观察不同的表现形式。

首先是最基础的Container,对于Container本身来说,他可以设置width和height,但是这两个属性并不是constraint,所以还得从parent widget中继承。

那么对于下面的一个widget来说:

  Widget build(BuildContext context) {
return Container(color: blue);
}

它会使用从parent继承的constraints,也就是说尽可能的大,所以会展示下面的界面:

填满所有的区域。

如果给Container指定了width和hight,同样的,Container需要从parent继承constraints,所以仍然是填满整个区域:

  Widget build(BuildContext context) {
return Container(width: 100, height: 100, color: blue);
}

但是,如果我们在Container的外面再加上一个constraints,比如Center:

  Widget build(BuildContext context) {
return Center(
child: Container(width: 100, height: 100, color: blue),
);
}

那么虽然Center会从parent继承constraints,去填满整个区域,但是Center本身的constraints是告诉子widget可以按照他自己的意愿来调整大小,所以这个时候最终Container的大小就是100x100:

除了Center之外,我们还可以使用Align,效果和Center是一致的:

  Widget build(BuildContext context) {
return Align(
alignment: Alignment.bottomLeft,
child: Container(width: 100, height: 100, color: blue),
);
}

下面是一个使用Center的很有趣的例子:

  Widget build(BuildContext context) {
return Center(
child: Container(
color: blue,
child: Container(color: green, width: 30, height: 30),
),
);
}

这里Center中有一个Container,Container中有一个Container,但是这两个Container设置了不同的颜色。

因为外层的Container并没有设置大小,所以他的大小是由child Container来决定的,因为两个Container大小一样,所以外部的颜色会被内部的覆盖,我们可以得到下面的界面:

如果我们给外层的添加一个padding如下:

  Widget build(BuildContext context) {
return Center(
child: Container(
padding: const EdgeInsets.all(20.0),
color: blue,
child: Container(color: green, width: 30, height: 30),
),
);
}

那么外层现在就比内层的widget要大了,颜色也可以展示出来了:

我们再来看下面的例子:

  Widget build(BuildContext context) {
return ConstrainedBox(
constraints: const BoxConstraints(
minWidth: 70,
minHeight: 70,
maxWidth: 150,
maxHeight: 150,
),
child: Container(color: blue, width: 10, height: 10),
);
}

上面的例子在Container外面添加了一个ConstrainedBox,指定了四个constraints属性,但是这个ConstrainedBox并不会应用到child上,所以最终得到的界面还是全部的蓝色。

为什么呢?这是因为不同的widget对constraints有不同的定义,对于ConstrainedBox来说,他是一个对其子项施加额外约束的小部件。记住,这里是额外的约束。因为对于它的parent来说,约束已经制定好了,所以ConstrainedBox会被忽略。

我们再看下下面的代码:

  Widget build(BuildContext context) {
return Center(
child: ConstrainedBox(
constraints: const BoxConstraints(
minWidth: 70,
minHeight: 70,
maxWidth: 150,
maxHeight: 150,
),
child: Container(color: blue, width: 10, height: 10),
),
);
}

这里因为使用了Center,Center会让child来自行决定他们的大小,所以这里的ConstrainedBox是生效的,如下:

flutter中除了ConstrainedBox,还有一个UnconstrainedBox,它的作用和ConstrainedBox是相反的,大家可以自行尝试。

总结

从上面的具体例子,我们可以看出,虽然我们有通用的Constraint规则,但是具体的表现还是要看不同的widget来定。

所以大家在使用widget的时候,一定要去读一下widget的代码,从而加深对widget的掌握。

本文的例子:https://github.com/ddean2009/learn-flutter.git

更多内容请参考 http://www.flydean.com/13-flutter-ui-constraints/

最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧等你来发现!

欢迎关注我的公众号:「程序那些事」,懂技术,更懂你!

flutter系列之:深入理解布局的基础constraints的更多相关文章

  1. flutter系列之:移动端的手势基础GestureDetector

    目录 简介 Pointers和Listener GestureDetector 手势冲突 总结 简介 移动的和PC端有什么不同呢?同样的H5可以运行在APP端,也可以运行在PC端.两者最大的区别就是移 ...

  2. flutter系列之:把box布局用出花来

    目录 简介 LimitedBox SizedBox FittedBox 总结 简介 flutter中的layout有很多,基本上看layout的名字就知道这个layout到底是做什么用的.比如说这些l ...

  3. 深入理解mysql之BDB系列(1)---BDB相关基础知识

        深入理解mysql之BDB系列(1) ---BDB相关基础知识 作者:杨万富   一:BDB体系结构 1.1.BDB体系结构 BDB总体的体系结构如图1.1所看到的,包括五个子系统(见图1.1 ...

  4. c#基础系列3---深入理解ref 和out

    "大菜":源于自己刚踏入猿途混沌时起,自我感觉不是一般的菜,因而得名"大菜",于自身共勉. 扩展阅读 c#基础系列1---深入理解 值类型和引用类型 c#基础系 ...

  5. Flutter系列博文链接

    Flutter系列博文链接 ↓: Flutter基础篇: Flutter基础篇(1)-- 跨平台开发框架和工具集锦 Flutter基础篇(2)-- 老司机用一篇博客带你快速熟悉Dart语法 Flutt ...

  6. [转]Java多线程干货系列—(一)Java多线程基础

    Java多线程干货系列—(一)Java多线程基础 字数7618 阅读1875 评论21 喜欢86 前言 多线程并发编程是Java编程中重要的一块内容,也是面试重点覆盖区域,所以学好多线程并发编程对我们 ...

  7. spring cloud系列教程第四篇-Eureka基础知识

    通过前三篇文章学习,我们搭建好了两个微服务工程.即:order80和payment8001这两个服务.有了这两个基础的框架之后,我们将要开始往里面添加东西了.还记得分布式架构的几个维度吗?我们要通过一 ...

  8. 理解RxJava:(一)基础知识

    理解RxJava:(一)基础知识 本文翻译自Grokking RxJava, Part 1: The Basics,著作权归原作者danlew所有.译文由JohnTsai翻译.转载请注明出处,并保留此 ...

  9. 第九十三节,html5+css3移动手机端流体布局,基础CSS,头部设计,轮播设计,底部设计

    html5+css3移动手机端流体布局,基础CSS,头部设计,轮播设计,底部设计 基础CSS 首先将通用css属性写好 @charset "utf-8"; /*通用样式*/ /*去 ...

随机推荐

  1. Dubbo源码(二) - SPI源码

    前情提要 假设你已经知道Dubbo SPI的使用方式,不知道的请出门左转: Dubbo源码(一) - SPI使用 Dubbo源码地址: apache/dubbo 本文使用版本:2.6.x 测试Demo ...

  2. C# 实例解释面向对象编程中的依赖反转原则

    在面向对象编程中,SOLID 是五个设计原则的首字母缩写,旨在使软件设计更易于理解.灵活和可维护.这些原则是由美国软件工程师和讲师罗伯特·C·马丁(Robert Cecil Martin)提出的许多原 ...

  3. python jinjia2 使用语法

    简介 对于jinjia2来说,模板仅仅是文本文件,可以生成任何基于文本的文件格式,例如HTML.XML.CSV.LaTex 等等,以下是基础的模板内容: <!DOCTYPE html> & ...

  4. pathlib相关操作

    简介 python中操作文件或者文件夹的模块目前我知道的有四个,分别为os.shutil.pathlib.glob,在了解到pathlib之前,我一直使用的是os进行相关路径的操作,但在使用了path ...

  5. 精心总结十三条建议,帮你创建更合适的MySQL索引

    上篇文章讲到使用MySQL的Explain命令可以分析SQL性能瓶颈,优化SQL查询,以及查看是否用到了索引. 我们都知道创建索引可以提高查询效率,但是具体该怎么创建索引? 哪些字段适合创建索引? 哪 ...

  6. [极客大挑战 2019]HardSQL-1

    1.打开之后万能密码等均被过滤,那就先确定下过滤的内容,采用brup抓包进行爆破,发现对union进行了过滤,因此这里就没法使用联合注入,结果如下: 爆破得字典: ^ & && ...

  7. Nodemon 如何实时监听 TypeScript 项目下的文件并热部署?

    首先你的项目要安装ts-node和nodemon: npm i -D ts-node nodemon 在package.json文件中配置运行脚本: "dev": "no ...

  8. Spring源码环境搭建

    Spring源码在github上,地址是https://github.com/spring-projects/spring-framework/,选择5.3.x版本,直接从github上克隆项目网速很 ...

  9. 在 IconFont 上获取图标资源的操作方法与感悟

    如何在 IconFont 上获取图标资源 阿里巴巴矢量图标库网站(https://www.iconfont.cn/)上提供了非常丰富的图标资源,包括 SVG.AI.PNG.字体图标等格式.使用该网站提 ...

  10. MixCSE:困难样本在句子表示中的使用

    Unsupervised Sentence Representation via Contrastive Learning with Mixing Negatives 论文地址:https://www ...