使用Flutter的视觉,结构,平台和交互式小部件集合更快地建立漂亮的应用程序。html
基本部件java
在构建您的第一个Flutter应用程序以前,您绝对须要了解这些小部件。算法
一个方便的小部件,结合了常见的绘画,定位和尺寸小部件。数组
一个容器首先用padding包围子组件(由decoration中出现的全部边框填满),而后将附加constraints应用于填充范围(将width和height做为约束合并(若是其中任一个非空)。而后container被 margin描述的额外的空白空间包围。app
在绘制过程当中,容器首先应用给定的transform,而后绘制decoration来填满填充范围,而后绘制子组件,最后绘制foregroundDecoration,并填满填充范围。框架
没有子组件的容器尽量大,除非传入的约束是无限的。在这种状况下,他们尽量小,有子组件的容器将本身的尺寸扩大到他们的孩子大小,构造函数的宽度,高度和constraints参数将覆盖这些。less
布局行为ide
有关Box布局模型的介绍,请参阅BoxConstraints(盒修饰)。函数
因为Container将许多其它部件与各自的布局行为结合在一块儿,所以Container的布局行为有点复杂。工具
Container按顺序尝试:遵照alignment,将本身调整到child部件的尺寸,遵照宽度,高度和constraints,扩展以适应父部件,变得尽量小。
进一步来讲:
若是部件没有子,没有height,没有width,没有constraints(对子部件的约束),父母提供了无界限的约束,那么Container尝试尽量小。
若是部件没有子且没有alignment(对齐),可是提供了高度,宽度或constraints(约束),那么基于给定这些约束和父对象的约束相结合容器会尝试尽量小。
若是小部件没有孩子,没有高度,没有宽度,没有约束,也没有对齐,但父级提供有界的约束,则Container展开以适应父级提供的约束。
若是部件具备alignment,而且父级提供了无界的约束,那么容器会尝试围绕该子部件调整本身的大小。
若是部件有alignment,而且父级提供了有界限的约束,那么容器会尝试展开以适合父级,而后根据alignment将该子级定位到其自身内。
另外,部件有一个子部件,但没有高度,没有宽度,没有约束,也没有对齐,而且容器将约束从父项传递给子项,并将其自身尺寸设置为与子部件匹配。
如这些属性的文档中所述,margin和padding属性也会影响布局。 (它们的效果只是丰富了上述规则。)decoration能够隐式强化填充(例如,BoxDecoration中的边框有助于填充); 请参阅Decoration.padding。
示例代码
这个例子显示了一个48x48的绿色正方形(放置在一个Center部件中,以防父容器对Container应该采用的尺寸有本身的见解),并带有一个边距,以便它远离相邻的小部件:
new Center( child: new Container( margin: const EdgeInsets.all(10.0), color: const Color(0xFF00FF00), width: 48.0, height: 48.0, ), )
此示例显示如何一次使用Container的许多功能。constraints被设置为适合字体大小加上充足的头部垂直空间,同时水平扩展以适合父母。padding用于确保内容和文本之间有空间。 颜色使箱子蓝绿色。alignment使得子部件被置于框中。foregroundDecoration将九个斑点的图像叠加到文本上。最后,transform对整个装置施加轻微旋转以完成效果。
new Container( constraints: new BoxConstraints.expand( height: Theme.of(context).textTheme.display1.fontSize * 1.1 + 200.0, ), padding: const EdgeInsets.all(8.0), color: Colors.teal.shade700, alignment: Alignment.center, child: new Text('Hello World', style: Theme.of(context).textTheme.display1.copyWith(color: Colors.white)), foregroundDecoration: new BoxDecoration( image: new DecorationImage( image: new NetworkImage('https://www.example.com/images/frame.png'), centerSlice: new Rect.fromLTRB(270.0, 180.0, 1360.0, 730.0), ), ), transform: new Matrix4.rotationZ(0.1), )
也能够看看:
继承结构
Object>Diagnosticable>DiagnosticableTree>Widget>StatelessWidget>Container
构造器
Container({Key key, AlignmentGeometry alignment, EdgeInsetsGeometry padding, Color color, Decoration decoration, Decoration foregroundDecoration, double width, double height, BoxConstraints constraints, EdgeInsetsGeometry margin, Matrix4 transform, Widget child })
建立一个结合常见绘画,定位和尺寸小部件的小部件。[...]
属性
将容器内的子部件对齐。[...]
final
容器中包含的子部件。[...]
final
应用于子部件的附加限制。[...]
final
绘制子部件背景装饰。[...]
final
foregroundDecoration → Decoration
绘制子部件前景装饰。
final
围绕装饰和子部件的空的区域。
final
在装饰里面刻写的空的区域。 子部件,若是有的话,被放置在这个填充。 [...]
final
绘制容器以前应用的转换矩阵。
final
此对象的哈希码. [...]
read-only, inherited
控制一个部件如何替换树中的另外一个部件。 [...]
final, inherited
对象的运行时类型的表示。
read-only, inherited
方法
build(BuildContext context) → Widget
介绍由此部件表明的用户界面的一部分. [...]
debugFillProperties(DiagnosticPropertiesBuilder description) → void
createElement() → StatelessElement
建立一个StatelessElement来管理该小部件在树中的位置. [...]
inherited
debugDescribeChildren() → List<DiagnosticsNode>
返回描述此节点的子节点的DiagnosticsNode对象的列表. [...]
@protected, inherited
noSuchMethod(Invocation invocation) → dynamic
当访问不存在的方法或属性时调用. [...]
inherited
toDiagnosticsNode({String name, DiagnosticsTreeStyle style }) → DiagnosticsNode
返回调试工具和toStringDeep使用的对象的调试表示形式. [...]
inherited
toString({DiagnosticLevel minLevel: DiagnosticLevel.debug }) → String
返回此对象的字符串表示形式.
inherited
toStringDeep({String prefixLineOne: '', String prefixOtherLines, DiagnosticLevel minLevel: DiagnosticLevel.debug }) → String
返回此节点及其后代的字符串表示形式. [...]
inherited
toStringShallow({String joiner: ',', DiagnosticLevel minLevel: DiagnosticLevel.debug }) → String
返回对象的单行详细描述. [...]
inherited
toStringShort() → String
这个部件的简短的文字描述.
inherited
操做符
operator ==(other) → bool
相等运算符. [...]
inherited
在水平方向上布局子部件的列表。
一个以水平数组显示其子项的部件。
要让孩子展开以填充可用的水平空间,请将该孩子包裹在Expanded部件中。
Row部件不会滚动(而且通常认为在一行中有更多的孩子比适合可用的房间更好是错误的)。若是您有一行小部件,并但愿它们在空间不足的状况下可以滚动,请考虑使用ListView。
对于垂直变体,请参见Column。
若是你只有一个子组件,那么考虑使用Align或Center来定位子组件。
示例代码
此示例将可用空间划分为三个(水平),并将文本居中放置在前两个单元格中,并将Flutter徽标放在第三个单元格中央:
new Row( children: <Widget>[ new Expanded( child: new Text('Deliver features faster', textAlign: TextAlign.center), ), new Expanded( child: new Text('Craft beautiful UIs', textAlign: TextAlign.center), ), new Expanded( child: new FittedBox( fit: BoxFit.contain, // otherwise the logo will be tiny child: const FlutterLogo(), ), ), ], )
疑难解答
为何个人行有黄色和黑色的警告条纹?
若是该行的非弹性内容比该行(那些不包含在Expanded或Flexible部件中的)自己多,则该行被认为已经溢出。当一行溢出时,该行没有任何剩余空间Expanded和Flexible的子项。该行经过在溢出的边上绘制黄色和黑色条纹警告来报告此状况。若是行外有空间,溢出量将以红色字体打印。
故事时间
假设,例如,你有这样的代码:
new Row( children: <Widget>[ const FlutterLogo(), const Text('Flutter\'s hot reload helps you quickly and easily experiment, build UIs, add features, and fix bug faster. Experience sub-second reload times, without losing state, on emulators, simulators, and hardware for iOS and Android.'), const Icon(Icons.sentiment_very_satisfied), ], )
该行首先询问其第一个子部件FlutterLogo布局,以任何尺寸标识。该徽标是友好的,愉快地决定一边24像素。这为下一个子部件留下了不少空间。该行而后询问下一个子部件,文本,它认为最好的尺寸布局。
在这一点上,不知道有多宽的文字会超出,说:“Ok, I will be thiiiiiiiiiiiiiiiiiiiis wide.”,而且远远超出了该行可用的空间,而不是包裹。行反应,“That's not fair, now I have no more room available for my other children!”,并生气发芽,黄色和黑色的条幅。
解决方法是将第二个孩子包装在Expanded部件中,该部件告诉行该子部件应该给予剩余房间:
new Row( children: <Widget>[ const FlutterLogo(), const Expanded( child: const Text('Flutter\'s hot reload helps you quickly and easily experiment, build UIs, add features, and fix bug faster. Experience sub-second reload times, without losing state, on emulators, simulators, and hardware for iOS and Android.'), ), const Icon(Icons.sentiment_very_satisfied), ], )
如今,该行首先要求logo布局,而后要求该icon布局。象标志同样,Icon很乐意采用合理的尺寸(也是24像素,并不是巧合,由于FlutterLogo和Icon都符合环境IconTheme)。这留下了一些空间,如今该行告诉文本究竟有多宽:剩余空间的确切宽度。该文本如今很乐意遵照合理的请求,将文本包装在该宽度内,而且最终将一段文字分红几行。
布局算法
本节介绍框架如何渲染Row。 有关Box布局模型的介绍,请参阅BoxConstraints。
一行的布局分六步进行:
也能够看看:
继承结构
Object>Diagnosticable>DiagnosticableTree>Widget>RenderObjectWidge>MultiChildRenderObjectWidget>Flex>Row
构造函数
Row({Key key, MainAxisAlignment mainAxisAlignment: MainAxisAlignment.start, MainAxisSize mainAxisSize: MainAxisSize.max, CrossAxisAlignment crossAxisAlignment: CrossAxisAlignment.center, TextDirection textDirection, VerticalDirection verticalDirection: VerticalDirection.down, TextBaseline textBaseline, List<Widget> children: const [] })
建立一个水平的子部件数组。[...]
属性
树中的部件下面的部件. [...]
final, inherited
crossAxisAlignment → CrossAxisAlignment
子部件应该如何沿着横轴放置. [...]
final, inherited
用做主轴的方向. [...]
final, inherited
此对象的哈希码. [...]
read-only, inherited
控制一个部件如何替换树中的另外一个部件. [...]
final, inherited
mainAxisAlignment → MainAxisAlignment
子部件应该如何沿主轴放置. [...]
final, inherited
在主轴上应占多少空间. [...]
final, inherited
对象的运行时类型的表示.
read-only, inherited
若是根据他们的基线对齐条目,使用哪一个基线.
final, inherited
肯定水平放置子部件的顺序以及如何解释水平方向的开始和结束. [...]
final, inherited
verticalDirection → VerticalDirection
肯定垂直放置子部件的顺序以及如何解释垂直方向的开始和结束. [...]
final, inherited
方法
createElement() → MultiChildRenderObjectElement
RenderObjectWidgets老是膨胀为一个RenderObjectElement子类.
inherited
createRenderObject(BuildContext context) → RenderFlex
使用RenderObjectWidget描述的配置建立此RenderObjectWidget表示的RenderObject类的实例 . [...]
inherited
debugDescribeChildren() → List<DiagnosticsNode>
返回描述此节点的子节点的DiagnosticsNode对象的列表. [...]
@protected, inherited
debugFillProperties(DiagnosticPropertiesBuilder description) → void
inherited
didUnmountRenderObject(RenderObject renderObject) → void
先前与此部件关联的呈现对象已从树中移除。 给定的RenderObject将与此对象的createRenderObject返回的类型相同.
@protected, inherited
getEffectiveTextDirection(BuildContext context) → TextDirection
传给RenderFlex.textDirection的值. [...]
@protected, inherited
noSuchMethod(Invocation invocation) → dynamic
当访问不存在的方法或属性时调用. [...]
inherited
toDiagnosticsNode({String name, DiagnosticsTreeStyle style }) → DiagnosticsNode
返回调试工具和toStringDeep使用的对象的调试表示形式. [...]
inherited
toString({DiagnosticLevel minLevel: DiagnosticLevel.debug }) → String
返回此对象的字符串表示形式.
inherited
toStringDeep({String prefixLineOne: '', String prefixOtherLines, DiagnosticLevel minLevel: DiagnosticLevel.debug }) → String
返回此节点及其后代的字符串表示形式. [...]
inherited
toStringShallow({String joiner: ', ', DiagnosticLevel minLevel: DiagnosticLevel.debug }) → String
返回对象的单行详细描述. [...]
inherited
toStringShort() → String
这个部件的简短的文字描述.
inherited
updateRenderObject(BuildContext context, RenderFlex renderObject) → void
将此RenderObjectWidget描述的配置复制到给定的RenderObject,该RenderObject与该对象的createRenderObject返回的类型相同 . [...]
inherited
操做符
operator ==(other) → bool
等值操做符. [...]
inherited
以垂直阵列显示其子项的部件。
要让子部件扩大以填充可用的垂直空间,请将该子部件包装在Expanded部件中。
Column部件不滚动(而且一般认为宁愿在列中有更多子项也不使用适合可用空间是错误的)。 若是您有一行小部件,并但愿它们在空间不足的状况下可以滚动,请考虑使用ListView。
对于水平变体,请参见Row。
若是只有一个子部件,那么考虑使用Align或Center来定位子部件。
示例代码
这个例子使用一个Column垂直排列三个部件,最后一个用来填充全部剩余的空间。
new Column( children: <Widget>[ new Text('Deliver features faster'), new Text('Craft beautiful UIs'), new Expanded( child: new FittedBox( fit: BoxFit.contain, // otherwise the logo will be tiny child: const FlutterLogo(), ), ), ], )
在上面的示例中,text和logo位于每行的中心。在如下示例中,crossAxisAlignment设置为CrossAxisAlignment.start,以便子部件左对齐。mainAxisSize被设置为MainAxisSize.min,以便该列缩小以适合子部件。
new Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, children: <Widget>[ new Text('We move under cover and we move as one'), new Text('Through the night, we have one shot to live another day'), new Text('We cannot let a stray gunshot give us away'), new Text('We will fight up close, seize the moment and stay in it'), new Text('It’s either that or meet the business end of a bayonet'), new Text('The code word is ‘Rochambeau,’ dig me?'), new Text('Rochambeau!', style: DefaultTextStyle.of(context).style.apply(fontSizeFactor: 2.0)), ], )
故障排除
当传入的垂直约束是无界的时候
当一个列有一个或多个Expanded或Flexible的子元素,而且被放置在另外一列,或者在一个ListView中,或者在其它没有为该列提供最大高度限制的上下文中时,你会在运行时说这个异常存在弹性子部件,但垂直约束是无界的。
这个例外所伴随的细节中所描述的问题是,使用Flexible或Expanded意味着在布置全部其余子部件以后的剩余空间必须平等地共享,可是若是传入的垂直约束是无限的,则剩余空间有无限空间。
解决这个问题的关键一般是肯定为何Column正在接收无界的垂直约束。
发生这种状况的一个常见缘由是列已被放置在另外一列中(没有使用Expanded或Flexible围绕内部嵌套列)。当一个列布局它的非柔性子部件(那些既没有 Expanded也没有Flexible包裹的子部件)时,它给了他们无限的约束,以便他们能够肯定他们本身的尺寸(传递无界的约束一般指示子部件应该收缩包裹其内容)。在这种状况下,解决方案一般只是将内部列包装在Expanded中,以代表它应该占用外部列的剩余空间,而不只仅是它须要的空间。
显示此消息的另外一个缘由是将列嵌套到ListView或其余垂直滚动条中。在这种状况下,确实存在无限的垂直空间(垂直滚动列表的整个点是容许垂直无限空间)。在这种状况下,一般值得研究内部列为何应该有一个Expanded或Flexible的子部件:内部子部件应该是多大?这种状况下的解决方案一般是从内部子部件周围移除Expanded或Flexible部件。
有关约束的更多讨论,请参阅BoxConstraints。
黄色和黑色的条纹横幅
当列的内容超过可用空间量时,列溢出,内容被剪辑。 在调试模式下,在溢出边缘处呈现黄色和黑色条纹条以指示问题,并在列下方显示一条消息,指出检测到多少溢出。
一般的解决方案是使用ListView而不是Column来在垂直空间有限时使内容滚动。
布局算法
本节介绍框架如何呈现一列。 有关Box布局模型的介绍,请参阅BoxConstraints。
一列的布局分六步进行:
也能够看看:
继承结构
Object>Diagnosticable>DiagnosticableTree>Widget>RenderObjectWidget>MultiChildRenderObjectWidget>Flex>Column
构造函数
Column({Key key, MainAxisAlignment mainAxisAlignment: MainAxisAlignment.start, MainAxisSize mainAxisSize: MainAxisSize.max, CrossAxisAlignment crossAxisAlignment: CrossAxisAlignment.center, TextDirection textDirection, VerticalDirection verticalDirection: VerticalDirection.down, TextBaseline textBaseline, List<Widget> children: const [] })
建立一个垂直的子部件数组. [...]
属性,方法,操做符
同Row