flutterexpandablelistview

Flutter ExpansionPanel closes immediately after clicking


I'fetching data from my API and want to display the data in a ExpansionPanelList. Now I have the problem, that every time when i want to fold out a Panel it closes immediately. Thanks for helping, here my Code:

import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:http/http.dart' as http;


class Job {
  final String vorname;
  final String nachname;
  bool isExpanded;


  Job({
    required this.vorname,
    required this.nachname,
    required this.isExpanded,
  });

  factory Job.fromJson(Map<String, dynamic> json) {
    return Job(
      vorname: json['vorname'],
      nachname: json['nachname'],
      isExpanded: false,
    );
  }
}

Future<List<Job>> fetchJobs() async {
  final response = await http.get(Uri.parse('http://10.0.2.2:8000/api/jobs'));
  if(response.statusCode == 200){
    List jsonResponse = json.decode(response.body);
    return jsonResponse.map((data) => Job.fromJson(data)).toList();
  } else {
    throw Exception('failed to load job');
  }
}



class AuftraegePage extends StatefulWidget {

   @override
   _AuftraegePage createState() => _AuftraegePage();
}

class _AuftraegePage extends State<AuftraegePage>{




 String selectedDay = DateFormat('dd.MM.yyyy').format(DateTime.now());

 final List<Map<String, dynamic>> _items = List.generate(
     10,
         (index) => {
       'id': index,
       'title': 'Max Mustermann',
       'description':
       'This is the description of the item $index. Lorem Ipsum is simply dummy text of the printing and typesetting industry.',
       'isExpanded': false,
     });




 void _showDatePicker(){
   showDatePicker(
     locale:  const Locale('de', 'DE'),
     context: context,
     initialDate: DateTime.now(),
     firstDate: DateTime(1970),
     lastDate: DateTime(2050),
     builder: (context, child) {
       return Theme(
         data: ThemeData.light().copyWith(
           colorScheme: ColorScheme.light(
             primary: Color(0xff1f6526),
             onPrimary: Colors.white,
             onSurface: Colors.black,
           ),
           dialogBackgroundColor:Colors.white,
         ),
         child: child!,
       );
     },
   ).then((value) {
     setState(() {
       String _dateTime = DateFormat('dd.MM.yyy', 'de_DE').format(value!);
       selectedDay = _dateTime;
     });
   } );

 }


  @override
  Widget build(BuildContext context) {
     return Container(
       color: Colors.grey[300],
       child: SingleChildScrollView(
         padding: EdgeInsets.only(left: 16.0, right: 16.0, top: 4.0),
         physics: AlwaysScrollableScrollPhysics(),
         child: Column(
           children: <Widget> [
             const SizedBox(height: 20),
             const Text('Aufträge',
             style: TextStyle(
               fontSize: 35,
               fontWeight: FontWeight.bold,
             ),
             ),
             const SizedBox(height: 15),
             buildDatePicker(),
             const SizedBox(height: 20),
             buildCreateButton(),
             const SizedBox(height: 20),
             buildListOfJobs(),
           ],
         ),

       ),
     );

  }

  
 Widget buildListOfJobs(){
    return FutureBuilder<List<Job>>(
      future: fetchJobs(),
      builder: (context, snapshot) {
        if(snapshot.hasData){
          return ExpansionPanelList(
            dividerColor: Colors.grey[700],
            elevation: 3,
            // Controlling the expansion behavior
            expansionCallback: (index, isExpanded) {
              setState(() {
                snapshot.data![index].isExpanded = !isExpanded;
                 print(snapshot.data![index].isExpanded);
              });
            },
            animationDuration: Duration(milliseconds: 600),
            children: snapshot.data!.map(
                  (item) => ExpansionPanel(

                canTapOnHeader: true,
                backgroundColor:
                item.isExpanded == true ? Colors.grey[300] : Colors.grey[300],
                headerBuilder: (context, isExpanded){
                  return Container(
                      padding: EdgeInsets.symmetric(vertical: 10, horizontal: 30),
                      child: Column(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: [
                          Text(
                            item.vorname,
                            style: TextStyle(
                              fontSize: 18.0,
                            ),
                          ),

                          SizedBox(height: 5),
                          Wrap(
                            children: <Widget>[
                              Icon(
                                Icons.access_time_filled,
                                size: 22.0,
                              ),
                              SizedBox(
                                width:5,
                              ),
                              Text('07:00 - 07:13',
                                style: TextStyle(
                                    fontWeight: FontWeight.bold,
                                    fontSize: 15
                                ),)
                            ],
                          ),
                        ],
                      )

                  );
                },
                body: Container(
                  color: Colors.grey[300],
                  padding: EdgeInsets.symmetric(vertical: 15, horizontal: 30),
                  child: Column(
                    children: [
                      Row(
                        children: [
                          Expanded(
                            flex: 5,
                            child: Wrap(
                              children: <Widget>[
                                Icon(FontAwesomeIcons.user,
                                  size: 19,),
                                SizedBox(
                                  width:5,
                                ),
                                Text('Mitglied: OGV Imst ',
                                  style: TextStyle(
                                    fontSize: 15,
                                  ),),
                              ],

                            ),
                          ),

                          Expanded(
                            flex: 4,
                            child: Wrap(
                              children: <Widget>[
                                Icon(FontAwesomeIcons.locationDot,
                                    size: 19),
                                SizedBox(
                                  width:5,
                                ),
                                Text('Ort: Imst',
                                    style: TextStyle(
                                      fontSize: 15,
                                    )),
                              ],
                            ),
                          ),
                        ],
                      ),

                      SizedBox(height: 10),
                      Row(
                        children: [
                          Expanded(
                            flex: 5,
                            child: Wrap(
                              children: <Widget>[
                                Icon(FontAwesomeIcons.weightHanging,
                                  size: 19,),
                                SizedBox(
                                  width:5,
                                ),
                                Text('Menge: 300 ',
                                  style: TextStyle(
                                    fontSize: 15,
                                  ),),
                              ],
                            ),
                          ),

                          Expanded(
                            flex: 4,
                            child: Wrap(
                              children: <Widget>[
                                Icon(FontAwesomeIcons.wineBottle,
                                  size: 19,),
                                SizedBox(
                                  width:5,
                                ),
                                Text('Most: 0',
                                    style: TextStyle(
                                      fontSize: 15,
                                    )),
                              ],
                            ),
                          ),
                        ],
                      ),

                      SizedBox(height: 10),
                      Row(
                        children: [
                          Expanded(
                            flex: 5,
                            child: Wrap(
                              children: <Widget>[
                                Icon(FontAwesomeIcons.bottleDroplet,
                                  size: 19,),
                                SizedBox(
                                  width:5,
                                ),
                                Text('Flaschen: 0',
                                  style: TextStyle(
                                    fontSize: 15,
                                  ),),
                              ],
                            ),
                          ),

                          Expanded(
                            flex: 4,
                            child: Wrap(
                              children: <Widget>[
                                Icon(FontAwesomeIcons.bagShopping,
                                  size: 19,),
                                SizedBox(
                                  width:5,
                                ),
                                Text('Bag: 0',
                                    style: TextStyle(
                                      fontSize: 15,
                                    )),
                              ],
                            ),
                          ),
                        ],
                      ),
                      SizedBox(height: 10),
                      Row(
                        children: [
                          Expanded(
                            flex: 5,
                            child: Wrap(
                              children: <Widget>[
                                Icon(FontAwesomeIcons.box,
                                  size: 19,),
                                SizedBox(
                                  width:5,
                                ),
                                Text('Karton: 0',
                                  style: TextStyle(
                                    fontSize: 15,
                                  ),),
                              ],
                            ),
                          ),
                        ],
                      ),
                      SizedBox(height: 10),
                      Divider(color: Colors.black,),
                      SizedBox(height: 10),
                      Row(
                        children: [
                          Wrap(
                            children: <Widget>[
                              Icon(FontAwesomeIcons.message,
                                size: 19,),
                              SizedBox(
                                width:5,
                              ),
                              Text('Anmerkungen: ',
                                style: TextStyle(
                                  fontSize: 15,
                                ),),
                            ],
                          ),
                        ],
                      ),

                      SizedBox(height: 10),
                      Divider(color: Colors.black,),
                      SizedBox(height: 10),
                      Row(
                        children: [
                          Expanded(
                            flex: 5,
                            child: Wrap(
                              children: <Widget>[
                                Icon(FontAwesomeIcons.tasks,
                                  size: 19,),
                                SizedBox(
                                  width:5,
                                ),
                                Text('Bestätigt: Nein',
                                  style: TextStyle(
                                    fontSize: 15,
                                  ),),
                              ],
                            ),
                          ),

                          Expanded(
                            flex: 4,
                            child: Wrap(
                              children: <Widget>[
                                Icon(FontAwesomeIcons.xmark,
                                  size: 19,),
                                SizedBox(
                                  width:5,
                                ),
                                Text('Stoniert: Nein',
                                    style: TextStyle(
                                      fontSize: 15,
                                    )),
                              ],
                            ),
                          ),
                        ],
                      ),

                      SizedBox(height: 10),
                      Row(
                        children: [
                          Expanded(
                            flex: 5,
                            child: Wrap(
                              children: <Widget>[
                                Icon(FontAwesomeIcons.eye,
                                  size: 19,),
                                SizedBox(
                                  width:5,
                                ),
                                Text('Noshow: Nein',
                                  style: TextStyle(
                                    fontSize: 15,
                                  ),),
                              ],
                            ),
                          ),

                          Expanded(
                            flex: 4,
                            child: Wrap(
                              children: <Widget>[
                                Icon(FontAwesomeIcons.check,
                                  size: 19,),
                                SizedBox(
                                  width:5,
                                ),
                                Text('Erledigt: Nein',
                                    style: TextStyle(
                                      fontSize: 15,
                                    )),
                              ],
                            ),
                          ),
                        ],
                      ),
                      SizedBox(height: 20),

                      Row(
                        children: [
                          Expanded(
                            flex: 5,
                            child: ElevatedButton(
                              onPressed:_showDatePicker,
                              style: ElevatedButton.styleFrom(
                                backgroundColor: Colors.blue,
                                elevation: 5,
                                padding: EdgeInsets.all(13),
                                shape: RoundedRectangleBorder(
                                    borderRadius: BorderRadius.circular(15)),
                              ),
                              child:  Wrap(
                                children: const <Widget>[
                                  Icon(FontAwesomeIcons.edit,
                                    color: Colors.white,
                                    size: 20.0,
                                  ),
                                  SizedBox(
                                    width:5,
                                  ),
                                  Text(
                                    'Bearbeiten',
                                    style: TextStyle(
                                      color: Colors.white,
                                      fontSize: 16.0,
                                    ),
                                  ),
                                ],
                              ),
                            ),
                          ),

                          SizedBox(width: 10),

                          Expanded(
                            flex: 5,
                            child: ElevatedButton(
                              onPressed:_showDatePicker,
                              style: ElevatedButton.styleFrom(
                                backgroundColor: Colors.yellow[600],
                                elevation: 5,
                                padding: EdgeInsets.all(13),
                                shape: RoundedRectangleBorder(
                                    borderRadius: BorderRadius.circular(15)),
                              ),
                              child:  Wrap(
                                children: <Widget>[
                                  Icon(FontAwesomeIcons.file,
                                    color: Colors.black,
                                    size: 20.0,
                                  ),
                                  SizedBox(
                                    width:5,
                                  ),
                                  Text(
                                    'Rechnung',
                                    style: TextStyle(
                                      color: Colors.black,
                                      fontSize: 16.0,
                                    ),
                                  ),
                                ],
                              ),
                            ),
                          ),
                        ],
                      ),
                    ],
                  ),
                ),
                    isExpanded: item.isExpanded,
              ),
            ).toList(),
          );
        } else if(snapshot.hasError) {
          return Text('${snapshot.error}');
          //return Text('keine Daten gefunden');
        }
        return const CircularProgressIndicator();
      },
    );
  }



  Widget buildDatePicker(){
    return Row(
      mainAxisAlignment: MainAxisAlignment.center,
      children:  [
        Text(
          'Datum wählen: ',
          style: TextStyle(
            fontSize: 20,
          ),
        ),
        ElevatedButton(
          onPressed:_showDatePicker,
          style: ElevatedButton.styleFrom(
            backgroundColor: Colors.grey[700],
            elevation: 5,
            padding: EdgeInsets.all(13),
            shape: RoundedRectangleBorder(
                borderRadius: BorderRadius.circular(15)),
          ),
          child:  Wrap(
            children: <Widget>[
              Icon(
                Icons.date_range,
                color: Colors.white,
                size: 20.0,
              ),
              SizedBox(
                width:5,
              ),
              Text(
                selectedDay,
                style: TextStyle(
                  color: Colors.white,
                  fontSize: 16.0,
                ),
              ),
            ],
          ),
        ),
      ],
    );
  }

  Widget buildCreateButton(){
    return ElevatedButton(
      onPressed:_showDatePicker,
      style: ElevatedButton.styleFrom(
        backgroundColor: Colors.grey[700],
        minimumSize: const Size.fromHeight(50),
        elevation: 5,
        padding: EdgeInsets.only(left: 35, right: 20, top: 13, bottom: 13),
        shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.circular(15)),
      ),
      child:  Wrap(
        children: <Widget>[
          Text(
            'Auftrag erstellen',
            style: TextStyle(
              color: Colors.white,
              fontSize: 16.0,
            ),
          ),
          SizedBox(
            width:5,
          ),
          Icon(
            Icons.add_card ,
            color: Colors.white,
            size: 20.0,
          ),
        ],
      ),
    );
  }
}

I think there could be an issue during fetching the data, because I think with every click my data get reloaded and "isExpanded" is set to *false * again.


Solution

  • You can replace future: fetchJobs() with by creating a state future variable. It will prevent unwanted api call.

      late final jobListFuture  =  fetchJobs();
      @override
      Widget build(BuildContext context) {
    
     Widget buildListOfJobs(){
        return FutureBuilder<List<Job>>(
          future: jobListFuture,