Scaffold是基于Material Design可视化布局的结构,也是Flutter提供的标准化布局容器。其结构体如下:
Scaffold(
appBar: //顶部导航栏
body: //界面内容
floatingActionButton: //右下角按钮
bottomNavigationBar://底部菜单
drawer://侧滑菜单
)
AppBar是顶部导航栏,有leading、actions、title属性。其结构体如下:
AppBar(
leading: //左边区域,一般作为返回按钮、侧滑菜单按钮和图标等
title: //中间区域,如果appbar展示不下,会优先挤压title,一般用于界面标题
actions: //右边区域,一般用作搜索按钮
)
Row和Column属性线性布局,Row是行多子元素组件,Column是列多子元素组件。它们有如下属性:
属性 | 说明 |
---|---|
crossAxisAlignment | 与组件方向垂直轴的对齐方式 |
mainAxisAlignment | 主轴方向对齐方式 |
textDirection | 布局的顺序默认是从左到右(从上到下) |
mainAxisSize | max表示尽可能多的占用水平方向位置,min相反 |
children | 子组件数组 |
Row(
// mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.end,
mainAxisSize: MainAxisSize.max,
textDirection: TextDirection.ltr,
children: <Widget>[
Container(
width: 100,
height: 100,
color: Colors.yellow,
alignment: Alignment.center,
child: ListView(
itemExtent: 30,
scrollDirection: Axis.vertical,
children: const [
Text('text1'),
Text('text2'),
Text('text3'),
Text('text4'),
Text('text5'),
],
),
),
Container(
width: 100,
height: 80,
color: Colors.blue,
alignment: Alignment.center,
child: ListView.builder(
itemExtent: 30,
itemCount: 20,
itemBuilder: (context, position) {
if (position == 2) {
return const Text('我是二货');
}
return Text('我有$position 个冰棍');
}),
),
Container(
width: 100,
height: 100,
color: Colors.green,
alignment: Alignment.center,
child: ListView.separated(
itemBuilder: (context, position) {
if (position == 2) {
return const Text('我是二货');
}
return Text('我有$position 个冰棍');
},
separatorBuilder: (context, position) {
return const Divider(height: 1.0, color: Colors.grey);
},
itemCount: 20),
),
Container(
width: 100,
height: 100,
color: Colors.white,
alignment: Alignment.center,
child: ListView.custom(
scrollDirection: Axis.vertical,
childrenDelegate: SliverChildBuilderDelegate(
(BuildContext context, int position) {
return Container(
height: 20.0,
alignment: Alignment.center,
color: position % 2 == 1 ? Colors.green : Colors.yellow,
child: Text('$position'),
);
}, childCount: 50),
),
)
])
Flutter中的ListView与Android中ListView类似,都是线性列表组件。ListView常用的创建方式有3种,如下:
(1)ListView
ListView(
itemExtent:20,//子组件的高度
children:<widget>[
Text('item0'),
Text('item1'),
Text('item2'),
Text('item3'),
....
]
)
(2)ListView.builder
ListView.builder(
itemExtent:20,
itemCount:5,
itemBuilder:(context,position){
return Text('第$position个条目’);
}
)
(3)ListView.separated
ListView.separated(
itemBuilder: (context, position) {
if (position == 2) {
return const Text('我是二货');
}
return Text('我有$position 个冰棍');
},
separatorBuilder: (context, position) {
return const Divider(height: 1.0, color: Colors.grey);
},
itemCount: 20)
CustomMultiChildLayout是一个多节点、自定义布局组件,通过提供的delegate可以实现控制节点的位置以及尺寸。代码如下:
class _MyLayoutDelegate extends MultiChildLayoutDelegate {
static const String layoutTitle='layout_bar';
static const String body = 'body';
void performLayout(Size size) {
Size layoutSize = layoutChild(layoutTitle,
BoxConstraints(maxHeight: size.height, maxWidth: size.width));
positionChild(layoutTitle, const Offset(0, 0));
layoutChild(body, BoxConstraints.tight(Size(size.width, size.height)));
positionChild(body, Offset(layoutSize.width, layoutSize.height));
}
bool shouldRelayout(covariant MultiChildLayoutDelegate oldDelegate) {
return false;
}
}
Scaffold(
appBar: AppBar(
title: const Text("ListWheelScrollView Example"),
leading: const Text('leading'),
actions: [
IconButton(
onPressed: () => {
print('add'),
},
icon: const Icon(Icons.add)),
IconButton(
onPressed: () => {
print('delete'),
},
icon: const Icon(Icons.delete)),
],
),
body: CustomMultiChildLayout(
delegate: _MyLayoutDelegate(),
children: [LayoutId(id: _MyLayoutDelegate.layoutTitle, child: Text('这是title')),
LayoutId(id: _MyLayoutDelegate.body, child: Text('是body'))],
),
)
IndexedStack继承Stack,通过index属性可以直接切换它的子组件。开发中,我们可以用IndexedStack切换界面,但是IndexedStack切换是没有任何动画的。
IndexedStack(
index: 1,
alignment: Alignment.center,
children: const [
Text('第一个Text'),
Text('第二个Text'),
Text('第三个Text'),
],
)
Wrap是自适应布局组件,Wrap组件可以替代Row组件,当一行显示不全时,会自动进行换行处理。
Wrap(
spacing: 10,
runSpacing: 5,
children: const [
Text('苹果',style: TextStyle(fontSize: 50,color: Colors.blue),),
Text('西瓜',style: TextStyle(fontSize: 50,color: Colors.green),),
Text('香蕉',style: TextStyle(fontSize: 50,color: Colors.red),),
Text('荔枝',style: TextStyle(fontSize: 50,color: Colors.yellow),),
Text('葡萄',style: TextStyle(fontSize: 50,color: Colors.orange),),
Text('哈密瓜',style: TextStyle(fontSize: 50,color: Colors.purpleAccent),),
],
)