做自由与创造的先行者

Flutter 布局多个widgets

Flutter开发手册

垂直和水平放置多个widget

最常见的布局模式之一是垂直或水平排列widget。您可以使用行(Row)水平排列widget,并使用列(Column)垂直排列widget。

重点是什么?

行和列是两种最常用的布局模式。

行和列都需要一个子widget列表。

子widget本身可以是行、列或其他复杂widget。

您可以指定行或列如何在垂直或水平方向上对齐其子项

您可以拉伸或限制特定的子widget.

您可以指定子widget如何使用行或列的可用空间.

要在Flutter中创建行或列,可以将一个widget列表添加到Row 或Column 中。 同时,每个孩子本身可以是一个Row或一个Column,依此类推。以下示例显示如何在行或列内嵌套行或列。

注意:行和列是水平和垂直布局的基本、低级widget - 这些低级widget允许最大化的自定义。Flutter还提供专门的,更高级别的widget,可能足以满足您的需求。 例如,您可能更喜欢ListTile而不是Row,ListTile是一个易于使用的小部件,具有前后图标属性以及最多3行文本。您可能更喜欢ListView而不是列,ListView是一种列状布局,如果其内容太长而无法适应可用空间,则会自动滚动。 有关更多信息,请参阅通用布局widget。

对齐 widgets

您可以控制行或列如何使用mainAxisAlignment和crossAxisAlignment属性来对齐其子项。 对于行(Row)来说,主轴是水平方向,横轴垂直方向。对于列(Column)来说,主轴垂直方向,横轴水平方向。

MainAxisAlignment 和CrossAxisAlignment 类提供了很多控制对齐的常量.

注意: 将图片添加到项目时,需要更新pubspec文件才能访问它们 - 此示例使用Image.asset显示图像。 有关更多信息,请参阅此示例的pubspec.yaml文件, 或在Flutter中添加资源和图像。如果您使用的是网上的图片,则不需要执行此操作,使用Image.network即可。

在以下示例中,3个图像中的每一个都是100像素宽。渲染盒(在这种情况下,整个屏幕)宽度超过300个像素, 因此设置主轴对齐方式为spaceEvenly,它会在每个图像之间,之前和之后均匀分配空闲的水平空间。

appBar: new AppBar(

title: new Text(widget.title),

),

body: new Center(

child: new Row(

mainAxisAlignment: MainAxisAlignment.spaceEvenly,

children: [

new Image.asset('images/pic1.jpg'),

Dart code: main.dartImages: imagesPubspec: pubspec.yaml

列的工作方式与行相同。以下示例显示了一列,包含3个图片,每个图片高100个像素。 渲染盒(在这种情况下,整个屏幕)的高度大于300像素,因此设置主轴对齐方式为spaceEvenly,它会在每个图像之间,上方和下方均匀分配空闲的垂直空间。

appBar: new AppBar(

title: new Text(widget.title),

),

body: new Center(

child: new Column(

mainAxisAlignment: MainAxisAlignment.spaceEvenly,

children: [

new Image.asset('images/pic1.jpg'),

Dart code: main.dartImages: imagesPubspec: pubspec.yaml

调整 widget

也许你想要一个widget占据其兄弟widget两倍的空间。您可以将行或列的子项放置在Expandedwidget中, 以控制沿着主轴方向的widget大小。Expanded widget具有一个flex属性,它是一个整数,用于确定widget的弹性系数,默认弹性系数是1。

例如,要创建一个由三个widget组成的行,其中中间widget的宽度是其他两个widget的两倍,将中间widget的弹性系数设置为2:

appBar: new AppBar(

title: new Text(widget.title),

),

body: new Center(

child: new Row(

crossAxisAlignment: CrossAxisAlignment.center,

children: [

new Expanded(

child: new Image.asset('images/pic1.jpg'),

),

new Expanded(

flex: 2,

child: new Image.asset('images/pic2.jpg'),

),

new Expanded(

a row of 3 images with the middle image twice as wide as the others

Dart code: main.dartImages: imagesPubspec: pubspec.yaml

要修复上一节中的示例:其中一行有3张图片,行对于其渲染框太宽,并且导致右边出现红色条中的问题,可以使用Expanded widget来包装每个widget。 默认情况下,每个widget的弹性系数为1,将行的三分之一分配给每个小部件。

appBar: new AppBar(

title: new Text(widget.title),

),

body: new Center(

child: new Row(

crossAxisAlignment: CrossAxisAlignment.center,

children: [

new Expanded(

child: new Image.asset('images/pic1.jpg'),

),

new Expanded(

child: new Image.asset('images/pic2.jpg'),

),

new Expanded(

聚集 widgets

默认情况下,行或列沿着其主轴会尽可能占用尽可能多的空间,但如果要将孩子紧密聚集在一起,可以将mainAxisSize设置为MainAxisSize.min。 以下示例使用此属性将星形图标聚集在一起(如果不聚集,五张星形图标会分散开)。

class _MyHomePageState extends State {

@override

Widget build(BuildContext context) {

var packedRow = new Row(

mainAxisSize: MainAxisSize.min,

children: [

new Icon(Icons.star, color: Colors.green[500]),

new Icon(Icons.star, color: Colors.green[500]),

new Icon(Icons.star, color: Colors.green[500]),

new Icon(Icons.star, color: Colors.black),

new Icon(Icons.star, color: Colors.black),

],

);

// ...

}

嵌套行和列

布局框架允许您根据需要在行和列内部再嵌套行和列。

该ratings变量创建一个包含5个星形图标和一个文本的行:

class _MyHomePageState extends State {

@override

Widget build(BuildContext context) {

//...

var ratings = new Container(

padding: new EdgeInsets.all(20.0),

child: new Row(

mainAxisAlignment: MainAxisAlignment.spaceEvenly,

children: [

new Row(

mainAxisSize: MainAxisSize.min,

children: [

new Icon(Icons.star, color: Colors.black),

new Icon(Icons.star, color: Colors.black),

new Icon(Icons.star, color: Colors.black),

new Icon(Icons.star, color: Colors.black),

new Icon(Icons.star, color: Colors.black),

],

),

new Text(

'170 Reviews',

style: new TextStyle(

color: Colors.black,

fontWeight: FontWeight.w800,

fontFamily: 'Roboto',

letterSpacing: 0.5,

fontSize: 20.0,

),

),

],

),

);

//...

}

}

提示: 为了最大限度地减少由嵌套严重的布局代码导致的视觉混淆,可以在变量和函数中实现UI的各个部分。

该iconList变量定义了图标行:

class _MyHomePageState extends State {

@override

Widget build(BuildContext context) {

// ...

var descTextStyle = new TextStyle(

color: Colors.black,

fontWeight: FontWeight.w800,

fontFamily: 'Roboto',

letterSpacing: 0.5,

fontSize: 18.0,

height: 2.0,

);

// DefaultTextStyle.merge可以允许您创建一个默认的文本样式,该样式会被其

// 所有的子节点继承

var iconList = DefaultTextStyle.merge(

style: descTextStyle,

child: new Container(

padding: new EdgeInsets.all(20.0),

child: new Row(

mainAxisAlignment: MainAxisAlignment.spaceEvenly,

children: [

new Column(

children: [

new Icon(Icons.kitchen, color: Colors.green[500]),

new Text('PREP:'),

new Text('25 min'),

],

),

new Column(

children: [

new Icon(Icons.timer, color: Colors.green[500]),

new Text('COOK:'),

new Text('1 hr'),

],

),

new Column(

children: [

new Icon(Icons.restaurant, color: Colors.green[500]),

new Text('FEEDS:'),

new Text('4-6'),

],

),

],

),

),

);

// ...

}

}

该leftColumn变量包含评分和图标行,以及描述Pavlova的标题和文字:

class _MyHomePageState extends State {

@override

Widget build(BuildContext context) {

//...

var leftColumn = new Container(

padding: new EdgeInsets.fromLTRB(20.0, 30.0, 20.0, 20.0),

child: new Column(

children: [

titleText,

subTitle,

ratings,

iconList,

],

),

);

//...

}

}

左列放置在容器中以约束其宽度。最后,用整个行(包含左列和图像)放置在一个Card内构建UI:

Pavlova图片来自 Pixabay ,可以在Creative Commons许可下使用。 您可以使用Image.network直接从网上下载显示图片,但对于此示例,图像保存到项目中的图像目录中,添加到pubspec文件, 并使用Images.asset。 有关更多信息,请参阅在Flutter中添加Asserts和图片。

body: new Center(

child: new Container(

margin: new EdgeInsets.fromLTRB(0.0, 40.0, 0.0, 30.0),

height: 600.0,

child: new Card(

child: new Row(

crossAxisAlignment: CrossAxisAlignment.start,

children: [

new Container(

width: 440.0,

child: leftColumn,

),

mainImage,

],

),

),

),

),

Dart code: main.dartImages: imagesPubspec: pubspec.yaml

提示: Pavlova示例在广泛的横屏设备(如平板电脑)上运行最佳。如果您在iOS模拟器中运行此示例, 则可以使用Hardware > Device菜单选择其他设备。对于这个例子,我们推荐iPad Pro。 您可以使用Hardware > Rotate将其方向更改为横向模式 。您还可以使用Window > Scale更改模拟器窗口的大小(不更改逻辑像素的数量)

网站建设开发|APP设计开发|小程序建设开发
下一篇:Flutter 常用布局widgets
上一篇:Flutter 布局方法