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

flutter系列之:深入理解布局的基础constraints

文章目录

  • 简介
  • Tight和loose constraints
  • 理解constraints的原则
  • 总结

简介

我们在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/

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

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

相关文章:

  • 【C语言进阶】动态内存管理及柔性数组
  • 网课查题接口系统
  • C语言基础知识入门
  • 闲暇之际敲敲代码,记录Leetcode刷题Day-01
  • 2021年下半年信息安全工程师上午真题及答案解析
  • Dinky,让 Flink SQL 纵享丝滑
  • Docker | docker容器导出以及常见问题的处理
  • 【node进阶】深度解析之Express框架入门
  • 【重温Linux】一、Ubuntu系统一些常识性的东西(这节持续更新)
  • mysql group_concat 与 union 联合查询漏洞,数据列最大长度为341
  • ISO27001认证需要准备什么资料?
  • 腾讯研究成果登 Nature 子刊:scBERT 攻克单细胞测序数据分析痛点
  • Vue2和Vue3的区别——实例创建、响应式数据代理、v-for和v-if优先级、生命周期
  • 跑步装备推荐:2022年跑步装备选购清单
  • 【云原生之Docker实战】使用Docker部署Pichome个人相册系统
  • 【跃迁之路】【733天】程序员高效学习方法论探索系列(实验阶段490-2019.2.23)...
  • C++类中的特殊成员函数
  • CSS实用技巧
  • Docker: 容器互访的三种方式
  • JavaWeb(学习笔记二)
  • Linux编程学习笔记 | Linux多线程学习[2] - 线程的同步
  • Nacos系列:Nacos的Java SDK使用
  • React的组件模式
  • Service Worker
  • Solarized Scheme
  • Vim Clutch | 面向脚踏板编程……
  • 事件委托的小应用
  • 数据可视化之 Sankey 桑基图的实现
  • 用简单代码看卷积组块发展
  • 原生 js 实现移动端 Touch 滑动反弹
  • Python 之网络式编程
  • Redis4.x新特性 -- 萌萌的MEMORY DOCTOR
  • ​​​​​​​ubuntu16.04 fastreid训练过程
  • #NOIP 2014# day.2 T2 寻找道路
  • #我与Java虚拟机的故事#连载09:面试大厂逃不过的JVM
  • (04)Hive的相关概念——order by 、sort by、distribute by 、cluster by
  • (1)(1.19) TeraRanger One/EVO测距仪
  • (2)STL算法之元素计数
  • (DenseNet)Densely Connected Convolutional Networks--Gao Huang
  • (iPhone/iPad开发)在UIWebView中自定义菜单栏
  • (附源码)springboot车辆管理系统 毕业设计 031034
  • (附源码)计算机毕业设计ssm本地美食推荐平台
  • (附源码)小程序 交通违法举报系统 毕业设计 242045
  • (论文阅读31/100)Stacked hourglass networks for human pose estimation
  • (三)docker:Dockerfile构建容器运行jar包
  • (四)JPA - JQPL 实现增删改查
  • (原)Matlab的svmtrain和svmclassify
  • .Net - 类的介绍
  • .NET 4.0中使用内存映射文件实现进程通讯
  • .net core 微服务_.NET Core 3.0中用 Code-First 方式创建 gRPC 服务与客户端
  • .NET MVC 验证码
  • .net php 通信,flash与asp/php/asp.net通信的方法
  • .NET 设计模式—简单工厂(Simple Factory Pattern)
  • .net 微服务 服务保护 自动重试 Polly
  • .NET/C# 使窗口永不激活(No Activate 永不获得焦点)