一、老套路,先看样式
左图是我业务中的样式,右图是下方源码展示样式(复制可直接运行,无额外组件引入)
二、讲解
1.涉及组件
首先,没有一个单一组件来实现这个效果
实现这个效果涉及以下组件:
AppBar:顶端栏,一个最基本的软件
Text:文本
Container:布局组件
CustomScrollView:自定义滚动效果组件,比如列表和网格组件都可以包含在其中
SliverGrid:网格视图组件
SliverList:列表控件
InkWell:效果控件,可以给其他widget包裹一个点击效果
ListTile:标题组件,通常填充listview
2.首先设置下标题样式
getItem是我们的主内容
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: new IconButton(
icon: new Icon(Icons.arrow_back,
color: Colors.black38),
onPressed: () {
print('返回按钮');
},
),
title: Text('换一批效果'),
centerTitle: true,
elevation: 0.0,
actions: <Widget>[
IconButton(
icon: Icon(Icons.save),
onPressed: () {},
),
],
), //这个是顶部tab样式,如果不需要可以去掉
body: Container(
child: getItem(),
));
}
3.换一批点击效果
我们给换一批样式设置一个点击效果
当点击的时候,判断当前内容是否满足18条(一屏展示的数目)
如果不满足,说明最后一页了,重置页码为1
如果满足,说明当前数据>=18,后面可能还有数据,页码+1
然后请求数据,_getData()是封装的一个请求数据函数
SliverList(
delegate: SliverChildListDelegate([
ListTile(
onTap: () {
int Temp = page + 1;
if (_list.length < 18) {
Temp = 1;
}
setState(() {
page = Temp;
});
_getData();
},
title: Text(
'挑选一个图标吧',
style: TextStyle(color: Colors.black, fontSize: 12),
),
trailing: Text('换一批',
style: TextStyle(color: Colors.black54, fontSize: 10)),
),
]),
),
4.网格内容其实就是一个SliverGrid,切换数据后,进行了部分页面重新渲染
三、源码(可直接运行调试)
import 'package:flutter/material.dart';
class AddHabit extends StatefulWidget {
String hid = '';
AddHabit({this.hid});
@override
_AddHabitState createState() => _AddHabitState();
}
class _AddHabitState extends State<AddHabit> {
var _icon = '';
double leftPadding = 15.0;
List _list = [ { 'id': 1, 'image': 'https://daybili.oss-cn-beijing.aliyuncs.com/image/202008/liaotian.png' } ];
int page = 1;
@override
void initState() {
super.initState();
this._getData();
}
//获取数据, 为了测试方便, 我处理为了静态数据
_getData() async {
//_list数据应该是通过网络请求获得
print(_list);
setState(() {
_list = _list;
});
}
//build初始化
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: new IconButton(
icon: new Icon(Icons.arrow_back, color: Colors.black38),
onPressed: () {
print('返回按钮');
},
),
title: Text('换一批效果'),
centerTitle: true,
elevation: 0.0,
actions: <Widget>[
IconButton(
icon: Icon(Icons.save),
onPressed: () {},
),
],
), //这个是顶部tab样式,如果不需要可以去掉
body: Container(
child: getItem(),
));
}
//核心内容
Widget getItem() {
return CustomScrollView(slivers: <Widget>[
SliverList(
delegate: SliverChildListDelegate([
ListTile(
onTap: () {
int Temp = page + 1;
if (_list.length < 18) {
Temp = 1;
}
setState(() {
page = Temp;
});
_getData();
},
title: Text(
'挑选一个图标吧',
style: TextStyle(color: Colors.black, fontSize: 12),
),
trailing: Text('换一批',
style: TextStyle(color: Colors.black54, fontSize: 10)),
),
]),
),
SliverGrid(
//padding: EdgeInsets.zero,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 6, crossAxisSpacing: 5, mainAxisSpacing: 3),
delegate: SliverChildBuilderDelegate((BuildContext context, int index) {
return habitIcon(_list[index]);
}, childCount: _list.length),
),
]);
}
//某个图标样式
Widget habitIcon(item) {
return InkWell(
onTap: () {
setState(() {
_icon = item['id'];
});
},
child: Container(
height: 100,
width: 100,
color: item['id'] == _icon ? Colors.white : Colors.black12,
alignment: Alignment.center,
child: Image.network(
item['image'],
width: 30,
height: 30,
),
),
);
}
}