在 Flutter 中动态显示数据表布局中的 JSON 数据
Posted
技术标签:
【中文标题】在 Flutter 中动态显示数据表布局中的 JSON 数据【英文标题】:Dynamically display JSON data in data table layout in flutter 【发布时间】:2021-04-27 13:46:41 【问题描述】:我正在 flutter 中创建一个动态数据表视图,其中列标题和行值是动态添加的。数据是一个 Json 响应,标题是一个字符串数组,要在行中显示的数据也是一个字符串数组。目标是在表格视图中显示数据,而不需要任何硬编码值。 这就是我尝试显示数据的方式。
return ListView.builder(
shrinkWrap: true,
scrollDirection: Axis.vertical,
itemCount: snapshot.data.dataList.length,
itemBuilder: (BuildContext context, int index)
return SingleChildScrollView(
child: DataTable(
columns: (snapshot.data.headerList[index] as List).map((item) =>
DataColumn(
label:(
List.generate(item.length,(index)
return Text(item[index].toString());
)
)
)).toList(),
rows: (snapshot.data.dataList[index].dataList as List).map((item) =>
DataRow(
cells:<DataCell>[
DataCell(
List.generate(item.length,(index)
return Text(item[index].toString());
)
)
])).toList(),
),
这是 JSON 响应
"DayEnd":
"ColumnWidths": "40´168´96´96´108´156",
"Headers": "SL.>´Customer< ´Balance Qty>´Amount>´Oldest / Recent ",
"FieldSeparator": "´",
"DataList": [
"Data": "1. ´ABD ´14 / 14.60´11,090´313 / 313",
"NextLevelZoomData": [
"Element": "eg7P27fbW/GmCr"
,
"Element": "AAA=="
],
"NextLevelZoomType": 2
,
"Data": "2. ´LATA´16´7,921´20 / 9",
"NextLevelZoomData": [
"Element": "MT63z0m7piukmtJZqdZ"
,
"Element": "QT/2zE/AAA="
],
"NextLevelZoomType": 2
,
"Data": "3. ´ANAND´11´915´426 / 426",
"NextLevelZoomData": [
"Element": "AAA="
],
"NextLevelZoomType": 2
,
"Data": "4. ´Asts´1´1,010´27 / 27",
"NextLevelZoomData": [
"Element": "w/VbTHwKgQAAA=="
],
"NextLevelZoomType": 2
,
上面的响应给出了一个字符串数据Headers
,由一个特殊字符“`”分隔,每个字符必须显示在每个列标题中,以便转换为数组。同样的数据也是如此。 columnWidth 中提到了必须为每个数据维护的列宽
同样,数据的对齐方式如 if "SL.>" then ">" 它必须是右对齐的。
我不确定这是否是获取它的正确方法,这会出错
The argument type 'List<Text>' can't be assigned to the parameter type 'Widget'.
任何以更好的方式接近的想法将不胜感激。
【问题讨论】:
如果可能,请添加您的 json 响应 @ShubhamNarkhede 添加了 json 响应 【参考方案1】:第 1 步:
[
"DayEnd": [
"ColumnWidths": "40´168´96´96´108´156",
"Headers": "SL.>´Customer< ´Balance Qty>´Amount>´Oldest / Recent ",
"FieldSeparator": "´",
"DataList": [
"Data": "1. ´ABD ´14 / 14.60´11,090´313 / 313",
"NextLevelZoomData": [
"Element": "eg7P27fbW/GmCr"
,
"Element": "AAA=="
],
"NextLevelZoomType": 2
]
]
]
第 2 步:
class TableModel
TableModel(this.headerData, this.rowData);
List<String> headerData;
List<List<String>> rowData;
factory TableModel.fromJson(Map<String, dynamic> json)
return TableModel(
json['DayEnd'][0]["Headers"].split('´').toList(),
buildRowData(json),
);
List<List<String>> buildRowData(Map<String, dynamic> json)
List<List<String>> rowDataCollection = [];
json['DayEnd'][0]["DataList"].forEach((rows)
rowDataCollection.add(rows['Data'].split('´').toList());
);
return rowDataCollection;
第 3 步:
Future<void> generateList() async
String responseBody = await rootBundle.loadString("assets/data.json");
var list = await json.decode(responseBody).cast<Map<String, dynamic>>();
return await list
.map<TableModel>((json) => TableModel.fromJson(json))
.toList();
@override
Widget build(BuildContext context)
return SafeArea(
child: Scaffold(
appBar: AppBar(
title: Text('DataTable'),
),
body: FutureBuilder(
future: generateList(),
builder: (context, snapShot)
if (snapShot.data == null ||
snapShot.connectionState == ConnectionState.waiting ||
snapShot.hasError ||
snapShot.data.length == 0)
return Container(
child: Center(child: CircularProgressIndicator()),
);
else
return ListView.builder(
shrinkWrap: true,
scrollDirection: Axis.vertical,
itemCount: snapShot.data.length,
itemBuilder: (BuildContext context, int index)
final TableModel table = snapShot.data[index];
return SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: DataTable(
columns: table.headerData.map<DataColumn>((e)
var columnName = e;
TextAlign align;
if (columnName.contains('<'))
align = TextAlign.start;
columnName = columnName.replaceAll('<', '');
else if (columnName.contains('>'))
align = TextAlign.end;
columnName = columnName.replaceAll('>', '');
else
align = TextAlign.center;
return DataColumn(
label: Text(
columnName,
textAlign: align,
));
).toList(),
rows: table.rowData.map<DataRow>((e)
return DataRow(
cells: e
.map<DataCell>((e) => DataCell(Text(e)))
.toList());
).toList(),
),
);
);
,
)));
【讨论】:
谢谢你的灵魂。这真的很有帮助。通过一些修改,我能够实现结果。但是出现的一个问题是所有列的标题都重复了。我有什么问题吗 您能否再分享一些结构化虚拟 json 数据的示例,这将有助于我理解......如何提取数据以及哪个小部件适合该数据。 嗨@android_id我已经修改了第2步。请查看 请分享图片,我会努力整理的 让我们continue this discussion in chat.【参考方案2】:使用 createTable() & 给它列表 & 对象必须有 .tojson() 方法
import 'package:flutter/material.dart';
// This class takes any list that its elements have .toJson method and return every list element as a table row
class TableController
static Widget createTable(List list)
List<TableRow> rows = [];
rows.add(_createTableHeader(list[0].toJson().keys));
for (var item in list)
rows.add(TableRow(
children: _createTableBody(item.toJson().values),
));
return Padding(
padding: const EdgeInsets.all(8.0),
child: Table(border: TableBorder.all(), children: rows),
);
static TableRow _createTableHeader(Iterable<String> keys)
List<Widget> elements = [];
for (String key in keys)
elements.add(Padding(
padding: const EdgeInsets.all(4.0),
child: Text(key.toString(), overflow: TextOverflow.ellipsis),
));
return TableRow(
children: elements,
);
static List<Widget> _createTableBody(Iterable values)
List<Widget> elements = [];
for (var value in values)
elements.add(Padding(
padding: const EdgeInsets.all(4.0),
child: Text(value.toString(), overflow: TextOverflow.ellipsis),
));
return elements;
像这样使用它:
class Employee
Employee(
this.id,
this.name,
this.email,
);
int id;
String name;
String email;
Map<String, dynamic> toJson() =>
"id": id,
"name": name,
"email": email,
;
final Employee emp = Employee(id: 1, name: 'name 1');
final Employee emp1 = Employee(id: 2, name: 'name 2');
final Employee emp2 = Employee(id: 3, name: 'name 3');
final Employee emp3 = Employee(id: 4, name: 'name 4');
final List<Employee> emps = [emp, emp2, emp1];
class TablePage extends StatelessWidget
@override
Widget build(BuildContext context)
return Scaffold(
body: Center(child: TableController.createTable(emps)),
);
输出:
【讨论】:
【参考方案3】:您正在尝试将 List 设置为具有 Widget 类型的属性:DataColumn 中的标签和 DataCell 中的子级。 List 不是 Widget 的子类型。这里可能需要 ListView。
【讨论】:
以上是关于在 Flutter 中动态显示数据表布局中的 JSON 数据的主要内容,如果未能解决你的问题,请参考以下文章