官方文档——一篇文章弄懂Flutter中的布局
  Tj2IEF7IlkTw 2023年11月02日 106 0


来自Flutter中文资源主页https://flutter.cn/

Flutter 中的布局

要点

  • Widgets 是用于构建 UI 的类。
  • Widgets 可以用于布局和展示 UI 元素。
  • 通过组合简单的 widgets 来构建复杂的 widgets。
    Compose simple widgets to build complex widgets.

Flutter 布局的核心机制是 widgets。在 Flutter 中,几乎所有东西都是 widget —— 甚至布局模型都是 widgets。你在 Flutter 应用程序中看到的图像,图标和文本都是 widgets。此外不能直接看到的也是 widgets,例如用来排列、限制和对齐可见 widgets 的行、列和网格。

你可以通过组合 widgets 来构建更复杂的 widgets 来创建布局。比如,下面第一个截图上有 3 个图标,每个图标下面都有一个标签:

官方文档——一篇文章弄懂Flutter中的布局_Image

 

官方文档——一篇文章弄懂Flutter中的布局_App_02

第二个截图显示了可视布局,可以看到有一排三列,其中每列包含一个图标和一个标签。

 提示

本教程中的大多数截图都是将 ​​debugPaintSizeEnabled​​​ 设置为 true 以后的效果,因此你可以看到可视布局。更多信息可以查看文档中的 ​​可视化调试​​​,它是 ​​调试 Flutter 应用​​ 中的一节。

以下是这个 UI 的 widget 树形图:

官方文档——一篇文章弄懂Flutter中的布局_Text_03

图上大部分应该和你预想的一样,但你可能会疑惑 containers(图上粉色显示的)是什么。 [Container][] 是一个 widget,允许你自定义其子 widget。举几个例子,如果要添加 padding、margin、边框或背景颜色,你就可以用上 ​​Container​​ 了。

在这个例子中,每个 ​​Text​​​ widget 都被放在一个 ​​Container​​​ 以添加 padding。整个 ​​Row​​​ 也被放在一个 ​​Container​​ 中,以便添加 padding。

这个例子其余部分的 UI 由属性控制。通过 ​​Icon​​​ 的 ​​color​​​ 属性来设置它的颜色,通过 ​​Text.style​​ 属性来设置文字的字体、颜色、字重等等。列和行有一些属性可以让你指定子项垂直或水平的对齐方式以及子项应占用的空间大小。

布局 widget

如何在 Flutter 中布局单个 widget?本节将介绍如何创建和显示单个 widget。本节还包括一个简单的 Hello World app 的完整代码。

在 Flutter 中,只需几步就可以在屏幕上显示文本、图标或图像。

In Flutter, it takes only a few steps to put text, an icon, or an image on the screen.

1. 选择一个布局 widget

根据你想要对齐或限制可见 widget 的方式从各种 ​​layout widgets​​ 中进行选择,因为这些特性通常会传递它所给包含的 widget。

本例使用将其内容水平和垂直居中的 ​​Center​​。

2. 创建一个可见 widget

举个例子,创建一个 ​​Text​​ widget:

content_copy

Text('Hello World'),


创建一个 ​​Image​​ widget:

content_copy

Image.asset( 'images/lake.jpg',
fit: BoxFit.cover,
),


创建一个 ​​Icon​​ widget:

content_copy

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


3. 将可见 widget 添加到布局 widget

所有布局 widgets 都具有以下任一项:

  • 一个 ​​child​​ 属性,如果它们只包含一个子项 —— 例如 ​​Center​​ 和 ​​Container​
  • 一个 ​​children​​ 属性,如果它们包含多个子项 —— 例如 ​​Row​​、​​Column​​、​​ListView​​ 和 ​​Stack​

将 ​​Text​​​ widget 添加进 ​​Center​​ widget:

content_copy

Center( child: Text('Hello World'),
),


4. 将布局 widget 添加到页面

一个 Flutter app 本身就是一个 widget,大多数 widgets 都有一个 ​​build()​​​ 方法,在 app 的 ​​build()​​ 方法中实例化和返回一个 widget 会让它显示出来。

对于 ​​Material​​​ app,你可以使用 ​​Scaffold​​​ widget,它提供默认的 banner 背景颜色,还有用于添加抽屉、提示条和底部列表弹窗的 API。你可以将 ​​Center​​​ widget 直接添加到主页 ​​body​​ 的属性中。

lib/main.dart (MyApp)

content_copy

class MyApp extends StatelessWidget {  @override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter layout demo',
home: Scaffold(
appBar: AppBar(
title: Text('Flutter layout demo'),
),
body: Center(
child: Text('Hello World'),
),
),
);
}
}


 提示

​Material 库​​​ 实现了一些遵循 ​​Material Design​​​ 原则的 widgets。在设计 UI 时,你可以只使用标准 ​​widgets 库​​ 中的 widgets,也可以使用 Material library 中的 widgets。你可以混合来自两个库的 widgets,可以自定义现有 widgets,也可以构建自己的一组自定义 widgets。

非 Material apps

对于非 Material app,你可以将 ​​Center​​​ widget 添加到 app 的 ​​build()​​ 方法里:

lib/main.dart (MyApp)
content_copy

class MyApp extends StatelessWidget { @override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(color: Colors.white),
child: Center(
child: Text(
'Hello World',
textDirection: TextDirection.ltr,
style: TextStyle(
fontSize: 32,
color: Colors.black87,
),
),
),
);
}
}


默认情况下,非 Material app 不包含 ​​AppBar​​、标题和背景颜色。如果你希望在非 Material app 中使用这些功能,则必须自己构建它们。以上 app 将背景颜色更改为白色,将文本更改为深灰色来模拟一个 Material app。

完成! 启动这个 app,你应该能看到 Hello World

App 源码:

官方文档——一篇文章弄懂Flutter中的布局_Text_04


横向或纵向布局多个 widgets

最常见的布局模式之一是垂直或水平 widgets。你可以使用 Row widget 水平排列 widgets,使用 Column widget 垂直排列 widgets。

要点

  • ​Row​​​ 和 ​​Column​​ 是两种最常用的布局模式。
  • ​Row​​​ and ​​Column​​ each take a list of child widgets.

content_copy

`Row` 和 `Column` 每个都有一个子 widgets 列表。
  • 一个子 widget 本身可以是 ​​Row​​、​​Column​​ 或其他复杂 widget。
  • 可以指定 ​​Row​​ 或 ​​Column​​ 如何在垂直和水平方向上对齐其子项。
  • 可以拉伸或限制特定的子 widgets。
  • 可以指定子 widgets 如何占用 ​​Row​​ 或 ​​Column​​ 的可用空间。

要在 Flutter 中创建行或列,可以将子 widgets 列表添加到 ​​Row​​​ 或 ​​Column​​ widget 中。反过来,每个子项本身可以是一行或一列,依此类推。以下示例演示了如何在行或列中嵌套行或列。

这个布局被组织为 ​​Row​​。这一行包含两个子项:左侧的列和右侧的图像:

官方文档——一篇文章弄懂Flutter中的布局_App_05

左侧列的 widget 树嵌套着行和列。

官方文档——一篇文章弄懂Flutter中的布局_App_06

你将在 ​​嵌套行和列​​ 中实现蛋糕介绍示例的一些布局代码。

 提示

Row 和 Column 是水平和垂直布局的基本原始 widgets —— 这些低级 widgets 允许最大程度的自定义。 Flutter 还提供专门的、更高级别的 widgets,可能可以直接满足需求。例如,和 Row 相比你可能更喜欢 ​​ListTile​​​,这是一个易于使用的 widget,有属性可以设置头尾图标,最多可以显示 3 行文本;和 Column 相比你也可能更喜欢 ​​ListView​​​,这是一种类似于列的布局,但如果其内容太长导致可用空间不够容纳时会自动滚动。更多信息可以查看 ​​通用布局 widgets​​。

对齐 widgets

你可以使用 ​​mainAxisAlignment​​​ 和 ​​crossAxisAlignment​​ 属性控制行或列如何对齐其子项。对于一行来说,主轴水平延伸,交叉轴垂直延伸。对于一列来说,主轴垂直延伸,交叉轴水平延伸。

官方文档——一篇文章弄懂Flutter中的布局_Text_07

 

官方文档——一篇文章弄懂Flutter中的布局_Image_08

​MainAxisAlignment​​​ 和 ​​CrossAxisAlignment​​ 这两个类提供了很多用于控制对齐的常量。

 提示

当你将图像添加到项目中时,你需要更新 ​​pubspec.yaml​​​ 文件来访问它们 —— 本例使用 ​​Image.asset​​​ 来显示图像。更多信息可以查看本例的 ​​pubspec.yaml 文件​​​,或文档:​​添加资源和图片​​​。如果你正在使用 ​​Image.network​​ 引用在线图像,则不需要这些操作。

在以下示例中,3 个图像每个都是是 100 像素宽。渲染框(在本例中是整个屏幕)宽度超过 300 像素,因此设置主轴对齐方式为 ​​spaceEvenly​​ 会将空余空间在每个图像之间、之前和之后均匀地划分。

content_copy


Row(  mainAxisAlignment: MainAxisAlignment.spaceEvenly,  children: [
Image.asset('images/pic1.jpg'),
Image.asset('images/pic2.jpg'),
Image.asset('images/pic3.jpg'),
],
);

官方文档——一篇文章弄懂Flutter中的布局_Image_09

App 源码: ​​row_column​

列的工作方式与行的工作方式相同。以下示例展示了包含 3 个图像的列,每个图像的高度为 100 像素。渲染框(在本例中是整个屏幕)高度超过 300 像素,因此设置主轴对齐方式为 ​​spaceEvenly​​ 会将空余空间在每个图像之间、之上和之下均匀地划分。

content_copy

Column(  mainAxisAlignment: MainAxisAlignment.spaceEvenly,  children: [
Image.asset('images/pic1.jpg'),
Image.asset('images/pic2.jpg'),
Image.asset('images/pic3.jpg'),
],
);


App 源码: ​​row_column​

官方文档——一篇文章弄懂Flutter中的布局_Image_10

调整 widgets 大小

当某个布局太大而超出屏幕时,受影响的边缘会出现黄色和黑色条纹图案。这里有一个行太宽的 ​​例子​​:

官方文档——一篇文章弄懂Flutter中的布局_Text_11

通过使用 ​​Expanded​​​ widget,可以调整 widgets 的大小以适合行或列。要修复上一个图像行对其渲染框来说太宽的示例,可以用 ​​Expanded​​ widget 把每个图像包起来。

content_copy


Row(  crossAxisAlignment: CrossAxisAlignment.center,  children: [
Expanded(
child: Image.asset('images/pic1.jpg'),
),
Expanded(
child: Image.asset('images/pic2.jpg'),
),
Expanded(
child: Image.asset('images/pic3.jpg'),
),
],
);


官方文档——一篇文章弄懂Flutter中的布局_App_12

App 源码: ​​sizing​

也许你想要一个 widget 占用的空间是兄弟项的两倍。为了达到这个效果,可以使用 ​​Expanded​​​ widget 的 ​​flex​​ 属性,这是一个用来确定 widget 的弹性系数的整数。默认的弹性系数为 1,以下代码将中间图像的弹性系数设置为 2:

content_copy

Row(  crossAxisAlignment: CrossAxisAlignment.center,  children: [
Expanded(
child: Image.asset('images/pic1.jpg'),
),
Expanded(
flex: 2,
child: Image.asset('images/pic2.jpg'),
),
Expanded(
child: Image.asset('images/pic3.jpg'),
),
],
);


官方文档——一篇文章弄懂Flutter中的布局_App_13

App 源码: ​​sizing​

组合 widgets

默认情况下,行或列沿其主轴会占用尽可能多的空间,但如果要将子项紧密组合在一起,请将其 ​​mainAxisSize​​​ 设置为 ​​MainAxisSize.min​​。以下示例使用此属性将星形图标组合在一起。

content_copy

Row(  mainAxisSize: MainAxisSize.min,  children: [
Icon(Icons.star, color: Colors.green[500]),
Icon(Icons.star, color: Colors.green[500]),
Icon(Icons.star, color: Colors.green[500]),
Icon(Icons.star, color: Colors.black),
Icon(Icons.star, color: Colors.black),
],
)

官方文档——一篇文章弄懂Flutter中的布局_App_14

App 源码: ​​pavlova​

嵌套行和列

布局框架允许你根据需要在行和列内嵌套行和列。让我们看看以下布局的概述部分的代码:

官方文档——一篇文章弄懂Flutter中的布局_Text_15

概述的部分实现为两行,评级一行包含五颗星和评论的数量,图标一行包含由图标与文本组成的三列。

以下是评级行的 widget 树形图:

官方文档——一篇文章弄懂Flutter中的布局_Image_16

​ratings​​ 变量创建了一个行,其中包含较小的由 5 个星形图标和文本组成的一行:

content_copy

var stars = Row(  mainAxisSize: MainAxisSize.min,  children: [
Icon(Icons.star, color: Colors.green[500]),
Icon(Icons.star, color: Colors.green[500]),
Icon(Icons.star, color: Colors.green[500]),
Icon(Icons.star, color: Colors.black),
Icon(Icons.star, color: Colors.black),
],
);

final ratings = Container(
padding: EdgeInsets.all(20),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
stars,
Text(
'170 Reviews',
style: TextStyle(
color: Colors.black,
fontWeight: FontWeight.w800,
fontFamily: 'Roboto',
letterSpacing: 0.5,
fontSize: 20,
),
),
],
),
);


 小提示

为了最大限度地减少高度嵌套的布局代码可能导致的视觉混乱,可以在变量和函数中实现 UI 的各个部分。

评级行下方的图标行包含 3 列,每列包含一个图标和两行文本,你可以在其 widget 树中看到:

官方文档——一篇文章弄懂Flutter中的布局_App_17

​iconList​​ 变量定义了图标行:

content_copy


final descTextStyle = TextStyle(  color: Colors.black,  fontWeight: FontWeight.w800,
fontFamily: 'Roboto',
letterSpacing: 0.5,
fontSize: 18,
height: 2,
);

// DefaultTextStyle.merge() allows you to create a default text
// style that is inherited by its child and all subsequent children.
final iconList = DefaultTextStyle.merge(
style: descTextStyle,
child: Container(
padding: EdgeInsets.all(20),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Column(
children: [
Icon(Icons.kitchen, color: Colors.green[500]),
Text('PREP:'),
Text('25 min'),
],
),
Column(
children: [
Icon(Icons.timer, color: Colors.green[500]),
Text('COOK:'),
Text('1 hr'),
],
),
Column(
children: [
Icon(Icons.restaurant, color: Colors.green[500]),
Text('FEEDS:'),
Text('4-6'),
],
),
],
),
),
);


​leftColumn​​ 变量包含评级和图标行,以及蛋糕介绍的标题和文本:

content_copy


final leftColumn = Container(  padding: EdgeInsets.fromLTRB(20, 30, 20, 20),  child: Column(
children: [
titleText,
subTitle,
ratings,
iconList,
],
),
);


左列放置在 ​​Container​​​ 中以限制其宽度。最后,UI 由 ​​Card​​ 内的整行(包含左列和图像)构成。

​蛋糕图片​​​ 来自 ​​Pixabay​​​ 网站。你可以使用 ​​Image.network()​​​ 从网络上引用图像,但是在本例图像将保存到项目中的一个图像目录中,添加到 ​​pubspec 文件​​​,并使用 ​​Images.asset()​​​ 访问。更多信息可以查看文档中关于 ​​添加资源和图片​​ 这一章。

content_copy


body: Center(  child: Container(    margin: EdgeInsets.fromLTRB(0, 40, 0, 30),
height: 600,
child: Card(
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
width: 440,
child: leftColumn,
),
mainImage,
],
),
),
),
),

 小提示

蛋糕介绍的例子在宽屏设备(如平板电脑)上横向运行效果最佳。如果在 iOS 模拟器中运行这个示例,可以使用 Hardware > Device 菜单选择不同的设备。在本例中,我们推荐 iPad Pro。你可以使用 Hardware > Rotate 将其方向更改为横向模式。你还可以使用 Window > Scale 更改模拟器窗口的大小(不改变逻辑像素的数量)。

App 源码: ​​pavlova​


通用布局 widgets

Flutter 有一个丰富的布局 widget 仓库,里面有很多经常会用到的布局 widget。目的是为了让你更快的上手,而不是被一个完整的列表吓跑。关于其他有用的 widget 的信息,可以参考 ​​Widget 目录​​​,或者使用 ​​API 参考文档​​ 中的搜索框。而且,API 文档中的 widget 页面中经常会给出一些关于相似的 widget 哪个会更适合你的建议。

下面的 widget 会分为两类:​​widgets 库​​​ 中的标准 widgets 和 ​​Material 库​​ 中的 widgets。任何 app 都可以使用 widget 库,但是 Material 库中的组件只能在 Material app 中使用。

标准 widgets

  • ​Container​​:向 widget 增加 padding、margins、borders、background color 或者其他的“装饰”。
  • ​GridView​​:将 widget 展示为一个可滚动的网格。
  • ​ListView​​:将 widget 展示为一个可滚动的列表。
  • ​Stack​​:将 widget 覆盖在另一个的上面。

Material widgets

  • ​Card​​:将相关信息整理到一个有圆角和阴影的盒子中。
  • ​ListTile​​:将最多三行的文本、可选的导语以及后面的图标组织在一行中。

Container

许多布局都可以随意的用 [Container][],它可以将使用了 padding 或者增加了 borders/margins 的 widget 分开。你可以通过将整个布局放到一个 ​​Container​​ 中,并且改变它的背景色或者图片,来改变设备的背景。

摘要 (Container)

  • 增加 padding、margins、borders
  • 改变背景色或者图片
  • 只包含一个子 widget,但是这个子 widget 可以是行、列或者是 widget 树的根 widget

官方文档——一篇文章弄懂Flutter中的布局_Text_18

示例 (Container)

这个布局包含一个有两行的列,每行有两张图片。 ​​Container​​ 用来将列的背景色变为浅灰色。

content_copy


Widget _buildImageColumn() => Container(      decoration: BoxDecoration(        color: Colors.black26,
),
child: Column(
children: [
_buildImageRow(1),
_buildImageRow(3),
],
),
);


官方文档——一篇文章弄懂Flutter中的布局_Image_19

​Container​​ 还用来为每个图片添加圆角和外边距:

content_copy


Widget _buildDecoratedImage(int imageIndex) => Expanded(      child: Container(        decoration: BoxDecoration(
border: Border.all(width: 10, color: Colors.black38),
borderRadius: const BorderRadius.all(const Radius.circular(8)),
),
margin: const EdgeInsets.all(4),
child: Image.asset('images/pic$imageIndex.jpg'),
),
);

Widget _buildImageRow(int imageIndex) => Row(
children: [
_buildDecoratedImage(imageIndex),
_buildDecoratedImage(imageIndex + 1),
],
);


你可以在 ​​布局构建教程​​​ 和 [Flutter Gallery][] 中可以发现更多关于 ​​Container​​ 的例子。

App 源码: ​​container​


GridView

使用 ​​GridView​​​ 将 widget 作为二维列表展示。 ​​GridView​​​ 提供两个预制的列表,或者你可以自定义网格。当 ​​GridView​​ 检测到内容太长而无法适应渲染盒时,它就会自动支持滚动。

摘要 (GridView)

  • 在网格中使用 widget
  • 当列的内容超出渲染容器的时候,它会自动支持滚动。
  • 创建自定义的网格,或者使用下面提供的网格的其中一个:
  • ​GridView.count​​ 允许你制定列的数量
  • ​GridView.extent​​ 允许你制定单元格的最大宽度

 提示 When displaying a two-dimensional list where it’s important which row and column a cell occupies (for example, it’s the entry in the “calorie” column for the “avocado” row), use ​​Table​​​ or ​​DataTable​​.

当展示二维列表中的单元格所在的行和列的位置很重要的(例如,它是 “calorie” 行和 “avocado” 列的条目)的时候,使用 ​​Table​​​ 或者 ​​DataTable​​.。

示例 (GridView)

官方文档——一篇文章弄懂Flutter中的布局_Text_20

使用 ​​GridView.extent​​ 创建一个最大宽度为 150 像素的网格。

App 源码: ​​grid_and_list​

官方文档——一篇文章弄懂Flutter中的布局_App_21

使用 ​​GridView.count​​​ 创建一个网格,它在竖屏模式下有两行,在横屏模式下有三行。可以通过为每个 ​​GridTile​​​ 设置 ​​footer​​ 属性来创建标题。

Dart 代码: ​​Flutter Gallery​​​ 中的 ​​grid_list_demo.dart​

content_copy

Widget _buildGrid() => GridView.extent(    maxCrossAxisExtent: 150,    padding: const EdgeInsets.all(4),
mainAxisSpacing: 4,
crossAxisSpacing: 4,
children: _buildGridTileList(30));

// The images are saved with names pic0.jpg, pic1.jpg...pic29.jpg.
// The List.generate() constructor allows an easy way to create
// a list when objects have a predictable naming pattern.
List<Container> _buildGridTileList(int count) => List.generate(
count, (i) => Container(child: Image.asset('images/pic$i.jpg')));



ListView

​ListView​​,一个和列很相似的 widget,当内容长于自己的渲染盒时,就会自动支持滚动。

摘要 (ListView)

  • 一个用来组织盒子中列表的专用 ​​Column​
  • 可以水平或者垂直布局
  • 当监测到空间不足时,会提供滚动
  • 比 ​​Column​​ 的配置少,使用更容易,并且支持滚动

示例 (ListView)

官方文档——一篇文章弄懂Flutter中的布局_Text_22

使用 ​​ListView​​​ 的业务列表,它使用了多个 ​​ListTile​​​。​​Divider​​ 将餐厅从剧院中分隔开。

App 源码: ​​grid_and_list​

官方文档——一篇文章弄懂Flutter中的布局_App_23

使用 ​​ListView​​​ 展示特定颜色系列 ​​Material Design 调色板​​​ 中的 ​​Colors​​。

Dart 代码: ​​Flutter Gallery​​​ 中的 ​​colors_demo.dart​

content_copy


Widget _buildList() => ListView(      children: [        _tile('CineArts at the Empire', '85 W Portal Ave', Icons.theaters),
_tile('The Castro Theater', '429 Castro St', Icons.theaters),
_tile('Alamo Drafthouse Cinema', '2550 Mission St', Icons.theaters),
_tile('Roxie Theater', '3117 16th St', Icons.theaters),
_tile('United Artists Stonestown Twin', '501 Buckingham Way',
Icons.theaters),
_tile('AMC Metreon 16', '135 4th St #3000', Icons.theaters),
Divider(),
_tile('K\'s Kitchen', '757 Monterey Blvd', Icons.restaurant),
_tile('Emmy\'s Restaurant', '1923 Ocean Ave', Icons.restaurant),
_tile(
'Chaiya Thai Restaurant', '272 Claremont Blvd', Icons.restaurant),
_tile('La Ciccia', '291 30th St', Icons.restaurant),
],
);

ListTile _tile(String title, String subtitle, IconData icon) => ListTile(
title: Text(title,
style: TextStyle(
fontWeight: FontWeight.w500,
fontSize: 20,
)),
subtitle: Text(subtitle),
leading: Icon(
icon,
color: Colors.blue[500],
),
);


Stack

可以使用 ​​Stack​​ 在基础 widget(通常是图片)上排列 widget, widget 可以完全或者部分覆盖基础 widget。

摘要 (Stack)

  • 用于覆盖另一个 widget
  • 子列表中的第一个 widget 是基础 widget;后面的子项覆盖在基础 widget 的顶部
  • ​Stack​​ 的内容是无法滚动的
  • 你可以剪切掉超出渲染框的子项

示例 (Stack)

官方文档——一篇文章弄懂Flutter中的布局_Image_24

在 ​​CircleAvatar​​​ 的上面使用 ​​Stack​​​ 覆盖 ​​Container​​​ (在透明的黑色背景上展示它的 ​​Text​​​)。 ​​Stack​​​ 使用 ​​alignment​​​ 属性和 ​​Alignment​​ 让文本偏移。

App 源码: ​​card_and_stack​

官方文档——一篇文章弄懂Flutter中的布局_Text_25

使用 ​​Stack​​ 将渐变叠加到图片的顶部,渐变可以将工具栏的图标和图片区分开来。

Dart 代码: ​​Flutter Gallery​​​ 中的​​contacts_demo.dart​

content_copy


Widget _buildStack() => Stack(    alignment: const Alignment(0.6, 0.6),    children: [
CircleAvatar(
backgroundImage: AssetImage('images/pic.jpg'),
radius: 100,
),
Container(
decoration: BoxDecoration(
color: Colors.black45,
),
child: Text(
'Mia B',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
),
],
);



Card

​Material 库​​​ 中的 ​​Card​​​ 包含相关有价值的信息,几乎可以由任何 widget 组成,但是通常和 ​​ListTile​​​ 一起使用。 ​​Card​​​ 只有一个子项,这个子项可以是列、行、列表、网格或者其他支持多个子项的 widget。默认情况下,​​Card​​​ 的大小是 0x0 像素。你可以使用 ​​SizedBox​​ 控制 card 的大小。

在 Flutter 中,​​Card​​​ 有轻微的圆角和阴影来使它具有 3D 效果。改变 ​​Card​​​ 的 ​​elevation​​​ 属性可以控制阴影效果。例如,把 elevation 设置为 24,可以从视觉上更多的把 ​​Card​​​ 抬离表面,使阴影变得更加分散。关于支持的 elevation 的值的列表,可以查看 ​​Material guidelines​​​ 中的 ​​Elevation​​。使用不支持的值则会使阴影无效。

摘要 (Card)

  • 实现一个 ​​Material card​
  • 用于呈现相关有价值的信息
  • 接收单个子项,但是子项可以是 ​​Row​​、​​Column​​ 或者其他可以包含列表子项的 widget
  • 显示圆角和阴影
  • ​Card​​ 的内容无法滚动
  • 来自 ​​Material 库​

示例 (Card)

官方文档——一篇文章弄懂Flutter中的布局_App_26

包含 3 个 ListTile 的 ​​Card​​​,并且通过被 ​​SizedBox​​​ 包住来调整大小。 ​​Divider​​​ 分隔了第一个和第二个 ​​ListTiles​​。

App 源码: ​​card_and_stack​

官方文档——一篇文章弄懂Flutter中的布局_Text_27

包含图片和文本的 ​​Card​​。

Dart 代码: ​​Flutter Gallery​​​ 中的 ​​cards_demo.dart​

content_copy

Widget _buildCard() => SizedBox(    height: 210,    child: Card(
child: Column(
children: [
ListTile(
title: Text('1625 Main Street',
style: TextStyle(fontWeight: FontWeight.w500)),
subtitle: Text('My City, CA 99984'),
leading: Icon(
Icons.restaurant_menu,
color: Colors.blue[500],
),
),
Divider(),
ListTile(
title: Text('
style: TextStyle(fontWeight: FontWeight.w500)),
leading: Icon(
Icons.contact_phone,
color: Colors.blue[500],
),
),
ListTile(
title: Text
leading: Icon(
Icons.contact_mail,
color: Colors.blue[500],
),
),
],
),
),
);



ListTile

​ListTile​​​ 是 ​​Material 库​​​ 中专用的行 widget,它可以很轻松的创建一个包含三行文本以及可选的行前和行尾图标的行。 ​​ListTile​​​在 ​​Card​​​ 或者 ​​ListView​​ 中最常用,但是也可以在别处使用。

摘要 (ListTile)

  • 一个可以包含最多 3 行文本和可选的图标的专用的行
  • 比 ​​Row​​ 更少的配置,更容易使用
  • 来自 ​​Material 库​

示例 (ListTile)

官方文档——一篇文章弄懂Flutter中的布局_App_26

包含 3 个 ​​ListTiles​​​ 的 ​​Card​​。

App 源码: ​​card_and_stack​

官方文档——一篇文章弄懂Flutter中的布局_Image_29

使用 ​​ListTile​​ 列出 3 个下拉按钮类型。

Dart 代码: ​​Flutter Gallery​​​ 中的 ​​buttons_demo.dart​


Constraints

To fully understand Flutter’s layout system, you need to learn how Flutter positions and sizes the components in a layout. For more information, see ​​Understanding constraints​​.

视频

下面的视频是 ​​Flutter in Focus​​ 系列的一部分,解释了 Stateless 和 Stateful 的 widget。

​Flutter in Focus​


​每周 widget 系列​​ 的每一集都会关注一个 widget。其中会包含布局 widget。

​Flutter Widget of the Week playlist​

其他资源

当写布局代码时,下面的资源可能会帮助到你。


【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月08日 0

暂无评论

推荐阅读
  sX9JkgY3DY86   2023年11月13日   43   0   0 idesedImage
  sX9JkgY3DY86   2023年11月13日   18   0   0 分割线ideText
  sX9JkgY3DY86   2023年11月13日   41   0   0 ideTextsed
  sX9JkgY3DY86   2023年11月13日   24   0   0 StackText点击事件
  sX9JkgY3DY86   2023年11月13日   25   0   0 ideTextList
  sX9JkgY3DY86   2023年11月13日   35   0   0 ci控件Text
  sX9JkgY3DY86   2023年11月13日   23   0   0 ideTextflutter
  sX9JkgY3DY86   2023年11月13日   37   0   0 Textsed
Tj2IEF7IlkTw