Flutter. FractionallySizedBox

欢迎关注我的公众号OpenFlutter,感恩

一个能将子控件的大小调整为可用总空间的一个分数的控件。

对于宽度和高度,FractionallySizedBox 会对它的子控件施加一个紧凑的约束,这个约束是它从父控件在相应轴上接收到的最大约束的一个倍数(通常小于 1.0)。如果某个轴的因子为 null,那么父控件的约束将直接传递给子控件。

dart 复制代码
  return Scaffold(
    body: Center(
        child: FractionallySizedBox(
          widthFactor: 0.97,
          heightFactor: 0.97,
          child: Container(
            color: Colors.blue,
            width: 100,
            height: 100,
          ),
        )),
  );
}

Center 会占据所有屏幕空间,并对其子控件 FractionallySizedBox 施加宽松的 约束。FractionallySizedBox 在两个轴向上都取其 97% 的大小,并将此大小作为紧凑的 约束施加给蓝色的 Container

Container 本身的大小(100x100)被忽略了。在 FractionallySizedBox 内部指定大小通常没有意义。在上面的例子中,我们应该使用 ColoredBox 而不是 Container


对齐只有在父控件提供紧凑的约束时才有效。

dart 复制代码
return Scaffold(
  body: Container(
    color: Colors.red,
    width: 300,
    height: 800,
    child: FractionallySizedBox(
      widthFactor: 0.5,
      heightFactor: 0.5,
      alignment: Alignment.bottomRight,
      child: ColoredBox(
        color: Colors.blue,
      ),
    ),
  ),
);

Container 应用了 300x800 的紧凑约束。ColoredBox 变成了 150x400,并对齐到底部右侧。

恕我直言,上面的例子意义不大,因为在固定大小的 Container 中使用 FractionallySizedBox 没有任何优势。我们可以使用更直接的 SizedBox 来替代。

像我这样的新手会直觉地尝试用它来调整 Column/Row 子控件的大小。

顺便说一句,以下代码是 ChatGPT 建议的:

dart 复制代码
return Scaffold(
  body: Center(
      child: Row(
        children: [
          FractionallySizedBox(
            widthFactor: 0.3,
            child: Container(color: Colors.blue),
          ),
          FractionallySizedBox(
            widthFactor: 0.7,
            child: Container(color: Colors.green),
          ),
        ],
      )),
);

这段代码会触发一个异常:BoxConstraints forces an infinite width(BoxConstraints 强制了一个无限的宽度)。

原因是 Row 沿着主轴(x 轴)对其子控件施加了无限制的 约束。而 0.3 乘以无限仍然是无限。

我们可以使用 Expanded 来解决这个问题。

dart 复制代码
return Scaffold(
  body: Center(
      child: SizedBox(
        height: 100,
        child: Row(
          children: [
            Expanded(
              child: FractionallySizedBox(
                widthFactor: 0.3,
                child: Container(color: Colors.blue),
              ),
            ),
            Expanded(
              child: FractionallySizedBox(
                widthFactor: 0.7,
                child: Container(color: Colors.green),
              ),
            ),
          ],
        ),
      )),
);

但这个结果并不是我所期望的。

也许在某些情况下有用,但通过来说我们想要的是这样的:

而且这可以用更少的代码实现:

dart 复制代码
return Scaffold(
  body: Center(
      child: SizedBox(
        height: 100,
        child: Row(
          children: [
            Flexible( flex: 3, child: Container(color: Colors.blue),),
            Flexible(flex: 7, child: Container(color: Colors.green)),
          ],
        ),
      )),
);

在父控件应用紧凑 约束时,FractionallySizedBox 没有意义;而在无限制约束内部,它又无法正常工作。

那么,它在哪里可以很好地发挥作用呢?

它在那些应用宽松约束minWidth < maxWidth, maxWidth != double.infinity)的控件内部能很好地工作,例如 ScaffoldCenterConstrainedBox

FractionallySizedBox 非常适合创建响应式布局,当你想让控件占据其父控件特定百分比的大小时,它是一个很棒的选择。

最佳应用场景

  • 一个占据可用宽度 80% 的按钮。(EzGlassButton 默认占据 width = double.infinity
dart 复制代码
return Scaffold(
    body: Center(
      child: FractionallySizedBox(
        widthFactor: 0.8,
        child: EzGlassButton(
          child: EzText('CLICK ME!', fontSize: 24,),
        ),
      ),
    ));

这在大屏幕上看起来太大了:

我们可以使用 ConstrainedBox 来进一步改进它。

dart 复制代码
return Scaffold(
    body: Center(
      child: ConstrainedBox(
        constraints: BoxConstraints(
          maxWidth: 500,
        ),
        child: FractionallySizedBox(
          widthFactor: 0.8,
          child: EzGlassButton(
            child: EzText('CLICK ME!', fontSize: 24,),
          ),
        ),
      ),
    ));

现在它的大小与其父控件成比例,但宽度不能超过 500 像素。


ConstrainedBox 包裹的 FractionallySizedBox 是一个非常强大的组合,在响应式 Flutter 设计中经常使用。

dart 复制代码
return Scaffold(
    body: Center(
      child: Wrap(
        children: [
          ConstrainedBox(
            constraints: BoxConstraints(
              maxWidth: 400,
            ),
            child: FractionallySizedBox(
                widthFactor: 0.9,
                child: Container(color: Colors.red, height: 150, )
            ),
          ),
          ConstrainedBox(
            constraints: BoxConstraints(
              maxWidth: 400,
            ),
            child: FractionallySizedBox(
                widthFactor: 0.9,
                child:  Container(color: Colors.blue, height: 150, )
            ),
          ),
          ConstrainedBox(
            constraints: BoxConstraints(
              maxWidth: 400,
            ),
            child: FractionallySizedBox(
                widthFactor: 0.9,
                child:  Container(color: Colors.orange, height: 150, )
            ),
          ),
        ],
      ),
    ));

在任何手机设备上,Container 会占据屏幕宽度的 90% 并垂直显示。然而,在桌面设备上,它们的宽度会受到 ConstrainedBox 的限制,并水平显示。

就是这些了。

感谢您的阅读,祝您设计愉快!

相关推荐
jay神41 分钟前
【计算机毕业设计】基于Flask+Vue的电影数据可视化与智能推荐系统
前端·vue.js·python·信息可视化·flask·毕业设计·课程设计
FreeTinker7 小时前
HTML本地存储技术解析:localStorage与sessionStorage的原理、差异与应用场景
前端·html
qq_452396237 小时前
第十二篇:《全链路监控与可观测性:前端错误追踪与性能分析》
前端
wangruofeng8 小时前
Phosphor Icons 官网源码拆解:URL 即存储、水波动画与 7362 Star 图标库的架构实践
前端·架构·github
BigTopOne8 小时前
WebRTC Native / Android 开发学习资源整理
前端
excel9 小时前
nuxt 3 升级 nuxt 4 报错之 hasInjectionContext
前端
何以解忧,唯有..9 小时前
LangChain 工具调用(Tool Calling)实战指南
java·前端·langchain
软件聚导航10 小时前
「聚小软 AI 助手」技术升级:从数据库检索到 RAG 知识库问答
前端·数据库·mysql·微信小程序·小程序·ai编程·rag
恋猫de小郭11 小时前
看懂大模型架构术语,帮助你理解目前常见的大模型开源架构
前端·人工智能·ai编程
yma1611 小时前
通过提示词实现GitHub Pages 和 Nginx 双部署竟然这么简单?
前端