前言
工作中,都会有这样子的需求,就是一张表格的行列都是动态生产的。博主最近也遇到了这个需求,一直研究了一个星期,总算写出来了。现在在这里和大家分享一下。
准备工具
这套课程是采用VScode进行开发的。当前在此之前请准备好Flutter开发环境,我这里就不进行讲解了。
实现界面
下面表格中的行列都是动态生产的
实例代码分析
这里实例的特点是: UI和数据进行分离,使用到了状态管理。
数据处理
创建一个table.dart中有一个TableProvide类,对从后端提到的数据进行处理
import 'package:flutter/material.dart';
import '../service/service_method.dart';
class TableProvide with ChangeNotifier{
List<String> keyList=[]; //后端json中的key值
List contextList=[]; //后端json内容
List titleList=[]; //后端数据中的标题信息
List contextNum=[]; //统计有几行数据
List openState=[]; //判断+号的状态
int count;
dynamic openNum;
getTableInfo() async{
await request('getCommodity').then((val){
contextList=val;
keyList=['number','price'];
titleList=['操作','数量','价格'];
count=contextList.length;
for(int i=0;i<count;i++){
contextNum.add(i);
openState.add({'symbol':'+'});
}
});
}
//编写一个改变符号函数,一开始是+号,之后点击之后,对应的 + 号会变成 - 号; - 号会编程 + 号
changeOpenState(){
for(int i=0;i<count;i++){
openState[i]['symbol']='+';
}
openState[openNum]['symbol']='-';
notifyListeners();
}
}
表格处理
我们这里使用DataTable这个组件
行列处理
DataTable(
// 标题区域
columns: Provide.value<TableProvide>(context).titleList.map((data)=>DataColumn(
label: Text(data)
)).toList(),
//内容区域
rows: Provide.value<TableProvide>(context).contextNum.map((data)=>
DataRow(
cells: _getCells(Provide.value<TableProvide>(context).keyList,data,Provide.value<TableProvide>(context).contextList),
),
).toList()
);
List<DataCell> _getCells(List<String> keyList,data,contextList) {
List<DataCell> cells = [];
cells.add(
//因为前面的操作符是通过状态管理进行控制的,所以我们要单独的插入到cells
DataCell(
Text('${Provide.value<TableProvide>(context).openState[data]['symbol']}'),
onTap: (){
Provide.value<TableProvide>(context).openNum=data;
Provide.value<TableProvide>(context).changeOpenState();
}
));
//利用key的数量,动态生产几列
keyList.forEach((key) {
cells.add(DataCell(
Text('${contextList[data][key]}'),
));
});
return cells;
}
请求接口和调用表格函数
child: FutureBuilder(
future: _getInfo(context), //调用请求方法
builder: (context,snapshot){
if(snapshot.hasData){ //判断是否有返回值
return Center(
child: new ListView(
children: <Widget>[
Provide<TableProvide>(
builder: (context,child,val){
return Container(
child:tableContext(),
);
}),
],
),
);
}else{
return Center(
child:Text('加载中')
);
}
},
),
页面完整代码
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:provide/provide.dart';
import '../provide/table.dart';
class CommodityPage extends StatefulWidget {
CommodityPage({Key key}) : super(key: key);
_CommodityPageState createState() => _CommodityPageState();
}
class _CommodityPageState extends State<CommodityPage> {
@override
Widget build(BuildContext context) {
ScreenUtil.instance=ScreenUtil(width: 750, height: 1334)..init(context);
return Scaffold(
appBar: AppBar(title: Text('测试'),),
body:Container(
child: FutureBuilder(
future: _getInfo(context), //调用请求方法
builder: (context,snapshot){
if(snapshot.hasData){ //判断是否有返回值
return Center(
child: new ListView(
children: <Widget>[
Provide<TableProvide>(
builder: (context,child,val){
return Container(
child:tableContext(),
);
}),
],
),
);
}else{
return Center(
child:Text('加载中')
);
}
},
),
),
);
}
Widget tableContext(){
return new DataTable(
columns: Provide.value<TableProvide>(context).titleList.map((data)=>DataColumn(
label: Text(data)
)).toList(),
rows: Provide.value<TableProvide>(context).contextNum.map((data)=>
DataRow(
cells: _getCells(Provide.value<TableProvide>(context).keyList,data,Provide.value<TableProvide>(context).contextList),
),
).toList()
);
}
List<DataCell> _getCells(List<String> keyList,data,contextList) {
List<DataCell> cells = [];
cells.add(
DataCell(
Text('${Provide.value<TableProvide>(context).openState[data]['symbol']}'),
onTap: (){
Provide.value<TableProvide>(context).openNum=data;
Provide.value<TableProvide>(context).changeOpenState();
}
));
keyList.forEach((key) {
cells.add(DataCell(
Text('${contextList[data][key]}'),
));
});
return cells;
}
Future _getInfo(BuildContext context) async{
await Provide.value<TableProvide>(context).getTableInfo();
return '加载完毕';
}
}
大家模拟一下数据,就可以进行测试了,希望可以帮助到大家