Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.3k views
in Technique[技术] by (71.8m points)

flutter dynamic expansionTile

Looking for some guidance on building expansionTile list dynamically. I have a successful Listview built dynamically from json API, but can not find any examples on building the expansionTile. I have 1 api call that brings back the top level and another call for each top level to bring back the expansion list. Anyone have an example of this? I have found the static example but is not clear how to how to make it dynamic.

Here is some code I came up with. I can see the Tile title portion and can see the json come in for the tile body, but can not figure out how to get the correct name of the list title in the body, nothing I try to set it to works. Any ideas?

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),
      ],
    );
  }
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Reacting to you comment and edit of the question I took the liberty to write a working example. Feel free to edit or comment. I hope, this is what you wanted to achieve.

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);
            }
          },
        )
      ],
    );
  }
}

Screenshot of the app


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

2.1m questions

2.1m answers

60 comments

57.0k users

...