一、老套路,先看样式
图一是我业务中的样式,图二是下方源码展示样式(复制可直接运行,无额外组件引入)
二、讲解
1.结构拆分
首先,页面是个滚动列表,所以一定需要一个listview来容纳
然后每一个item,有个标题,比如精选
标题下方是一个流式布局,可自动切换行,用到了flutter的wrap组件
结构清晰后,无非就三段代码
2.首界面和数据加载
list是我们要循环的列表,这个列表是一级分类的数据
然后里面还有个topic字段,是二级分类的列表数据
也就是说这个_list字段是二维数组感慨念
if (_list.isEmpty) {
return Text('加载中....');
} else {
return ListView.builder(
itemBuilder: (context, index) {
return getItem(_list[index]);
},
itemCount: _list.length,
);
}
复制代码
3.每一个item的设置
这里通过column来设置,一个组件就是标题,第二个组件就是wrap流式布局
4.wrap流式布局
我们重要来说这个
Wrap可以为子控件进行水平或者垂直方向布局,且当空间用完时,Wrap会自动换行,也是常说的流式布局。
Wrap(
alignment: WrapAlignment.spaceBetween,
spacing: 10,
children: List.generate(item['topic'].length, (i) {
return _childList(item['topic'][i]);
}
),
)
复制代码
direction
属性控制布局方向,默认为水平方向,设置方向为垂直代码如下:
Wrap(
direction: Axis.vertical,
...
)
复制代码
alignment
属性控制主轴对齐方式,crossAxisAlignment
属性控制交叉轴对齐方式,对齐方式只对有剩余空间的行或者列起作用,例如水平方向上正好填充完整,则不管设置主轴对齐方式为什么,看上去的效果都是铺满。
Wrap(
alignment: WrapAlignment.spaceBetween,
...
)
复制代码
spacing
和runSpacing
属性控制Wrap主轴方向和交叉轴方向子控件之间的间隙
verticalDirection
属性表示Wrap交叉轴方向上子控件的方向,取值范围是up
(从上到下)和down
(从下到上)
三、源码(可直接运行调试)
import 'package:flutter/material.dart';
class Mytest extends StatefulWidget {
Mytest({Key key}) : super(key: key);
_MytestState createState() => _MytestState();
}
class _MytestState extends State<Mytest> {
List _list = [];
@override
void initState() {
super.initState();
this._getData();
}
_getData() async {
//这里后面要换成数据请求
List ret = [
{
'title': '精选',
'topic': [
{
'title': '标题',
'icon':
'http://n1.c.imoxiu.com/85b4d9acec1b23abf499387f4fe4dd979483f46a/100'
}
]
}
];
setState(() {
this._list = ret;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(body: getHome(),appBar: AppBar(title: Text('流式布局'),elevation: 0.0,),);
}
Widget getHome() {
if (_list.isEmpty) {
return Text('加载中....');
} else {
return ListView.builder(
itemBuilder: (context, index) {
return getItem(_list[index]);
},
itemCount: _list.length,
);
}
}
Widget getItem(item) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Padding(
padding: const EdgeInsets.fromLTRB(20, 10, 0, 10),
child: Text(item['title'], style: TextStyle(color: Colors.black38)),
),
Padding(
padding: const EdgeInsets.fromLTRB(20, 10, 0, 10),
child: item['topic'].length > 0
? Wrap(
alignment: WrapAlignment.spaceBetween,
spacing: 10,
children: List.generate(item['topic'].length, (i) {
return _childList(item['topic'][i]);
}),
)
: Container(),
),
],
);
}
Widget _childList(topicItem) {
return GestureDetector(
onTap: () {},
child: Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Container(
height: 20,
child: Image.network(
topicItem['icon'],
fit: BoxFit.cover,
),
),
Padding(
padding: const EdgeInsets.fromLTRB(2, 0, 0, 0),
child: Text(
topicItem['title'],
style: TextStyle(fontSize: 12, color: Colors.black),
),
)
],
),
);
}
}
复制代码
支持更新中……
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END