Flutter 数据表布局
Flutter DataTable Layout
我在带有 FutureBuilder
的 Flutter 中遇到 DataTable
的一些布局问题,我调用了 API,它自然会这样显示:
可以理解,因为我正在构建一个 table 的列表,它将 return 多个 table 返回。我只想将行映射为列表,列应该保持不变,就像这样:
因此,First Name
、Last Name
和 Delete
列始终相同,它只是映射出 table 行单元格,如上面第二张图片所示。
是否可以像我的示例中那样使用 FutureBuilder
通过 DataTable
实现此目的?
我试过在 DataRow
单元格中使用 future builder,因为 DataCell
的每个 child 都是一个 Widget,但它看起来真的很糟糕,我不确定这是正确的做法...
代码如下:
API调用:
import 'dart:async';
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'models/names.dart';
Future<List<NameData>> fetchNames() async {
List<NameData> names = List();
final response = await http.get('https://jsonplaceholder.typicode.com/posts');
if (response.statusCode == 200) {
// If the server did return a 200 OK response,
// then parse the JSON.
var namesJson = jsonDecode(response.body);
print(response.body);
for (int i = 0; i < namesJson.length; i++) {
names.add(NameData.fromJson(jsonDecode(response.body)[i]));
}
return names;
} else {
// If the server did not return a 200 OK response,
// then throw an exception.
throw Exception('Failed to load names');
}
}
姓名模型:
import 'package:flutter/foundation.dart';
import 'dart:core';
class NameData extends ChangeNotifier {
final int id;
final int userId;
final String title;
final String body;
NameData({
this.id,
this.userId,
this.title,
this.body,
});
factory NameData.fromJson(Map<String, dynamic> json) {
return NameData(
id: json["id"],
userId: json["userId"],
title: json["title"],
body: json["body"],
);
}
}
以及带有数据的名称列表 table:
import 'package:flutter/material.dart';
import 'models/names.dart';
import 'services/name_api.dart';
class NameList extends StatefulWidget {
@override
_NameList createState() => _NameList();
}
class _NameList extends State<NameList> {
Future<List<NameData>> futureNames;
@override
void initState() {
super.initState();
futureNames = fetchNames();
}
@override
Widget build(BuildContext context) {
return Column(
children: [
SizedBox(
height: 600,
child: FutureBuilder<List<NameData>>(
future: futureNames,
builder: (context, snapshot) {
if (snapshot.hasData) {
return ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (context, index) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
SizedBox(
height: 12.0,
),
Container(
decoration: BoxDecoration(
color: Colors.grey[300],
borderRadius: BorderRadius.all(
Radius.circular(12.0),
),
),
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: DataTable(
columns: <DataColumn>[
DataColumn(
label: Text(
'First Name',
style:
TextStyle(fontStyle: FontStyle.italic),
),
),
DataColumn(
label: Text(
'Last Name',
style:
TextStyle(fontStyle: FontStyle.italic),
),
),
DataColumn(
label: Text(
'Delete',
style:
TextStyle(fontStyle: FontStyle.italic),
),
),
],
rows: <DataRow>[
DataRow(
cells: <DataCell>[
DataCell(
Text('${snapshot.data[index].id}')),
DataCell(
Text('${snapshot.data[index].userId}')),
DataCell(Icon(Icons.delete)),
],
),
],
),
),
),
SizedBox(
height: 16.0,
),
],
);
},
);
} else if (snapshot.hasError) {
return Text("${snapshot.error}");
}
return Container();
},
),
),
],
);
}
}
提前感谢您的宝贵时间和帮助。
第 1 步:
Future<List<NameData>> generateList() async {
final response =
await http.get('https://jsonplaceholder.typicode.com/posts');
var list = await json.decode(response.body).cast<Map<String, dynamic>>();
return await list.map<NameData>((json) => NameData.fromJson(json)).toList();
}
第 2 步:
@override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
appBar: AppBar(
title: Text('DataTable'),
),
body: Container(
child: FutureBuilder<List<NameData>>(
future: generateList(),
builder: (context, snapShot) {
if (snapShot.hasData) {
return SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: DataTable(
columns: <DataColumn>[
DataColumn(
label: Text(
'First Name',
style: TextStyle(fontStyle: FontStyle.italic),
),
),
DataColumn(
label: Text(
'Last Name',
style: TextStyle(fontStyle: FontStyle.italic),
),
),
DataColumn(
label: Text(
'Delete',
style: TextStyle(fontStyle: FontStyle.italic),
),
),
],
rows: snapShot.data.map<DataRow>((e) {
return DataRow(
cells: <DataCell>[
DataCell(Text('${e.id}')),
DataCell(Text('${e.userId}')),
DataCell(Icon(Icons.delete)),
],
);
}).toList(),
),
);
}else{
return CircularProgressIndicator();
}
},
)),
),
);
}
我在带有 FutureBuilder
的 Flutter 中遇到 DataTable
的一些布局问题,我调用了 API,它自然会这样显示:
可以理解,因为我正在构建一个 table 的列表,它将 return 多个 table 返回。我只想将行映射为列表,列应该保持不变,就像这样:
因此,First Name
、Last Name
和 Delete
列始终相同,它只是映射出 table 行单元格,如上面第二张图片所示。
是否可以像我的示例中那样使用 FutureBuilder
通过 DataTable
实现此目的?
我试过在 DataRow
单元格中使用 future builder,因为 DataCell
的每个 child 都是一个 Widget,但它看起来真的很糟糕,我不确定这是正确的做法...
代码如下:
API调用:
import 'dart:async';
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'models/names.dart';
Future<List<NameData>> fetchNames() async {
List<NameData> names = List();
final response = await http.get('https://jsonplaceholder.typicode.com/posts');
if (response.statusCode == 200) {
// If the server did return a 200 OK response,
// then parse the JSON.
var namesJson = jsonDecode(response.body);
print(response.body);
for (int i = 0; i < namesJson.length; i++) {
names.add(NameData.fromJson(jsonDecode(response.body)[i]));
}
return names;
} else {
// If the server did not return a 200 OK response,
// then throw an exception.
throw Exception('Failed to load names');
}
}
姓名模型:
import 'package:flutter/foundation.dart';
import 'dart:core';
class NameData extends ChangeNotifier {
final int id;
final int userId;
final String title;
final String body;
NameData({
this.id,
this.userId,
this.title,
this.body,
});
factory NameData.fromJson(Map<String, dynamic> json) {
return NameData(
id: json["id"],
userId: json["userId"],
title: json["title"],
body: json["body"],
);
}
}
以及带有数据的名称列表 table:
import 'package:flutter/material.dart';
import 'models/names.dart';
import 'services/name_api.dart';
class NameList extends StatefulWidget {
@override
_NameList createState() => _NameList();
}
class _NameList extends State<NameList> {
Future<List<NameData>> futureNames;
@override
void initState() {
super.initState();
futureNames = fetchNames();
}
@override
Widget build(BuildContext context) {
return Column(
children: [
SizedBox(
height: 600,
child: FutureBuilder<List<NameData>>(
future: futureNames,
builder: (context, snapshot) {
if (snapshot.hasData) {
return ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (context, index) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
SizedBox(
height: 12.0,
),
Container(
decoration: BoxDecoration(
color: Colors.grey[300],
borderRadius: BorderRadius.all(
Radius.circular(12.0),
),
),
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: DataTable(
columns: <DataColumn>[
DataColumn(
label: Text(
'First Name',
style:
TextStyle(fontStyle: FontStyle.italic),
),
),
DataColumn(
label: Text(
'Last Name',
style:
TextStyle(fontStyle: FontStyle.italic),
),
),
DataColumn(
label: Text(
'Delete',
style:
TextStyle(fontStyle: FontStyle.italic),
),
),
],
rows: <DataRow>[
DataRow(
cells: <DataCell>[
DataCell(
Text('${snapshot.data[index].id}')),
DataCell(
Text('${snapshot.data[index].userId}')),
DataCell(Icon(Icons.delete)),
],
),
],
),
),
),
SizedBox(
height: 16.0,
),
],
);
},
);
} else if (snapshot.hasError) {
return Text("${snapshot.error}");
}
return Container();
},
),
),
],
);
}
}
提前感谢您的宝贵时间和帮助。
第 1 步:
Future<List<NameData>> generateList() async {
final response =
await http.get('https://jsonplaceholder.typicode.com/posts');
var list = await json.decode(response.body).cast<Map<String, dynamic>>();
return await list.map<NameData>((json) => NameData.fromJson(json)).toList();
}
第 2 步:
@override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
appBar: AppBar(
title: Text('DataTable'),
),
body: Container(
child: FutureBuilder<List<NameData>>(
future: generateList(),
builder: (context, snapShot) {
if (snapShot.hasData) {
return SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: DataTable(
columns: <DataColumn>[
DataColumn(
label: Text(
'First Name',
style: TextStyle(fontStyle: FontStyle.italic),
),
),
DataColumn(
label: Text(
'Last Name',
style: TextStyle(fontStyle: FontStyle.italic),
),
),
DataColumn(
label: Text(
'Delete',
style: TextStyle(fontStyle: FontStyle.italic),
),
),
],
rows: snapShot.data.map<DataRow>((e) {
return DataRow(
cells: <DataCell>[
DataCell(Text('${e.id}')),
DataCell(Text('${e.userId}')),
DataCell(Icon(Icons.delete)),
],
);
}).toList(),
),
);
}else{
return CircularProgressIndicator();
}
},
)),
),
);
}