专栏首页Flutter笔记Flutter | ConstrainedBox & UnconstrainedBox 组件

Flutter | ConstrainedBox & UnconstrainedBox 组件

0. 前言

在 Flutter 当中,我们如何控制组件的大小?套上一层 Container?SizeBox?还是一些别的技巧?

有没有同学遇到这种情况:在布局中,无论如何都控制不了一个组件的大小,烦的一批?

例如这段代码:

Widget build(BuildContext context) {
  return Scaffold(
    body: ListView.separated(itemBuilder: (context, index){
      return Container(
        height: 200,
        width: 200,
        color: Colors.amber,
      );
    }, itemCount: 10, separatorBuilder: (BuildContext context, int index) {
      return Container(height: 10,);
    },),
  );
}

我创建了一个ListView,每一个 item 是一个 200*200 的琥铂色(黄色)Container,讲道理,这个时候我们的脑海里就应该有这样的一个列表呈现。然而,当你运行的时候:

WTF??我 200*200 的大方块呢?怎么变成长方形了?

难道不应该是这样的吗?

好,带着这个问题,我们就来说今天的两个主角。

注意:这里并不打算深入讨论 Flutter 中约束的机制,只是为了讲解这两个控件

看本篇文章时我们只需要记住:child 尺寸大小是由父级 Widget 给出的约束来调整的。

其他的如果想要了解,可以看这篇处理边界约束 (Box constraints) 的问题[1]

1. ConstrainedBox

首先我们来说一下 ConstrainedBox,从名字上我们也能解读个大概:「约束盒」。

没错,就是约束盒,他是用来干嘛的?看一下官方文档:

A widget that imposes additional constraints on its child. For example, if you wanted child to have a minimum height of 50.0 logical pixels, you could use const BoxConstraints(minHeight: 50.0) as the constraints. 在其 child 上添加约束的 widget。 例如,如果你希望 child 最小高度为 50.0 像素,可以用 BoxConstraints(minHeight: 50.0) 来进行约束。

接下来再看一下他的构造函数:

ConstrainedBox({
  Key key,
  @required this.constraints,
  Widget child,
}) : assert(constraints != null),
assert(constraints.debugAssertIsValid()),
super(key: key, child: child);

可以看到,必要的参数有 constraints: BoxConstraints,这里也简单说一下约束:

约束是由最小宽度、最大宽度、最小高度、最大高度四个方面构成;尺寸大小则由特定的宽度和高度两个方面构成。

那我们再来看一下 BoxConstraints是怎么用的,它有6个构造函数,分别是:

1.BoxConstraints({double minWidth: 0.0, double maxWidth: double.infinity, double minHeight: 0.0, double maxHeight: double.infinity }):使用给定的约束来构建2.BoxConstraints.expand({double width, double height }):创建一个充满另一个约束的约束3.BoxConstraints.expand({double width, double height }):创建一个不能大于给定大小的约束4.BoxConstraints.tight(Size size):创建一个给定大小的约束5.BoxConstraints.tightFor({double width, double height }):同上6.BoxConstraints.tightForFinite({double width: double.infinity, double height: double.infinity }):创建给定大小的约束,除非他们是无限的

Widget build(BuildContext context) {
  return Scaffold(
    body: Center(
      child: Container(
        height: 200,
        width: 200,
        color: Colors.amber,
      ),
    ),
  );
}

这是一个 200200 的Container,接下来定义一个 ConstrainedBox,并且把min宽高设定为 300\300:

Widget build(BuildContext context) {
  return Scaffold(
    body: Center(
      child: ConstrainedBox(
        child: Container(
          height: 200,
          width: 200,
          color: Colors.amber,
        ), constraints: BoxConstraints(minHeight: 300, minWidth: 300),
      ),
    ),
  );
}

可以看到,这个时候 Container 的宽高完全是按照 ConstrainedBox 的约束来设定的。

2. UnconstrainedBox

该组件就厉害了,官方解释为:

A widget that imposes no constraints on its child, allowing it to render at its "natural" size. This allows a child to render at the size it would render if it were alone on an infinite canvas with no constraints. This container will then attempt to adopt the same size, within the limits of its own constraints. If it ends up with a different size, it will align the child based on alignment[2]. If the box cannot expand enough to accommodate the entire child, the child will be clipped. 对 child 不添加任何约束,允许他以 “自然”大小进行渲染。 这样一来,child就可以在没有约束的、无限的画布上进行渲染,然后此容器讲尝试在自身限制的范围内采用相同的大小,如果大小不相同,则根据 alignment 来对齐,如果child过大,则会裁剪 child。

在我们开头举的例子,为什么我设置 200*200 的Container默认是屏幕宽度的?

因为ListView这种类型的组件会根据滑动方向来设置约束。

例如垂直滑动,那么所有 item 的宽度都是默认 double.infinity,所以这个时候无论我们设置多少宽度都是无用的,

相反也一样。

所以,如果我们想自己设定 item 的宽度,就需要用到 UnconstrainedBox,不给child 设置约束。

3. 总结

这两个组件实际开发过程中使用的可能不是很多,但是了解一下肯定是要的,否则遇到类似的问题也很麻烦。

总结来讲,这些都属于 Flutter 约束中的知识点,只要有个了解就好了。

References

[1] 处理边界约束 (Box constraints) 的问题: https://flutter.cn/docs/development/ui/layout/box-constraints [2] alignment: https://api.flutter.dev/flutter/widgets/UnconstrainedBox/alignment.html

本文分享自微信公众号 - Flutter笔记(Flutter_Note),作者:Flutter笔记

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-12-09

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Flutter 手势处理 & Hero 动画

    第一层有原始指针事件,它描述了屏幕上指针(例如,触摸,鼠标和触控笔)的位置和移动。

    Flutter笔记
  • Flutter | 一个超级酷炫的登录页是怎样炼成的

    1.首先我们最清晰明了的需求就是点击「注册」弹出 Dialog2.弹出 Dialog 后延迟一段时间弹出 Dialog 里的内容3.Dialog 内说明文字有两...

    Flutter笔记
  • Flutter | 可能是目前最好用的仿微信聊天长按弹出框 WPopupMenu

    1.onValueChanged:是点击选中了某一个 action 时候的回调,返回值是一个 int,如果没有选中,点击空白处了,则会返回一个 null2.ac...

    Flutter笔记
  • Flutter 学习笔记 16 - Hero 动画

    七适散人
  • 【Flutter 专题】66 图解基本约束 Box (一)

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

    阿策
  • Vue项目错误汇总

    城市中的游牧民族
  • 科学家提出人机交互新方法

    2016年7月12日,美国马萨诸塞大学安姆斯特分校网站发布消息称,该校研究人员创造了一种人机控制转移的新方法。 马萨诸塞大学安姆斯特分校计算机科学研究生Kyle...

    人工智能快报
  • 我用EggJS开发了一个日增量过亿的数据可视化平台

    前些日子,我所在的Team接到了一个“大活儿”,为我们公司某个服务(出于保密的原因,这里不能直说)做数据可视化及数据分析平台。

    用户1687375
  • [biztalk笔记]-1.Hello World!

    开始接触biztalk了,这个东西感觉不象linq,silverlight等具体的技术好学,看了几天文档,也跑通了一些小示例,但是仍然觉得毫无感觉,只大概的知道...

    菩提树下的杨过
  • iOS中解码.txt文件在UIWebView出现中文乱码的问题

    rectinajh

扫码关注云+社区

领取腾讯云代金券