下面的 widget 分为两类:widgets library中的标准 widget 和 Material Components library 中的专用 widget。任何应用程序都可以使用 widgets library 中的 widget,但只有 Material 应用程序可以使用 Material Components library。
标准 Widgets
Container
添加 padding,margins,borders,background color,或添加其它装饰。

return Scaffold (
backgroundColor: Colors.blue, // 背景色
appBar: AppBar(
title: Text('Startup Name Generator'),
),
body: Container(
decoration: BoxDecoration( // 边框
border: Border.all(width: 10.0, color: Colors.red), // 红色 10px
borderRadius: const BorderRadius.all(const Radius.circular(8.0)), // 圆角
),
margin: const EdgeInsets.all(14.0), // 外边距
padding: const EdgeInsets.all(16.0), // 内边距
child: Image.asset('images/lake.jpg'),
),
);

GridView
可滚动网格布局。它提供了两种 Grid:
GridView.extent 可指定项的最大像素宽度
class WidgetScaffold extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold (
backgroundColor: Colors.blue, // 背景色
appBar: AppBar(
title: Text('Startup Name Generator'),
),
body: Center(child: buildGrid(),)
);
}
}
Widget buildGrid() {
// GridView.extent
return GridView.extent(
maxCrossAxisExtent: 150, // 指定最大宽度
padding: const EdgeInsets.all(4.0),
mainAxisSpacing: 4.0,
crossAxisSpacing: 4.0,
children: _buildGridTileList(30)); // 通过 children 提供子项
}
List<Container> _buildGridTileList(int count) {
return List<Container>.generate(
count,
(int index) =>
Container(child: Image.asset('images/lake.jpg')));
}

改变最大宽度为 maxCrossAxisExtent: 350
变成

可见是根据这个最大宽度值自动计算来确定列数。
GridView.count 可指定列数
Widget buildGrid(BuildContext context) {
// 判断屏幕方向
final Orientation orientation = MediaQuery.of(context).orientation;
return GridView.count(
// 竖屏为 2 列,横屏为 3 列
crossAxisCount: (orientation == Orientation.portrait) ? 2 : 3,
mainAxisSpacing: 4.0,
crossAxisSpacing: 4.0,
padding: const EdgeInsets.all(4.0),
childAspectRatio: (orientation == Orientation.portrait) ? 1.0 : 1.3,
children: _buildGridTileList(30));
}
竖向两列:

旋转屏幕横向三列:

ListView
自动滚动的列表
class WidgetScaffold extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold (
appBar: AppBar(
title: Text('Startup Name Generator'),
),
// ListView 参数是一个 List
body: ListView(
children: _buildGridTileList(30),
)
);
}
}
List<ListTile> _buildGridTileList(int count) {
return List<ListTile>.generate(
count,
(int index) {
return ListTile(
title: Text('A $index',
style: TextStyle(fontWeight: FontWeight.w500, fontSize: 20.0)),
subtitle: Text('sub $index'),
);
}
);
}

Stack
将 widget 重叠在另一个 widget 之上。
class WidgetScaffold extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold (
appBar: AppBar(
title: Text('Startup Name Generator'),
),
body: stack
);
}
}
var stack = Stack(
alignment: const Alignment(0.6, 0.6),
children: [ // children 中的内容堆叠在一起
CircleAvatar( // 一个圆形图片
backgroundImage: AssetImage('images/lake.jpg'),
radius: 100.0,
),
Container(
decoration: BoxDecoration(
color: Colors.black45,
),
child: Text(
'Mia B',
style: TextStyle(
fontSize: 20.0,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
),
],
);

图片没显示出来。
Material Components
Card
具有圆角和阴影的 3D 效果,和 Android 的 CardView 有点相似。更改 elevation
属性控制投影效果。
只允许有一个 child,但这个 child 可以是其它复杂的 widget。
ListTile
是一个行级 widget。将最多三行文字,可选的行前和行尾的图标排成一行。在 Card 和 ListView 中最常用。
class WidgetScaffold extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold (
appBar: AppBar(
title: Text('Startup Name Generator'),
),
body: card
);
}
}
var card = SizedBox(
height: 140.0,
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('title'),
subtitle: Text('subtitle'),
leading: Icon( // 前面的 icon
Icons.contact_mail,
color: Colors.blue[500],
),
trailing:new Icon( // 后面的 icon
Icons.contact_phone,
color: Colors.blue[500],
),
),
],
),
),
);

网友评论