欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

flutter布局的基本概念

程序员文章站 2022-05-25 19:51:09
...

本文记录开发过程中看到的零散细节

Constraints

在flutter视图布局中,parent widget中会给child设置布局约束,包含

isTight: 是否是固定尺寸,比如BoxConstraints的min max均一致时isTight返回true
isNormalized: 约束是否正常,比如BoxConstraints中0<=min<=max时isNormalized为true

Constraints有两个子类,
BoxConstraints,由minWidth, maxWidth, minHeight, maxHeight共同构成的约束
loosen(): 返回min为0.0, max不变的约束
tighten(double width, doubleHeight): 取clamp(min, height)的值作为min、max。如果参数在min、max之间,则返回的是一个入参大小的固定尺寸约束
SliverConstraints,描述viewport中sliver的滚动状态
axisDirection:scrollOffset和remainingPaintExtend的方向,比如AxisDirection.up
grownthDirection: 内容的排列方向,比如GrowthDirection.forward

Flex

针对BoxConstraints,如果width或者height为double.INFILITY,那么可以称为unbounded constraints。比如ListView的高度就是double.INFILITY,它的约束就是unbounded cosntraints。
Flex的特点为:当在有限的空间内会占满所有空间,在无限空间(unbounded constraints)内会匹配子widget的大小
,比如常见的Row和Column。

Widget

widget是我们写界面时用于描述ui的组件,部分组件是可以用于界面显示的,比如Icon, Text,部分是用于布局的,比如Align, Container, Center等,部分是用于其它功能,比如GestureDetector是用于添加事件监听的。
Widget主要提供如下属性和方法
key: 用来控制在widget树中替换widget的时候使用的
createElement():创建一个Element,可以理解为将该widget作为该Element的configuration
canUpdate(Widget oldWidget, Widget newWidget):

Widget的子类StatelessWidget
build(BuildContext context): 创建一个widget,可以理解为根据配置重新配置widget tree

Widget的子类RenderObjectWidget
createRenderObject(BuildContext context): 根据当前widget的配置创建RenderObject
updateRenderObject(BuildContext context, covariant RenderObject renderObject): 复制当前widget的信息到新的renderObject
didUnmountRenderObject(covariant RenderObject renderObject): 当前widget关联的renderObject从树中移除

Element

可以理解为代表widget在树中的位置,它实现了BuildContext类
_widget: 关联的widget,不为null
_parent: 父Element
slot: 由父Element设置,用于确定位于parent中的位置
depth: 整数,比parent的要大
owner: 管理该element生命周期的对象,类型为BuildOwner
visitChildren(ElementVisitor visitor): 访问child,其中visitor是一个入参为element的函数
updateChild(Element child, Widget newWidget, dynamic newSlot): 用新配置更新child,会判断是要移除现有element,还是新建element替换或者添加到当前element位置,会间接调用到inflateWidget、mount等方法

RenderObject

reader tree中的对象,继承自AbstractNode,AbstractNode提供了node对象的一般方法,比如parent, depth, owner,attached的getter方法,同时提供adoptChild和dropChild等方法。
parentData: 在parent的setupParentData方法中设置,用于布局
visitChildren(RenderObjectVisitor visitor): 访问child
owner: 返回PipelineOwner,该对象仅在RenderingBinding.initInstances()中实例化
layout(Constraints constraints, { bool parentUsesSize = false }: 计算该render object的尺寸,通常由parent调用

调用堆栈

widget build的调用栈

MyApp.build (main.dart:12)
StatelessElement.build (framework.dart:3774)
ComponentElement.performRebuild (framework.dart:3721)
Element.rebuild (framework.dart:3547)
ComponentElement._firstBuild (framework.dart:3701)
ComponentElement.mount (framework.dart:3696)
Element.inflateWidget (framework.dart:2950)
Element.updateChild (framework.dart:2753)
RenderObjectToWidgetElement._rebuild (binding.dart:909)
RenderObjectToWidgetElement.mount (binding.dart:880)
RenderObjectToWidgetAdapter.attachToRenderTree.<anonymous closure> (binding.dart:826)
BuildOwner.buildScope (framework.dart:2266)
RenderObjectToWidgetAdapter.attachToRenderTree (binding.dart:825)
_WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding&WidgetsBinding.attachRootWidget (binding.dart:712)
runApp (binding.dart:756)
main (main.dart:7)
_startIsolate.<anonymous closure>
_RawReceivePortImpl._handleMessage

StatefulWidget createState的调用栈

MaterialApp.createState (app.dart:323)
new StatefulElement (framework.dart:3789)
StatefulWidget.createElement (framework.dart:795)
Element.inflateWidget (framework.dart:2948)
Element.updateChild (framework.dart:2753)
ComponentElement.performRebuild (framework.dart:3732)
Element.rebuild (framework.dart:3547)
ComponentElement._firstBuild (framework.dart:3701)
ComponentElement.mount (framework.dart:3696)
Element.inflateWidget (framework.dart:2950)
Element.updateChild (framework.dart:2753)
RenderObjectToWidgetElement._rebuild (binding.dart:909)
RenderObjectToWidgetElement.mount (binding.dart:880)
RenderObjectToWidgetAdapter.attachToRenderTree.<anonymous closure> (binding.dart:826)
BuildOwner.buildScope (framework.dart:2266)
RenderObjectToWidgetAdapter.attachToRenderTree (binding.dart:825)
_WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding&WidgetsBinding.attachRootWidget (binding.dart:712)
runApp (binding.dart:756)
main (main.dart:7)
_startIsolate.<anonymous closure>
_RawReceivePortImpl._handleMessage

drawFrame的调用栈,从main函数的runApp开始

_WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding.ensureVisualUpdate (binding.dart:641)
PipelineOwner.requestVisualUpdate (object.dart:720)
RenderView.scheduleInitialFrame (view.dart:117)
_WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding.initRenderView (binding.dart:134)
_WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding.initInstances (binding.dart:39)
_WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding&WidgetsBinding.initInstances (binding.dart:250)
new BindingBase (binding.dart:53)
new _WidgetsFlutterBinding&BindingBase&GestureBinding (binding.dart:1)
new _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding (binding.dart:1)
new _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding (binding.dart:1)
new _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding (binding.dart:1)
new _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding (binding.dart:1)
new _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding (binding.dart:1)
new _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding&WidgetsBinding (binding.dart:1)
new WidgetsFlutterBinding (binding.dart:1)
WidgetsFlutterBinding.ensureInitialized (binding.dart:964)
runApp (binding.dart:755)
main (main.dart:7)
_startIsolate.<anonymous closure>
_RawReceivePortImpl._handleMessage

RenderObject 的布局调用栈,一般RenderObject需要实现performLayout方法,在其中调用child的layout

RenderObject.layout (object.dart:1547)
_RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (proxy_box.dart:104)
RenderObject.layout (object.dart:1634)
RenderView.performLayout (view.dart:147)
RenderObject._layoutWithoutResize (object.dart:1509)
PipelineOwner.flushLayout (object.dart:768)
_WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding.drawFrame (binding.dart:281)
_WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding&WidgetsBinding.drawFrame (binding.dart:677)
_WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding._handlePersistentFrameCallback (binding.dart:219)
_WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding._invokeFrameCallback (binding.dart:990)
_WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding.handleDrawFrame (binding.dart:930)
_WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding.scheduleWarmUpFrame.<anonymous closure> (binding.dart:751)
Timer._createTimer.<anonymous closure>
_Timer._runTimers
_Timer._handleMessage
_RawReceivePortImpl._handleMessage
相关标签: flutter