Flutter有一个丰富的布局控件库,但我们只学习最常用的一些,目的是使你可以尽快开始开发,而不是按步就班的学习完整的课程。
控件分为两类:控件库(Widgets Library)中的标准控件和质感设计库(Material Library)中的专用控件。任何应用程序都可以使用控件库(Widgets Library),但只有质感设计应用程序可以使用质感设计库(Material Library)。
标准控件
Container(容器)
许多布局可以自由地使用容器来分隔带有填充的控件,或添加边框、边距。您可以通过将整个布局放入容器并更改其背景颜色或图像来更改设备的背景。
下面的布局由2行2列组成,每列包含2个图像(pic1.jpg、pic2.jpg、pic3.jpg、pic4.jpg)。每个图像使用容器来添加一个圆形的灰色边框和边距,包含图像行的列使用容器将背景颜色更改为较浅的灰色。
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
//...
var container = new Container(
decoration: new BoxDecoration(
backgroundColor: Colors.black26,
),
child: new Column(
children: [
new Row(
children: [
new Expanded(
child: new Container(
decoration: new BoxDecoration(
border: new Border.all(width: 10.0, color: Colors.black38),
borderRadius: const BorderRadius.all(const Radius.circular(8.0))
),
margin: const EdgeInsets.all(4.0),
child: new Image.asset('images/pic1.jpg'),
)
),
new Expanded(
child: new Container(
decoration: new BoxDecoration(
border: new Border.all(width: 10.0, color: Colors.black38),
borderRadius: const BorderRadius.all(const Radius.circular(8.0))
),
margin: const EdgeInsets.all(4.0),
child: new Image.asset('images/pic2.jpg'),
)
),
]
),
new Row(
children: [
new Expanded(
child: new Container(
decoration: new BoxDecoration(
border: new Border.all(width: 10.0, color: Colors.black38),
borderRadius: const BorderRadius.all(const Radius.circular(8.0))
),
margin: const EdgeInsets.all(4.0),
child: new Image.asset('images/pic3.jpg'),
)
),
new Expanded(
child: new Container(
decoration: new BoxDecoration(
border: new Border.all(width: 10.0, color: Colors.black38),
borderRadius: const BorderRadius.all(const Radius.circular(8.0))
),
margin: const EdgeInsets.all(4.0),
child: new Image.asset('images/pic4.jpg'),
)
),
]
),
]
)
);
//...
}
}
GridView(网格视图)
使用GridView将控件作为二维列表放置。 GridView提供了两个预制列表,或者您可以构建自己的自定义网格。当GridView检测到其内容太长,无法适应渲染框时,它会自动滚动。
下面的布局使用GridView.extent创建一个最大150像素宽的图块,图像保存名称为pic1.jpg、pic2.jpg … pic30.jpg,List.generate构造函数允许创建一个简单的方法。
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
//...
List<Container> _buildGridTileList(int count) {
return new List<Container>.generate(
count,
(int index) => new Container(child: new Image.asset('images/pic${index+1}.jpg'))
);
}
Widget buildGrid() {
return new GridView.extent(
maxCrossAxisExtent: 150.0,
padding: const EdgeInsets.all(4.0),
mainAxisSpacing: 4.0,
crossAxisSpacing: 4.0,
children: _buildGridTileList(20)
);
}
return new Scaffold(
appBar: new AppBar(
title: new Text(widget.title),
),
body: new Center(
child: buildGrid(),
),
);
//...
}
}
ListView(列表视图)
ListView是一个类列表的控件,当其内容对于其渲染框太长时,它会自动提供滚动。
下面的布局使用ListTiles的业务列表,用分隔线将剧院与餐厅分开。
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
//...
List<Widget> list = <Widget>[
new ListTile(
title: new Text('深圳万达海雅广场店', style: new TextStyle(fontWeight: FontWeight.w500, fontSize: 20.0)),
subtitle: new Text('深圳市宝安区建安一路海雅缤纷城4楼'),
leading: new Icon(
Icons.theaters,
color: Colors.blue[500],
)
),
//...
new Divider(),
new ListTile(
title: new Text('同仁四季音乐主题餐厅(海岸城店)', style: new TextStyle(fontWeight: FontWeight.w500, fontSize: 20.0)),
subtitle: new Text('海岸城保利文化广场2楼保利来觅C6(近地铁后海站E出口)'),
leading: new Icon(
Icons.restaurant,
color: Colors.blue[500],
)
),
//...
];
return new Scaffold(
appBar: new AppBar(
title: new Text(widget.title),
),
body: new Center(
child: new ListView(
children: list,
)
),
);
//...
}
}
Stack(层叠)
使用Stack在基本控件顶部排列控件,通常像图像,控件可以完全或部分地重叠基本控件。
下面的布局使用Stack覆盖一个容器(在半透明黑色背景上显示其文本)在圆形头像顶部。Stack使用alignment属性和FractionalOffsets来偏移文本。
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
//...
var stack = new Stack(
alignment: const FractionalOffset(0.8, 0.8),
children: [
new CircleAvatar(
backgroundImage: new AssetImage('images/pic4.jpg'),
radius: 100.0,
),
new Container(
decoration: new BoxDecoration(
backgroundColor: Colors.black45,
),
child: new Text(
'Hekaiyou',
style: new TextStyle(
fontSize: 20.0,
fontWeight: FontWeight.bold,
color: Colors.white,
)
)
)
]
);
//...
}
}
质感设计控件
Card(卡片)
Card包含相关的信息块,可以由大多数任何控件组成,但经常与ListTile一起使用。Card只有一个子控件,但它的子控件可以是支持多个子控件的列、行、列表、网格或其他控件。默认情况下,Card将其大小缩小为0像素。您可以使用SizedBox限制Card的大小。
在Flutter中,Card具有略微圆角和阴影,给予3D效果。更改Card的elevation属性可以控制阴影效果。例如,将elevation设置为24,可以将Card从表面进一步提升,并使阴影变得更加分散。
下面的布局是一张包含3个ListTile的卡片,并用SizedBox包装大小。分隔符分隔第一个和第二个ListTile。
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
//...
var card = new SizedBox(
height: 210.0,
child: new Card(
child: new Column(
children: [
new ListTile(
title: new Text('北京市复兴路10号', style: new TextStyle(fontWeight: FontWeight.w500)),
subtitle: new Text('北京市,100844'),
leading: new Icon(
Icons.business,
color: Colors.blue[500],
)
),
new Divider(),
new ListTile(
title: new Text('12306', style: new TextStyle(fontWeight: FontWeight.w500)),
leading: new Icon(
Icons.contact_phone,
color: Colors.blue[500],
)
),
new ListTile(
title: new Text('12306gw@china-mor.gov.cn', style: new TextStyle(fontWeight: FontWeight.w500)),
leading: new Icon(
Icons.contact_mail,
color: Colors.blue[500],
)
),
]
)
)
);
//...
}
}
ListTile(列表平铺)
ListTile是质感设计库中专门的行控件,可以轻松创建一行,其中最多包含3行文本和可选的前导和尾随图标。 ListTile最常用于Card或ListView,还可以在别的地方使用。