Flutter Row 实例 —— 新手礼包

打印 上一主题 下一主题

主题 822|帖子 822|积分 2466


各人好,我是 17。
本文在 3.31 日全站综合热榜第一。

新手礼包一共 3 篇文章,每篇都是形貌只管具体,实例讲解,包会!


  • Flutter Row 实例 —— 新手礼包
  • Flutter TextField UI 实例 —— 新手礼包
  • Flutter TextField 交互实例 —— 新手礼包
本篇先容 Row 的用法,用实例讲解 flex 弹性布局原理。本来在 Flutter 弹性布局的基石: Flex 和 Flexible 一文中的内容已经包含 Row 了,但因为 Row 太常用了,以是单写一篇。
Row 的尺寸

默认情况下, Row 在宽度上只管大,在高度上只要能包住全部的 children 即可。
第一个示例给出全部代码,后面的只给出 Row 的代码。在 Row 的外面加一个 Container ,是为了给 Row 加一个 border,方便查看。减去 margin,padding,border 后 ,Row 的宽度为 300。
  1. MaterialApp(
  2.   home: Scaffold(
  3.      body: Container(
  4.          width: 342,
  5.          alignment: Alignment.center,
  6.          child: Container(
  7.              padding: const EdgeInsets.all(10),
  8.              margin: const EdgeInsets.all(10),
  9.              decoration:
  10.                  BoxDecoration(border: Border.all(color: Colors.blue)),
  11.              child: Row(
  12.                children: [
  13.                  Container(
  14.                    width: 100,
  15.                    height: 50,
  16.                    color: const Color.fromARGB(255, 82, 143, 222),
  17.                  ),
  18.                ],
  19.              )))));
复制代码
在本例中,Row 的宽度达到答应的最大值 300。高度为 50,正好可以包含蓝色块的高度。MainAxisSize.min 可以让 Row 的宽度也正好能包含 children。
  1. Row(
  2.     mainAxisSize: MainAxisSize.min,
  3.     children: [
  4.       Container(
  5.         width: 100,
  6.         height: 50,
  7.         color: const Color.fromARGB(255, 82, 143, 222),
  8.       ),
  9.     ],
  10.   );
复制代码
mainAxisSize:MainAxisSize.min 让 Row 的宽度紧缩,直到正好包含 全部 children 为止。本例中,正好包含蓝色块,最终宽度为 100。
   mainAxisSize 的默认值是 mainAxisSize.max
  非弹性布局

非弹性布局是说在 children 中没有 Expanded,Flexible 这种有 flex 参数的 child。
  1. Row(
  2.     children: [
  3.       Container(
  4.         width: 100,
  5.         height: 50,
  6.         color: const Color.fromARGB(255, 82, 143, 222),
  7.       ),
  8.       const Text(
  9.         "IAM17",
  10.         style:
  11.             TextStyle(color: Color(0xFFC45F84), fontSize: 24),
  12.       )
  13.     ],
  14. );
复制代码
非弹性布局中,Row 的 children 在宽度方面没有限定, child 按本身期望的尺寸在水平方向依次分列。如果 children 的总宽度没有超过 Row 的宽度,没有什么问题。如果超过了 Row 的宽度,在开发情况下,会给出警告。
比如修改 Container 的 width:100 为 width:400,这个时候 Row 已经没有多余的空间给 Text 了,甚是连 Container 也放不下。
在生产情况中,多出来的部分会被直接截断。
弹性布局

弹性布局是说在 children 中有 Expanded,Flexible 这种有 flex 参数的 child。
简单来说,Row 分配空间的过程是这样的。

  • 先分配非弹性 child,比如 Container,Text,这些没有 flex 属性的 Widget。
  • 把剩余的空间按 flex 值的大小,分给全部的弹性块。
  • 如果是用 Expanded 包起来的 child, child 的大小就是 第 2 步分配空间的大小;如果是用 Flexible 包起来,child 的大小可以从 0 到 第 2 步分配空间的大小 之间自行决定。
这里说的 Flexible 的 fit 参数的值为 FlexFit.loose。Expanded 就是 fit 参数为 FlexFit.tight 的 Flexible。
让 child 占用全部分配到的空间,用 Expanded 包起来

  1. Row(
  2.    children: [
  3.      Expanded(
  4.          child: Container(
  5.        width: 100,
  6.        height: 50,
  7.        color: const Color.fromARGB(255, 82, 143, 222),
  8.      )),
  9.      const Text(
  10.        "IAM17",
  11.        style:
  12.            TextStyle(color: Color(0xFFC45F84), fontSize: 24),
  13.      )
  14.    ],
  15. )
复制代码
Row 的宽度为 300,先给非弹性块 Text 分配固定大小空间,剩余的全分给的 Expanded。child 蓝色块占用全部 Expanded 分配到的空间。
我们注意到 Container 的 width 是 100,实际上,就算是这里写 0,或写 1000 都没有关系,用 Expanded 包起来的 child 的 width 属性会被忽略。
Expanded 包起来的 child 的 width 是不能自定义的,如果 child 要自定义 width 又要保持弹性布局怎么办?用 Flexible!
让 child 可以在分配到的空间内自行决定大小,用 Flexible 包起来。

在下面的例子中 Row 总的可用宽度为 300,两个 Container 各占 100,还余 100 空缺在两个 Container 之间
  1. Row(
  2.      mainAxisAlignment: MainAxisAlignment.spaceBetween,
  3.      children: [
  4.        Container(
  5.          width: 100,
  6.          height: 50,
  7.          color: Colors.blue,
  8.        ),
  9.        Container(
  10.          width: 100,
  11.          height: 50,
  12.          color: Colors.red,
  13.        ),
  14.      ],
  15.    )
复制代码
如今我们把第一个 container 用 Flexible 包起来。
  1. Row(
  2.      mainAxisAlignment: MainAxisAlignment.spaceBetween,
  3.      children: [
  4.        Flexible(
  5.            child: Container(
  6.          width: 100,
  7.          height: 50,
  8.          color: Colors.blue,
  9.        )),
  10.        Container(
  11.          width: 100,
  12.          height: 50,
  13.          color: Colors.red,
  14.        ),
  15.      ],
  16.    )
复制代码
重新执行查看效果,发现没什么变化。这是因为 总宽度为 300,分给非弹性赤色块 100后另有 200, 唯一的弹性块拿到 200。蓝色块的 100 在分配到的空间范围内,以是没有什么反应。
把第一个 Container 的 width 加大到 150 查看效果,发现第一个 Container 的宽度变为 150 了。同理 150 也在 分配到的 200 之内。
继续加大 width 的宽度到 200,发现他们已经紧贴到一起了。继续加大就没有任何效果了,但也不会报错。
继续加大到 200 以上就超太过配到的 200了,以是宽度不再增加。不会报错是因为蓝色块被 Flexible 限定在 200 以内,加上赤色块的总宽度在 300 以内,没有超出,当然不会报错。
如果左面 Container 的 宽度不是我们指定的,而是 Container 的 child 撑起来的,那么就可以实现宽度自适应的布局效果,不消担心会超出边界。
Flexible 的 flex 与 fit 参数

Flexible 的 flex 决定了可以分配多少剩余空间。fit 参数决定 child 可否自行决定大小。
看下面的的例子,赤色块为固定宽度,绿蓝为弹性宽度。在fit: FlexFit.tight 的情况下,绿色块和赤色块的 width 无效。因为 Flexible 的 flex 已经决定了宽度值,child 只能用这个值不能修改。
  1. Row(children: [
  2.      Container(
  3.              width: 20, height: 50, color: Colors.red),
  4.      Flexible(
  5.          fit: FlexFit.tight,
  6.          flex: 1,
  7.          child: Container(
  8.              width: 100, height: 50, color: Colors.green)),
  9.      Flexible(
  10.          fit: FlexFit.tight,
  11.          flex: 2,
  12.          child: Container(
  13.              width: 100, height: 50, color: Colors.blue))
  14.    ]
复制代码
本例中 Row 的宽度为 320,起首分配 20 给固定宽度的赤色块,剩余的 300 由两个弹性块瓜分。根据 flex 值,绿色块得到 100,蓝色块得到 200。Flex 值越大,得到的空间越大。
   fit: FlexFit.tight 的 Flexible ,一般是用 Expanded。
  在fit: FlexFit.loose 的情况下,绿色块和赤色块的 width 是有作用的,可以在 0 和最大值之间自定义本身的宽度。
我们把第二个 Flexible 的 fit: FlexFit.tight 修改为 fit: FlexFit.loose,蓝色块的 width 起作用了,表现为 100 宽。
我们调整一下摆放方式,蓝色块省出来的 100 空间被填充到各个块之间了。
  1. child: Row(
  2.      mainAxisAlignment: MainAxisAlignment.spaceBetween,
  3.      ...
复制代码
在 children 之间加空缺。

在 children 之间增加固定空缺用 SizedBox

我们发现 Container 和 文本紧挨在一起了,想要他们之间有一个距离。可以用 Padding 把 Container 或 Text 包起来,但是这样写起来比较麻烦,而且多了一个层级,也不美观,不如用 SizedBox。
  1. Row(
  2.    children: [
  3.       Container(
  4.         width: 100,
  5.         height: 50,
  6.         color: const Color.fromARGB(255, 82, 143, 222),
  7.       ),
  8.       const SizedBox(width: 20,),
  9.       const Text(
  10.         "IAM17",
  11.         style:
  12.             TextStyle(color: Color(0xFFC45F84), fontSize: 24),
  13.       )
  14.     ],
  15.   )
复制代码
在 children 之间增加弹性空缺用 Spacer

  1. Row(
  2.      children: [
  3.         Container(
  4.          width: 100,
  5.          height: 50,
  6.          color: const Color.fromARGB(255, 82, 143, 222),
  7.        ),
  8.        const Spacer(),
  9.        const Text(
  10.          "IAM17",
  11.          style:
  12.              TextStyle(color: Color(0xFFC45F84), fontSize: 24),
  13.        )
  14.      ],
  15.    )
复制代码
文本 “IAM17” 与 蓝色块 之间的空缺是 文本 “IAM17” 与 文本 “Flutter” 之间空缺宽度的两倍。Row 的宽度如果增加或缩小,空缺的宽度也会增加会缩小,但会保持两倍的关系。
平均分配空缺

平均分配空缺用 mainAxisAlignment 参数,具体用法详见 Flutter Wrap 图例。虽然讲的是 Wrap Widget,但是 alignment 与 Row 的 mainAxisAlignment 用法是一样的。比如两端对齐:
  1. Row(
  2.    mainAxisAlignment: MainAxisAlignment.spaceBetween,
  3.    ...
复制代码
Row 嵌套

Row 嵌套的时候需要注意下,因为一不小心会报错。
  1. Row(
  2.      children: [
  3.        Row(children: [
  4.          Expanded(
  5.              child: Container(
  6.            width: 100,
  7.            height: 50,
  8.            color: Color.fromARGB(255, 210, 74, 137),
  9.          ))
  10.        ]),
  11.      ],
  12.    )
复制代码
Expanded 是要占据全部的可用空间,内层的 Row 在宽度可以是无穷,Expanded 无法占据无穷空间,以是报错。解决的办法很简单,让 内层的 Row 的宽度有限就可以了。
  1. Row(
  2.    children: [
  3.      Expanded(
  4.          child: Row(children: [
  5.        Expanded(
  6.            child: Container(
  7.          width: 100,
  8.          height: 50,
  9.          color: Color.fromARGB(255, 210, 74, 137),
  10.        ))
  11.      ])),
  12.    ],
  13. )
复制代码
或者给 Row 加一个宽度束缚。比如用 SizedBox 包起来。
  1. Row(
  2.    children: [
  3.      SizedBox(
  4.          width: 150,
  5.          child: Row(children: [
  6.            Expanded(
  7.                child: Container(
  8.              width: 100,
  9.              height: 50,
  10.              color: Color.fromARGB(255, 210, 74, 137),
  11.            ))
  12.          ])),
  13.    ],
  14. );
复制代码
用 Flexible 包起来也是可以的,Flexible 与 Expanded 的区别在于 Flexible 给 child loose 束缚,Expanded 给 child tight 束缚。通俗一点的说法是 Flexible 的 child 的宽度可以从 0 到 最大值之间本身决定。Expanded 的 child 的宽度只能是固定值,不能修改。
Row 嵌套的时候报错本质上是因为宽度无穷,遇到别的宽度无穷的场景也会出现这样的问题,比如 ListView 横向滚动的时候,把 Row 嵌套在 ListView 中也会有类似的问题。
  1. ListView(
  2.      scrollDirection: Axis.horizontal,
  3.      children: [
  4.        Row(children: [
  5.          Expanded(
  6.              child: Container(
  7.            width: 100,
  8.            height: 50,
  9.            color: Color.fromARGB(255, 210, 74, 137),
  10.          ))
  11.        ]),
  12.      ],
  13.    )
复制代码
解决办法相同,也是把 Row 用 Flexible 或 Expanded 包起来,或加一个宽度束缚。
  1. ListView(
  2.     scrollDirection: Axis.horizontal,
  3.     children: [
  4.       Expanded(
  5.           child: Row(children: [
  6.         Expanded(
  7.             child: Container(
  8.           width: 100,
  9.           height: 50,
  10.           color: Color.fromARGB(255, 210, 74, 137),
  11.         ))
  12.       ])),
  13.     ],
  14.   );
复制代码
到这里 Flutter Row 的常用的用法就都先容完了。谢谢观看!

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

饭宝

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表