前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Flutter布局指南之Box套盒子

Flutter布局指南之Box套盒子

作者头像
用户1907613
发布2022-03-31 21:51:36
1.1K0
发布2022-03-31 21:51:36
举报
文章被收录于专栏:Android群英传Android群英传

对于写过Flutter的开发者来说,我敢肯定,大部分的开发者都不能准确预测这次Hot Reload之后,布局是否是自己想要的结果。Flutter的布局与Native的布局方式非常不同,所以,了解Flutter这茫茫多的布局组件,是我们准确布局的基础。

在Flutter中,有一堆Box布局组件,它们可以用来更加精确的调整布局,下面我们就来看看这些Box都有哪些作用。

ConstrainedBox

ConstrainedBox用于限制Child Widget的尺寸约束,例如:

  • 让Text最宽100,从而实现多行
  • 固定Widget最大最小尺寸
代码语言:javascript
复制
body: Center(
  child: Column(
    mainAxisAlignment: MainAxisAlignment.center,
    children: [
      ConstrainedBox(
        constraints: const BoxConstraints(
          maxWidth: 100,
        ),
        child: const Text(
          'xuyisheng',
          textAlign: TextAlign.center,
          style: TextStyle(
            fontSize: 50,
          ),
        ),
      ),
      ConstrainedBox(
        constraints: const BoxConstraints(
          minHeight: 100,
        ),
        child: ElevatedButton(
          child: const Text('Flutter'),
          onPressed: () {},
        ),
      ),
    ],
  ),
)

效果如图所示。

UnconstrainedBox

UnconstrainedBox的作用正好和ConstrainedBox相反。它可以破除组件本身的约束规则,从而更方便的进行布局。

例如下面这个例子:

代码语言:javascript
复制
Center(
  child: Container(
    color: Colors.blue,
    width: 300,
    height: 300,
    child: Container(
      width: 100,
      height: 100,
      color: Colors.red,
    ),
  ),
)

由于Container的布局规则,内部的Container被设置为父Widget尺寸,从而忽略了子Widget的尺寸设置,所以,这里使用UnconstrainedBox来解除这种约束:

代码语言:javascript
复制
Center(
  child: Container(
    color: Colors.blue,
    width: 300,
    height: 300,
    child: UnconstrainedBox(
      child: Container(
        width: 100,
        height: 100,
        color: Colors.red,
      ),
    ),
  ),
)

从而可以让内部的Container按照自身尺寸进行布局。

更加灵活一点,我们还可以选择保留某一方向上的约束:constrainedAxis: Axis.horizontal。

SizedBox

SizedBox有下面几个使用场景:

  • 当你需要一个确切尺寸的Widget时,通过SizedBox来进行约束
  • 在父容器中撑满剩余空间
  • 在没有child的情况下,对空间做分割

场景1:

代码语言:javascript
复制
SizedBox(
  width: 200,
  height: 200,
  child: Text(
    'xuyisheng',
    textAlign: TextAlign.center,
    style: TextStyle(
      fontSize: 50,
    ),
  ),
)

场景2:某方向上的double.infinity,会在父级允许的尺寸下尽可能多的拓展。

代码语言:javascript
复制
Center(
  child: Container(
    color: Colors.red,
    width: 200,
    height: 200,
    child: Center(
      child: Container(
        color: Colors.blue,
        child: const SizedBox(
          width: double.infinity,
          height: 100,
          child: Text(
            'xuyisheng',
            textAlign: TextAlign.center,
            style: TextStyle(
              fontSize: 50,
            ),
          ),
        ),
      ),
    ),
  ),
)

展示效果如图所示。

如果width和height方向上都是撑满父Widget的剩余空间,那么可以使用SizedBox.expand来简写。

还有一个便捷方法——SizedBox.shrink,它的作用是让尺寸在父容器的约束下尽可能的小,如果父容器不设置minWidth或者minHeight,那么它的尺寸就是0,这个属性通常和BoxConstraints一起配合使用。

FractionallySizedBox

这是Flutter给你提供的一个百分百布局工具。通常用于在父容器中,按照百分比来进行布局。

代码语言:javascript
复制
Center(
  child: Container(
    color: Colors.red,
    width: 200,
    height: 200,
    child: const FractionallySizedBox(
      widthFactor: 0.5,
      heightFactor: 0.5,
      child: Text(
        'xuyisheng',
        textAlign: TextAlign.center,
        style: TextStyle(
          fontSize: 50,
        ),
      ),
    ),
  ),
)

展示效果如图所示。

和SizedBox一样,它也可以用于作为Widget直接的间隔,只不过它使用的是百分比作为单位,总量是父容器的尺寸。

如果使用Flexible组件包裹FractionallySizedBox,那么就可以适用于Row和Column。

要注意的是,widthFactor和heightFactor是可以大于1的,也就是说,子Widget可以超出父容器展示。

LimitedBox

当Widget没有父级来限制它们的尺寸时,如何在Widget上设置它的默认大小呢?这就需要使用到LimitedBox了。

LimitedBox只在父容器没有提供尺寸约束时,对子Widget的尺寸进行默认约束,在在Listview和Column、Row中是非常有用的。

❝如果外部容器对Child设置了尺寸约束,那么LimitedBox将不会生效 ❞

例如下面这个场景:

代码语言:javascript
复制
ListView(
  children: [
    for (var i = 0; i < 100; i++)
      Container(
        margin: const EdgeInsets.all(8),
        color: Colors.green,
      ),
  ],
)

由于Listview中无尺寸约束,所以Container是不会展示出来的,这时候就需要使用LimitedBox。

代码语言:javascript
复制
ListView(
  children: [
    for (var i = 0; i < 100; i++)
      LimitedBox(
        maxHeight: 100,
        child: Container(
          margin: const EdgeInsets.all(8),
          color: Colors.green,
        ),
      ),
  ],
)

一句话总结LimitedBox的作用:在不受限制的环境中,为其子元素提供默认尺寸。

FittedBox

在Flutter中,Widget之间可以任意堆叠、嵌套,所以,当子Widget的尺寸与父Widget尺寸不一致时,就会产生一些奇怪的样式,FittedBox就是用来处理这种场景的。

代码语言:javascript
复制
Center(
  child: Container(
    width: 200,
    height: 200,
    color: Colors.red,
    child: Text(
      'xuyishengxuyisheng',
      style: TextStyle(
        fontSize: 50,
      ),
    ),
  ),
)

效果如图所示。

Text会因为父容器尺寸的限制而自动换行,下面我们给它加上FittedBox。

代码语言:javascript
复制
Center(
  child: Container(
    width: 200,
    height: 200,
    color: Colors.red,
    child: FittedBox(
      child: Text(
        'xuyishengxuyisheng',
        style: TextStyle(
          fontSize: 50,
        ),
      ),
    ),
  ),
)

效果如图所示。

可以发现,FittedBox默认的fit是contain,所以内容被完整的一行显示了,与FontSize无关,这个就可以很方便的自适应修改文字大小。

当然,你还可以设置别的fit方式,详细的可以参考Flutter Dojo中的例子。fit属性是非常有用的一个属性,例如当我们设置FittedBox后,文字会在设备中自动显示为一行,但是在横竖屏切换时,Text会自动修改字体大小,来适配contain的效果,如果你想让它保存当前的文字Size,那么可以设置Fit为scaleDown,这样的话,它就会以最小尺寸来进行适配,当空间足够的时候,就不会自动放大字体大小了。

FittedBox中还可以设置alignment,从而控制剩余空间中子Widget的对齐方式。

简而言之,FittedBox就是一个让Child可以适配Parent的组件。

Flexible

准确来说,Flexible不算是Box类布局容器,但它和Box布局方式息息相关,所以这里一起说了。

Flexible通常在Column或者Row中使用,借助Flexible,可以让Column和Row中的元素根据Flex比例进行布局。

代码语言:javascript
复制
Column(
  children: [
    Flexible(
      flex: 3,
      child: Container(
        color: Colors.cyan,
      ),
    ),
    Flexible(
      flex: 2,
      child: Container(
        color: Colors.green,
      ),
    ),
    Flexible(
      flex: 1,
      child: Container(
        color: Colors.purple,
      ),
    ),
  ],
)

同时,当子Widget有尺寸约束时,可以使用fit属性来控制Flex选择怎样的约束,如果是FlexFit.tight,那么Flexible将严格按照Flex布局,而忽略子Widget的尺寸约束,如果是FlexFit.loose,则会将尺寸设置为子Widget的尺寸。

OverflowBox

对于Flutter的子父Widget来说,子Widget一般都是限制于父Widget的尺寸约束之下,但如果一定要让子Widget超过父Widget的渲染区域,那么就可以通过OverflowBox来实现。

代码语言:javascript
复制
Container(
  color: Colors.blue,
  width: 200,
  height: 200,
  padding: const EdgeInsets.all(12.0),
  child: OverflowBox(
    alignment: Alignment.topLeft,
    maxWidth: 300.0,
    maxHeight: 500.0,
    child: Container(
      color: Colors.red,
      width: 400.0,
      height: 400.0,
    ),
  ),
)

效果如图所示。

本文原创公众号:群英传,授权转载请联系微信,授权后,请在原创发表24小时后转载。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2022-03-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 群英传 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • ConstrainedBox
  • UnconstrainedBox
  • SizedBox
  • FractionallySizedBox
  • LimitedBox
  • FittedBox
  • Flexible
  • OverflowBox
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档