三河市建设厅公示网站,灰色行业推广渠道,女子医院网站开发策略,加强单位门户网站建设的通知1. Flutter UI架构Flutter将视图数据抽象成为三个部分#xff0c;即Widget树、Element树和RenderObject树。Widget树#xff1a;控件的配置信息#xff0c;不涉及渲染#xff0c;更新代价极低。RenderObject树#xff1a;真正的UI渲染树#xff0c;负责渲染UI#xff0c…1. Flutter UI架构Flutter将视图数据抽象成为三个部分即Widget树、Element树和RenderObject树。Widget树控件的配置信息不涉及渲染更新代价极低。RenderObject树真正的UI渲染树负责渲染UI更新代价极大。Element树Widget树和RenderObject树之间的粘合剂,负责将Widget树的变更以最低的代价映射到RenderObject树上。2. Flutte布局原理1. 源码分析RenderObject是Flutter真正的UI渲染树负责界面的测量布局和绘制Flutter页面布局相关的源码都在RenderObject及其子类中。上图是RenderObject类中和布局相关的属性和方法.constrainst属性由直接父布局提供的布局约束(最大高度最小高度最大宽度最小宽度)layout方法由父RenderObject调用计算当前RenderObject的布局父RenderObject传递给子RenderObject约束信息子RenderObject必须服从约束信息。如果父RenderObject需要子RenderObject的布局信息parentUsesSize参数应该传true否则传false。performLayout子类必须重写的方法计算当前RenderObject和子RenderObject的布局信息。performResize子类必须重写的方法仅使用约束更新RenderObject的布局。RenderConstrainedBox是ConstrainedBox对应的RenderObject最多有一个子RenderObject 如果子RenderoObject不为空则对子RenderObject进行布局并计算布局的大小。RenderFlex是Column和Row对应的RenderObject可以包含多个子RenderObject 如果子RenderoObject不为空则对子RenderObject依次进行布局并计算布局的大小。2. Flutte布局原理总结RenderObject会通过它的父级获得自身的约束。 约束实际上就是4个浮点类型的集合最大/最小宽度以及最大/最小高度。然后这个RenderObject将会逐个遍历它的children列表。向子级传递约束子级之间的约束可能会有所不同)然后询问它的每一个子级需要用于布局的大小。然后这个RenderObject就会对它子级的children逐个进行布局。(水平方向是x轴竖直是y轴)最后RenderObject将会把它的大小信息向上传递至父RenderObject(包括其原始约束条件)。3. Flutter布局限制由于父RenderObject传递给子RenderObject约束信息子RenderObject传递给父RenderObject大小信息Flutter布局存在一些限制一个RenderObject仅在其父级给其约束的情况下才能决定自身的大小。 这意味着RenderObject通常情况下不能任意获得其想要的大小。一个RenderObject无法知道也不需要决定其在屏幕中的位置。 因为它的位置是由其父级决定的。当轮到父级决定其大小和位置的时候同样的也取决于它自身的父级所以在不考虑整棵树的情况下几乎不可能精确定义任何RenderObject的大小和位置。4. Flutter布局实战1.线性布局线性布局的子布局在主轴上长度不能设置无限大(double.infinity)因为线性布局给子布局在主轴上的最大长度的约束就是无限大(double.infinity)会导致无限大的子布局无法计算当前布局的大小布局失败。如下// 第一个子Container的高度设置为无限大导致布局失败Column( children: [ Container( width: 200.0, height: double.infinity, color: Colors.blue, ), Container( width: 200.0, height: 200.0, color: Colors.red, ), ],);// 子Column的高度为无限大导致布局失败Column( children: [ Column( children: [ Container( width: 200.0, height: 200.0, color: Colors.blue, ), ], ) Container( width: 200.0, height: 200.0, color: Colors.red, ), ],);如果想要让子布局占满全屏可以增加Expanded布局。如下Column( children: [ Expanded( child: Container( width: 200.0, height: double.infinity, color: Colors.blue, ), ), Container( width: 200.0, height: 200.0, color: Colors.red, ), ],);Column( children: [ Expanded( child: Column( children: [ Container( width: 200.0, height: 200.0, color: Colors.blue, ), ], ), ), Container( width: 200.0, height: 200.0, color: Colors.red, ), ],);2. 栈布局栈布局的子布局设置相对位置推荐使用Padding代替Position并把fit属性设置StackFit.loose构建时Stack会自适应大小否则需要使用Container设置Stack和Position的大小并且Padding默认对上下左右都有相对距离(0)但Position没有默认的相对布局如果忘记设置会使Position的子布局无法自动换行或布局不显示。不推荐// Text无法自动换行// Container布局不显示Stack( children: [ Positioned( top: 100.0, child: Text( 测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试), ), Positioned( top: 0.0, child: Column( children: [ Container( height: 100.0, width: double.infinity, color: Colors.red, ), ], ), ) ],);推荐Stack( children: [ Padding( padding: const EdgeInsets.only(top: 10.0), child: Text( 测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试), ), Padding( padding: const EdgeInsets.only(top: 0.0), child: Column( children: [ Container( height: 100.0, width: double.infinity, color: Colors.red, ), ], ), ) ],);3. 可滚动布局可滚动布局在主轴方向上的长度是无限大父布局需要转递给可滚动布局最大长度的约束。Column( children: [ Expanded( child: ListView( children: [ Text(测试), ], ), ), ],);横向可滚动布局必须设置高度。Column( children: [ Container( height: 200.0, child: ListView( scrollDirection: Axis.horizontal, children: [ Text(测试), ], ), ), ],);可滚动布局嵌套可滚动布局被嵌套布局的shrinkWrap属性必须设置为true并且可以将physics属性设置为NeverScrollableScrollPhysics()来解决滑动冲突。ListView( children: [ ListView( shrinkWrap: true, physics: NeverScrollableScrollPhysics(), children: [ Text(测试), ], ), ],);5. 总结本文章通过源码分析讲述Flutter布局的过程分析实战中布局不显示的原因并给出Flutter布局的一些建议。