寻找有关动态构建expandTile列表的一些指导。我有一个从json API动态构建的成功Listview,但找不到构建expandTile的任何示例。我有1个api调用带回顶层,另一个调用每个顶级带回来扩展列表。有人有这方面的例子吗?我找到了静态示例,但不清楚如何使其动态化。
这是我提出的一些代码。我可以看到Tile标题部分,并且可以看到json进入了tile体,但是无法弄清楚如何在正文中获得列表标题的正确名称,我没有尝试将其设置为有效。有什么想法吗?
import 'dart:async';
import 'package:intl/intl.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
//import 'package:shared_preferences/shared_preferences.dart';
import 'package:http/http.dart' as http;
//import 'package:cswauthapp/models.dart';
import 'package:flutter/foundation.dart';
import 'dart:convert';
var jsonCodec = const JsonCodec();
List<Exp> myReasonList;
List myDCList;
int mycount = 0;
void main() {
runApp(new MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'ExpansionTile Test',
home: new MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
void initState() {
super.initState();
_getData();
//_getSpecialty();
}
_getData() async {
var _url = 'http://$baseurl:8080/support/dc/1';
var http = createHttpClient();
var response = await http.get(_url);
var dc = await jsonCodec.decode(response.body);
myDCList = await dc.toList();
print('DC: '+myDCList.toString());
if (mounted) {
setState(() {
//_dataReceived = true;
mycount = myDCList.length;
});
}
}
Future _getChildren(int did) async {
var _url2 = 'http://174.138.61.246:8080/support/dcreasons/$did';
var http = createHttpClient();
var response = await http.get(_url2);
var reasons = await jsonCodec.decode(response.body);
myReasonList = await reasons.toList();
print('REASONS: '+ myReasonList.toString());
return myReasonList;
}
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text('ExpansionTile Test'),
),
body: new ListView.builder(
itemBuilder: _itemBuilder,
itemCount: mycount,
),
);
}
Widget _itemBuilder(BuildContext context, int index) {
Exp exp = getExp(index);
return new ListChild(exp: exp,);
}
Exp getExp(int index) {
return new Exp(
myDCList[index]['dname'],
_getChildren(myDCList[index]['did']),
);
//return new Specialties.fromMap(mylist[index]);
}
}
class Exp {
Exp(this.title, [this.children]);
final String title;
final Future<List<Exp>> children;
}
class ListChild extends StatefulWidget {
ListChild({Key key, this.exp}) : super(key: key);
final Exp exp;
@override
State createState() => new ListChildState();
}
class ListChildState extends State<ListChild> {
//PageStorageKey<ListChildState> _key = new PageStorageKey(ListChild);
@override
Widget build(BuildContext context) {
return new ExpansionTile(
key: new PageStorageKey(ListChild),
title: new Text(widget.exp.title),
children: <Widget>[
new Text(widget.exp.children.title),
],
);
}
}
答案 0 :(得分:12)
反应你评论和编辑问题我冒昧地写了一个工作的例子。随意编辑或评论。我希望,这是你想要实现的目标。
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
void main() {
runApp(new MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'ExpansionTile Test',
home: new MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
Future<http.Response> _responseFuture;
@override
void initState() {
super.initState();
_responseFuture = http.get('http://174.138.61.246:8080/support/dc/1');
}
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text('ExpansionTile Test'),
),
body: new FutureBuilder(
future: _responseFuture,
builder: (BuildContext context, AsyncSnapshot<http.Response> response) {
if (!response.hasData) {
return const Center(
child: const Text('Loading...'),
);
} else if (response.data.statusCode != 200) {
return const Center(
child: const Text('Error loading data'),
);
} else {
List<dynamic> json = JSON.decode(response.data.body);
return new MyExpansionTileList(json);
}
},
),
);
}
}
class MyExpansionTileList extends StatelessWidget {
final List<dynamic> elementList;
MyExpansionTileList(this.elementList);
List<Widget> _getChildren() {
List<Widget> children = [];
elementList.forEach((element) {
children.add(
new MyExpansionTile(element['did'], element['dname']),
);
});
return children;
}
@override
Widget build(BuildContext context) {
return new ListView(
children: _getChildren(),
);
}
}
class MyExpansionTile extends StatefulWidget {
final int did;
final String name;
MyExpansionTile(this.did, this.name);
@override
State createState() => new MyExpansionTileState();
}
class MyExpansionTileState extends State<MyExpansionTile> {
PageStorageKey _key;
Future<http.Response> _responseFuture;
@override
void initState() {
super.initState();
_responseFuture =
http.get('http://174.138.61.246:8080/support/dcreasons/${widget.did}');
}
@override
Widget build(BuildContext context) {
_key = new PageStorageKey('${widget.did}');
return new ExpansionTile(
key: _key,
title: new Text(widget.name),
children: <Widget>[
new FutureBuilder(
future: _responseFuture,
builder:
(BuildContext context, AsyncSnapshot<http.Response> response) {
if (!response.hasData) {
return const Center(
child: const Text('Loading...'),
);
} else if (response.data.statusCode != 200) {
return const Center(
child: const Text('Error loading data'),
);
} else {
List<dynamic> json = JSON.decode(response.data.body);
List<Widget> reasonList = [];
json.forEach((element) {
reasonList.add(new ListTile(
dense: true,
title: new Text(element['reason']),
));
});
return new Column(children: reasonList);
}
},
)
],
);
}
}
答案 1 :(得分:2)
跟随Rainer Wittmann
方法,我对其进行了修改以满足自己的需求,并针对 Cloud Firestore 进行了实现,但我使用futures
代替了streams
。
我的 Cloud Firestore 的基本结构是:
集合项目
名称
集合调查:
解决方案:
class ProjectList extends StatelessWidget {
ProjectList({this.firestore});
final Firestore firestore;
@override
Widget build(BuildContext context) {
return StreamBuilder<QuerySnapshot>(
stream: firestore.collection('projects').snapshots(),
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (!snapshot.hasData) return const Text('Loading...');
//final int projectsCount = snapshot.data.documents.length;
List<DocumentSnapshot> documents = snapshot.data.documents;
return ExpansionTileList(
firestore: firestore,
documents: documents,
);
},
);
}
}
class ExpansionTileList extends StatelessWidget {
final List<DocumentSnapshot> documents;
final Firestore firestore;
ExpansionTileList({this.documents, this.firestore});
List<Widget> _getChildren() {
List<Widget> children = [];
documents.forEach((doc) {
children.add(
ProjectsExpansionTile(
name: doc['name'],
projectKey: doc.documentID,
firestore: firestore,
),
);
});
return children;
}
@override
Widget build(BuildContext context) {
return ListView(
children: _getChildren(),
);
}
}
class ProjectsExpansionTile extends StatelessWidget {
ProjectsExpansionTile({this.projectKey, this.name, this.firestore});
final String projectKey;
final String name;
final Firestore firestore;
@override
Widget build(BuildContext context) {
PageStorageKey _projectKey = PageStorageKey('$projectKey');
return ExpansionTile(
key: _projectKey,
title: Text(
name,
style: TextStyle(fontSize: 28.0),
),
children: <Widget>[
StreamBuilder(
stream: firestore
.collection('projects')
.document(projectKey)
.collection('surveys')
.snapshots(),
builder:
(BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (!snapshot.hasData) return const Text('Loading...');
//final int surveysCount = snapshot.data.documents.length;
List<DocumentSnapshot> documents = snapshot.data.documents;
List<Widget> surveysList = [];
documents.forEach((doc) {
PageStorageKey _surveyKey =
new PageStorageKey('${doc.documentID}');
surveysList.add(ListTile(
key: _surveyKey,
title: Text(doc['surveyName']),
));
});
return Column(children: surveysList);
})
],
);
}
}
希望这对那些在云存储库中的嵌套集合中丢失的人有所帮助。
编码愉快!
答案 2 :(得分:1)
我认为解决这个问题的最佳方法是使用FutureBuilder(也许看看this answer)。我将为ExpansionTile标题实现一个FutureBuilder,为每个ExpansionTile主体实现第二个 上面链接的答案中的示例可以很好地适应您的用例。
如果您需要更多帮助,请大声喊叫,我会尝试为您实施一个示例。