了解Flutter Widget前,你需要先理解这些前置知识

3,196 阅读4分钟

初学flutter基础widget时,如Container Widget,查阅官方文档时,经常会碰到

to size itself to the child, to honor the width, height, and constraints, to expand to fit the parent, to be as small as possible.

我们有必要了解:

  • 什么是Constraints(约束)?
  • Flutter中有几种Constraints子类?
  • Constraints与Widget Size 的关联?
  • BoxConstraints的类型?
  • BoxConstraints的作用?

什么是Constraints(约束)?

An abstract set of layout constraints.

Concrete layout models (such as box) will create concrete subclasses to communicate layout constraints between parents and children.

Constraints是抽象布局约束类,


具体的布局模型需要创建对应的Constraints子类,用来传递父Widget与子Widget之间的布局约束;

Flutter中有几种Constraints子类?

通过查看flutter代码,目前Flutter中有两个Constraints子类,( 以后估计会有更多子类)BoxConstraints和SliverConstraints,根据Constraints的说明,BoxConstraints是专为Box布局模型创建的,SilverConstraints是专为Silver布局模型创建的, 我们只需知道,前者用于显示在2D(笛卡尔坐标系中的)对象,后者用于显示对滚动做出反应的对象,具体这两种布局模型的区别,后续文章再述;我们先看下BoxConstraints:



BoxConstraints有maxWidth,minWidth,maxHeight,minHeight四个成员变量,且BoxConstraints需要满足:

double.infinity在此处表示无穷大;

Constraints与Widget Size 的关联?

Widget结点的大小(size:由指定的width和height组成)会遵循父结点传递给它的约束(Constraints),但是要求其满足以下条件:

BoxConstraints的类型?

  • tight constraints(紧密约束):
    指的是这些约束严格地限定了渲染对象确认大小(Size)时的可选余地(当constraints的minWidth等于maxWidth时,这种情况下,我们称这个约束有紧密宽度),例如MaterialApp Widget(flutter 提供的应用框架),会被传递紧密约束以直充满整个手机屏幕(根据不同的手机屏幕,会有不同的具体值);
  • loosen constraints(宽松约束):
    与紧密约束相比,宽松约束只会限定maxWidth或者maxHeight的值,minWidth或者minHeight的值为0;
  • bounded constraints(有边界约束):
    constraints中的maxWidth或者maxHeight小于double.infinity
    bool get hasBoundedWidth => maxWidth < double.infinity;

    bool get hasBoundedHeight => maxHeight < double.infinity;
  • unbounded constraints(无边界约束):
    constraints中的maxWidth或者maxHeight的值为double.infinity
  • expending constraints(扩展约束):
    constraints中的maxWidth,maxHeight,minWidth,minHeight都为double.infinity;

Constraints的作用?

在Flutter中,widget只会存储一些基本信息,具体的渲染由RenderBox对象完成,RenderBox由其父级给出约束,并根据这些约束自行调整自身大小;具体来说,Flutter框架中的布局模型是由一个个RenderBox对象排列组成的树形结构,从该树状模型的根结点开始渲染,向子结点传递约束,这些约束会被传递到最终子结点,并从最终子结点返回根结点,返回过程中,子结点会根据接收到的约束调整自身大小,并将此大小(Size)向上传递给父结点:


1,父结点A向每个子结点传递constraints,子结点的最终布局需要遵守这些约束,就像小时候出门玩,父母跟你的约定,你可以随便玩,但是6点前必须回家吃饭;
2,子结点B1,B2可以有自己的约束,同时B1也向它的子结点C传递该限制,直到C没有子结点为止,当你长大成家了,你也让你的孩子6点前必须回家吃饭
3,子结点B1可以根据接收来自父结点A的约束,自身的情况(width,height),子结点C上传过来的Size这三个因素来确定自身大小(Size),收集完这些布局信息之后,子结点B就可以把这些信息向上传给结点A;

对于Box模型(Box Model),由父结点向下传递给子结点的约束称为盒约(BoxConstraints),它决定了允许其子结点可占用的最大、最小宽度和最大最小高度,比如下图是父结点传递给子结点的盒约束,意味着子结点可以任意占用绿色框内大小,即:子结点的宽度介于150和300之间,高度介于100和无穷大(infinity),然后子结点在满足父结点的约束和自身需占用的大小等因素确认最终大小(Size),并通知其父结点;


结语:

本篇梳理了Flutter的一些布局及相关术语,下篇将会进入Flutter Widget Container的详解,Container与本篇中提及的知识点结合比较紧,是充分理解Container的必要基础知识。