Flutter 66: 图解基本约束 Box (一)

      小菜在学习过程中,为了调整或适配 Widget 大小时,会设置 Widget 或嵌套使用一些约束 Widget;小菜针对性学习一下这一系列的约束 Box

SizedBox

源码分析

class SizedBox extends SingleChildRenderObjectWidget {
  // 创建固定大小的约束Box
  const SizedBox({ Key key, this.width, this.height, Widget child })
    : super(key: key, child: child);

  // 创建父类允许最大尺寸的约束Box
  const SizedBox.expand({ Key key, Widget child })
    : width = double.infinity,
      height = double.infinity,
      super(key: key, child: child);

  // 创建父类允许最小尺寸的约束Box
  const SizedBox.shrink({ Key key, Widget child })
    : width = 0.0,
      height = 0.0,
      super(key: key, child: child);

  // 创建指定大小的约束Box
  SizedBox.fromSize({ Key key, Widget child, Size size })
    : width = size?.width,
      height = size?.height,
      super(key: key, child: child);
}

      分析源码可知,SizeBox 继承自 SingleChildRenderObjectWidget 仅提供子 Child 的存储并不提供更新逻辑;且 SizedBox 提供了多种使用方法,小菜逐一尝试;

案例尝试

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

      SizedBox 可自定义 widthheight,当限制宽高时,子 Widget 无论宽高如何,均默认填充;通过设置 double.infinity 填充父类 Widget 宽高,注意此时父类要有限制,不可是无限宽高;当 widthheight 未设置时,根据子 Widget 大小展示;

return SizedBox(width: 100.0, height: 100.0, child: Container(color: Colors.teal.withOpacity(0.4)));
return SizedBox(width: 100.0, height: 100.0, child: Container(color: Colors.red.withOpacity(0.4), width: 200.0, height: 200.0));
return SizedBox(width: 100.0, height: 100.0, child: Container(color: Colors.pink.withOpacity(0.4), width: 50.0, height: 50.0));
return SizedBox(width: double.infinity, height: 100.0, child: Container(color: Colors.blueAccent.withOpacity(0.4)));
2. SizedBox.expand({ Key key, Widget child })

      .expand 是便捷方法,默认 widthheight 均为 double.infinity,填充整个父类 Widget

return SizedBox.expand(child: Container(color: Colors.blueAccent.withOpacity(0.4)));
3. SizedBox.shrink({ Key key, Widget child })

      .shrink 同样是便捷方法,但 widthheight 均为 0.0,无论子 Widget 设置多少均不展示;小菜暂时未想出此类方法的应用场景;

return SizedBox.shrink(child: Container(color: Colors.pink.withOpacity(0.4)));
4. SizedBox.fromSize({ Key key, Widget child, Size size })

      .fromSize 便捷方式与基本的构建方式基本相同,只是 widthheightSize 封装,小菜用此方法实现与基本方式相同的效果;

return SizedBox.fromSize(size: Size(100.0, 100.0), child: Container(color: Colors.teal.withOpacity(0.4)));
return SizedBox.fromSize(size: Size(100.0, 100.0), child: Container(color: Colors.red.withOpacity(0.4), width: 200.0, height: 200.0));
return SizedBox.fromSize(size: Size(100.0, 100.0), child: Container(color: Colors.pink.withOpacity(0.4), width: 50.0, height: 50.0));
return SizedBox.fromSize(size: Size(double.infinity, 100.0), child: Container(color: Colors.blueAccent.withOpacity(0.4)));

ConstrainedBox

源码分析

class ConstrainedBox extends SingleChildRenderObjectWidget {
  ConstrainedBox({
    Key key,
    @required this.constraints,
    Widget child,
  })
}

class BoxConstraints extends Constraints {
  // 用指定的约束大小创建框架大小
  const BoxConstraints({
    this.minWidth = 0.0,
    this.maxWidth = double.infinity,
    this.minHeight = 0.0,
    this.maxHeight = double.infinity,
  });

  // 仅用指定大小创建框架大小
  BoxConstraints.tight(Size size)
    : minWidth = size.width,
      maxWidth = size.width,
      minHeight = size.height,
      maxHeight = size.height;

  // 用指定的约束大小创建框架大小
  const BoxConstraints.tightFor({
    double width,
    double height,
  })

  // 创建需要给定宽度或高度的框约束,除非它们是无限的
  const BoxConstraints.tightForFinite({
    double width = double.infinity,
    double height = double.infinity,
  })

  // 创建禁止大小大于给定大小的框约束
  BoxConstraints.loose(Size size)
    : minWidth = 0.0,
      maxWidth = size.width,
      minHeight = 0.0,
      maxHeight = size.height;

  // 创建扩展为填充另一个框约束的框约束
  const BoxConstraints.expand({
    double width,
    double height,
  })
}

      分析源码可知,ConstrainedBox 同样是继承自 SingleChildRenderObjectWidget;约束方式主要是对 constraints 的操作;相对于 SizedBox 约束更为灵活;

案例尝试

1. BoxConstraints()

      BoxConstraints 的构造方法可以设置最大最小宽度和高度四个属性,在实际场景中可以灵活运用;其约束的大小按照 minWidth <= child.width <= maxWidth && minHeight <= child.Height <= maxHeight,当我们不设置宽高尺寸时,minWidth = 0.0 && minHeight = 0.0 && maxWidth = double.infinity && maxHeight = double.infinity;

return ConstrainedBox(constraints: BoxConstraints(), child: Container(color: Colors.pink.withOpacity(0.4), child: _textWid('ConstrainedBox')));
return ConstrainedBox(constraints: BoxConstraints(), child: Container(color: Colors.blueAccent.withOpacity(0.4), child: _textWid('ConstrainedBox: A widget that imposes additional constraints on its child.')));
return ConstrainedBox(constraints: BoxConstraints(minWidth: 100.0, minHeight: 100.0), child: Container(color: Colors.orange.withOpacity(0.4), child: _textWid('ConstrainedBox')));
return ConstrainedBox(constraints: BoxConstraints(maxHeight: 100.0, maxWidth: 100.0),  child: Container(color: Colors.teal.withOpacity(0.4), child: _textWid('ConstrainedBox: A widget that imposes additional constraints on its child.')));
2. BoxConstraints.tight(Size size)

      .tight 构造方法中需要传一个固定尺寸的 Size 其中 minWidth == maxWidth == size.width && maxWidth == maxHeight == size.height;无论子 Widget 设置多大宽高均按照 Size 宽高约束;

return ConstrainedBox(constraints: BoxConstraints.tight(Size(110.0, 120.0)),
        child: Container(color: Colors.purple.withOpacity(0.4), child: _textWid('ConstrainedBox: A widget that imposes additional constraints on its child.')));
3. BoxConstraints.tightFor()

      小菜理解 .tightFor 方式是 .tight 方式的细化,可以自定义 widthheight;若宽高未设置,则最大宽高为无限,最小宽高为 0.0;若设置宽高则以设置尺寸进行约束;

return ConstrainedBox(constraints: BoxConstraints.tightFor(height: 110.0),
        child: Container(color: Colors.teal.withOpacity(0.4), child: _textWid('ConstrainedBox: A widget that imposes additional constraints on its child.')));
return ConstrainedBox(constraints: BoxConstraints.tightFor(width: 110.0, height: 120.0),
        child: Container(color: Colors.purple.withOpacity(0.4), child: _textWid('ConstrainedBox: A widget that imposes additional constraints on its child.')));
4. BoxConstraints.tightForFinite()

      .tightForFinite.tightFor 类似,默认最大宽高为无限,最小宽高为 0.0,其判断的是设置宽高是否为无限,不是 double.infinityminWidth == maxWidth == width && maxWidth == maxHeight == height 进行约束;

return ConstrainedBox(constraints: BoxConstraints.tightForFinite(),
        child: Container(color: Colors.teal.withOpacity(0.4), child: _textWid('ConstrainedBox: A widget that imposes additional constraints on its child.')));
return ConstrainedBox(constraints: BoxConstraints.tightForFinite(width: 110.0, height: 120.0),
        child: Container(color: Colors.purple.withOpacity(0.4), child: _textWid('ConstrainedBox: A widget that imposes additional constraints on its child.')));
5. BoxConstraints.loose()

      .loose 方式限制给定 Size 大小,minWidth / minHeight 均为 0.0,最大宽高为 Size 大小;其中整体约束由 Size 限制,实际展示与子 Widget 大小相关;

return ConstrainedBox(constraints: BoxConstraints.loose(Size(110.0, 150.0)),
        child: Container(color: Colors.purple.withOpacity(0.4), child: _textWid('ConstrainedBox: A widget that imposes additional constraints on its child.')));
return ConstrainedBox(constraints: BoxConstraints.loose(Size(110.0, 150.0)),
        child: Container(width: 200.0, height: 200.0, color: Colors.grey.withOpacity(0.6),
            child: _textWid('ConstrainedBox: A widget that imposes additional constraints on its child.')));
return ConstrainedBox(constraints: BoxConstraints.loose(Size(110.0, 120.0)),
        child: Container(width: 100.0, height: 100.0, color: Colors.green.withOpacity(0.6),
            child: _textWid('ConstrainedBox: A widget that imposes additional constraints on its child.')));
6. BoxConstraints.expand()

      大部分 .expand 方式是填充方式,默认填满父 Widget,若不设置宽高,默认 minWidth == maxWidth == double.infinity && minHeight == maxHeight == double.infinity,使用时注意父类约束;

return ConstrainedBox(constraints: BoxConstraints.expand(),
    child: Container(color: Colors.teal.withOpacity(0.4), child: _textWid('ConstrainedBox: A widget that imposes additional constraints on its child.')));
return ConstrainedBox(constraints: BoxConstraints.expand(width: 110.0, height: 150.0),
    child: Container(color: Colors.purple.withOpacity(0.4), child: _textWid('ConstrainedBox: A widget that imposes additional constraints on its child.')));

      Flutter 提供了多种约束 Box,所谓条条大路通罗马,同一种效果可以有多种实现方式,但小菜认为还是应该多多了解,尽量尝试最优方案;小菜对 Box 系列的研究还很浅显,有错误的地方请多多指导!

来源: 阿策小和尚

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,372评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,368评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,415评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,157评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,171评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,125评论 1 297
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,028评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,887评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,310评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,533评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,690评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,411评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,004评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,659评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,812评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,693评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,577评论 2 353

推荐阅读更多精彩内容