flutter 布局管理【详解】

简介: flutter 布局管理【详解】

布局原理

每个组件在渲染之前的布局过程具体可分为两个线性过程。首先从组件顶部向下传递布局约束,然后从底部向上传递布局信息。

这两个线性过程会在元素树所引用的RenderObject树中完成,并且最终的布局信息将保存在RenderObject中。因此,当重新构建组件时,如果元素和RenderObject能够复用,那么同样可以使用和上次一样的布局信息。这种单向传递和保存信息的方式是Flutter布局性能优于其他框架的重要原因之一。


RenderObject树由一个个RenderObject组合而成。当Element实例挂载到元素树上后,就会调用组件的createRenderObject()方法生成对应的RenderObject。由于RenderObject树被元素树引用,并且主要任务就是帮助Element实例做具体的渲染工作,因此RenderObject树也常称为元素树的子树。

每个RenderObject会被元素持有,并且在组件重建后会尽量复用,每当元素中的状态发生改变时,就会调用组件的updateRenderObject()方法更新渲染对象,屏幕上的值最终得以更新。

RenderObject类中提供了很多与布局密切相关的对象和方法,如下所示。

  • constraints对象,从父组件中传递过来的约束对象。
  • parentData对象,从子组件传递来的具体布局信息。
  • performLayout()方法,负责具体的布局逻辑。
  • paint方法,绘制组件和它的子组件。

RenderObject是一个抽象类,每种Element都会指向不同类型的渲染对象,继承自RenderOject的两个主要的类是RenderBox和RenderSliver,它们分别使用盒子协议和滑动协议来做布局工作。基于这两个类,Flutter还提供了许多处理特定场景的渲染类,如RenderShiftedBox和RenderStack等。

布局约束 1 —— 盒子协议

box protocol 用于静态布局

父节点传递给其子节点的约束是一个BoxConstraints对象。这种约束对象内部有4个属性,分别用来规定每个子节点的最大和最小宽度与高度。这种约束会一直向下延伸,子组件也会产生约束,再传递给它下面的子组件,这个过程一直延续到组件树最下面的叶子节点。


比如,父节点传入了MinWidth=150像素,MaxWidth=350像素,MinHeight=100像素,MaxHeight=double.infinity(尽可能大)的BoxConstraints对象。

子组件接收到这个约束后,便会根据BoxConstraints对象取得上图中指定范围内的值,即宽度介于150~350像素,高度大于或等于100像素。当取得具体的值之后,就会将值向上传递给父组件,父组件会根据这些信息确定子组件的位置,再对它做具体的布局操作,这样就达到了父子组件间的布局通信。



组件接收到盒子布局约束后,会分3种情况设置宽度和高度:

  1. 尽可能大地扩展宽度和高度,即总是取布局约束的最大值,如Center、ListView组件
  2. 组件会尽量选择最小值并与它的子组件(如Opacity)的最大宽度、高度相等。
  3. 像Text、Image这类属于叶子节点的组件会以固定尺寸渲染。

自定义盒子布局约束

使用 ConstrainedBox 组件

ConstrainedBox(
  constraints: BoxConstraints(
    maxWidth: 150.0,    // 最大宽度
    maxHeight: 70.0,    // 最大高度
  ),
  child: Container(
    color: Colors.lightBlue,
  ),
)

传递给子组件Container一个最大宽度为150.0像素、最大高度为70.0像素的盒子约束。由于Container在没有子组件的情况下会根据布局约束尽可能大扩展宽度和高度,因此Container的宽度会自动设置为150像素,高度会自动设置为70像素。

布局约束 2 —— 滑动协议

sliver protocol 用于滚动布局

滚动组件里的每个子组件都被定义为一个sliver组件,父组件传递的约束对象为SliverConstraints,该对象不仅记录了视图的滚动方向、遗留空间等信息,还为每个Sliver组件提供了它们在滚动布局中的偏移量。

如上图中的浅黄色的高亮组件,当偏移量为0像素时,在滚动布局边缘完全展示出来。



所以,滚动布局中的组件分为3种:

  1. 当前显示在布局中的组件
  2. 已经滚动出屏幕的组件
  3. 还未滚动到屏幕下方的组件。
目录
相关文章
|
5月前
|
编解码 前端开发 开发者
【Flutter前端技术开发专栏】Flutter中的响应式设计与自适应布局
【4月更文挑战第30天】Flutter框架助力移动应用实现响应式设计与自适应布局,通过层次化布局系统和`Widget`树管理,结合`BoxConstraints`定义尺寸范围,实现自适应。利用`MediaQuery`获取设备信息,调整布局以适应不同屏幕。`FractionallySizedBox`按比例设定尺寸,`LayoutBuilder`动态计算布局。借助这些工具,开发者能创建跨屏幕尺寸、方向兼容的应用,提升用户体验。
130 0
【Flutter前端技术开发专栏】Flutter中的响应式设计与自适应布局
|
5月前
|
存储 JavaScript 前端开发
盘点主流 Flutter 状态管理库2024
状态管理是每个应用不可缺少的,本文将会盘点下主流的状态管理包。
321 2
盘点主流 Flutter 状态管理库2024
|
5月前
|
开发框架 前端开发 数据安全/隐私保护
【Flutter 前端技术开发专栏】Flutter 中的布局与样式设计
【4月更文挑战第30天】本文探讨了Flutter的布局和样式设计,关键点包括:1) 布局基础如Column、Row和Stack用于创建复杂结构;2) Container、Center和Expanded等常用组件的作用;3) Theme和Decoration实现全局样式和组件装饰;4) 实战应用如登录界面和列表页面的构建;5) 响应式布局利用MediaQuery和弹性组件适应不同屏幕;6) 性能优化,避免过度复杂设计。了解并掌握这些,有助于开发者创建高效美观的Flutter应用。
138 0
【Flutter 前端技术开发专栏】Flutter 中的布局与样式设计
|
3月前
Flutter-自定义折叠流布局实现
Flutter-自定义折叠流布局实现
48 0
|
3月前
flutter的状态管理学习
flutter的状态管理学习
|
5月前
|
前端开发 开发者 UED
【Flutter前端技术开发专栏】Flutter中的图标、字体与样式管理
【4月更文挑战第30天】本文介绍了在Flutter中管理图标、字体和样式的做法。Flutter提供`Icons`类用于内置矢量图标,支持第三方图标库如FontAwesome。自定义字体可通过添加字体文件至`assets`目录并配置`pubspec.yaml`,然后使用`TextStyle`设置。借助`ThemeData`,开发者能统一管理应用主题样式,局部样式可覆盖全局。通过集中管理样式,提升代码复用性和应用一致性。
148 0
【Flutter前端技术开发专栏】Flutter中的图标、字体与样式管理
|
5月前
|
存储 JavaScript 前端开发
【Flutter 前端技术开发专栏】Flutter 中的状态管理框架(如 Provider、Redux 等)
【4月更文挑战第30天】本文探讨了 Flutter 开发中的状态管理,重点介绍了 Provider 和 Redux 两种框架。Provider 以其简单易用性适合初学者和小项目,而 Redux 则适用于大型复杂应用,保证状态一致性。此外,还提到了 Riverpod 和 BLoC 等其他框架。选择框架时要考虑项目规模、团队技术水平和个人偏好。文章通过购物车应用示例展示了不同框架的使用,并展望了状态管理框架的未来发展。
143 0
【Flutter 前端技术开发专栏】Flutter 中的状态管理框架(如 Provider、Redux 等)
|
5月前
|
JavaScript 前端开发 开发者
【Flutter前端技术开发专栏】Flutter中的Widget与状态管理
【4月更文挑战第30天】本文探讨了Flutter的Widget和状态管理。Widget是Flutter构建UI的基础,分为有状态和无状态两种。状态管理确保UI随应用状态变化更新,影响应用性能和可维护性。文章介绍了`setState`、`Provider`、`Riverpod`、`Bloc`和`Redux`等状态管理方法,并通过计数器应用展示了其实现。选择合适的状态管理策略对高效开发至关重要。
68 0
【Flutter前端技术开发专栏】Flutter中的Widget与状态管理
|
5月前
|
前端开发 开发者 iOS开发
【Flutter前端技术开发专栏】Flutter中的路由管理与页面跳转
【4月更文挑战第30天】本文介绍了Flutter的路由管理与页面跳转,包括基本和命名路由管理。基本路由使用`Navigator`的`push`和`pop`方法,如`MaterialPageRoute`和`CupertinoPageRoute`。命名路由则通过路由表注册名称进行跳转,如`Navigator.pushNamed`。此外,还展示了如何通过构造函数、`arguments`和`PageRouteBuilder`进行路由传值。掌握这些知识能提升Flutter开发效率。
84 0
【Flutter前端技术开发专栏】Flutter中的路由管理与页面跳转
|
5月前
|
Dart IDE API
Flutter Riverpod 状态管理上手技巧分享
时代在进步 Riverpod 作为一个优秀的状态管理,猫哥也开始做些技术调研。今天会写两个例子,计数器、拉取数据。
141 1
Flutter Riverpod 状态管理上手技巧分享
下一篇
无影云桌面