【问题标题】:Getting ExpansionPanelList to work inside Streambuilder in flutter让ExpansionPanelList在Streambuilder中工作
【发布时间】:2020-12-17 00:13:08
【问题描述】:

我正在尝试使用 ExpansionPanellist 安排一些从 Firebase 流式传输的数据。 panelList 放置在 StreamBuilder 内,在 StreamBuilder 上方我有一个 SingleChildScrollView。

我可以看到带有标题的列表,但我无法让展开/折叠功能工作,所以我看不到正文。 screenshot of the list

扩展/折叠功能在 Streambuilder 之外工作,但当时我无法从 Firebase 访问数据。

任何帮助将不胜感激!如果这是这样做的错误的方式,我也将感谢任何指向实现此目标的替代方法的指针。 (在查看过去的攀登和图表时,不会有任何数据添加到服务器,因此如果有更简单/更好的方法,则可能不需要流构建器。

-克里斯蒂安

 class Graphs extends StatefulWidget {
      static String id = 'graphs_screen';
      @override
      _GraphsState createState() => _GraphsState();
    } 

@override
      Widget build(BuildContext context) {
        return Scaffold(
          backgroundColor: Colors.white,
          body: DefaultTabController(
            length: 3,
            child: Scaffold(
                appBar: AppBar(
                  bottom: TabBar(tabs: [
                    Tab(text: 'Graphs'),
                    Tab(text: 'Stats'),
                    Tab(text: 'Climbs'),
                  ]),
                ),
                body: TabBarView(
                  children: [
                    //Image.asset('assets/images/line_graph.png'),
                    Expanded(child: NumericComboLinePointChart.withSampleData()),
                    Container(
                      child: Text(''),
                    ),
                    SingleChildScrollView(
                      child: DataStream(),
                    ),
                  ],
                )),
          ),
        );
      }
    }

class DataStream extends StatefulWidget {
  @override
  _DataStreamState createState() => _DataStreamState();
}

class _DataStreamState extends State<DataStream> {
  @override
  Widget build(BuildContext context) {
    return StreamBuilder<QuerySnapshot>(
        stream: _firestore
            .collection('climbs')
            .orderBy('Date', descending: true)
            .snapshots(),
        builder: (context, snapshot) {
   

          List<ExpansionItem> expansionList = <ExpansionItem>[];

          if (snapshot.hasData) {
            final alldata = snapshot.data.docs;

            for (var data in alldata) {
              final dataFunction = data.data();

              final grades = dataFunction['gradeScore'];

              final climbDate = dataFunction['Date'];

              final climbDateT = DateTime.fromMicrosecondsSinceEpoch(
                  climbDate.microsecondsSinceEpoch);
              String climbDateString =
                  "${climbDateT.year.toString()}-${climbDateT.month.toString().padLeft(2, '0')}-${climbDateT.day.toString().padLeft(2, '0')} ${climbDateT.hour.toString()}-${climbDateT.minute.toString()}";

              final climber = dataFunction['sender'];

              final currentUSer = loggedInUser.email;

              if (climber == loggedInUser.email) {
                expansionList.add(ExpansionItem(
                    dateTimeHeader: climbDateString,
                    climbs: grades.toString()));
             
              }
            }
          }
          return ExpansionPanelList(
            expansionCallback: (int index, bool isExpanded) {
              setState(() {
                print('tap registered');
                expansionList[index].isExpanded = !isExpanded;
              });
            },
            children: expansionList.map((ExpansionItem item) {
              return ExpansionPanel(
                headerBuilder: (BuildContext context, bool isExpanded) {
                  return Container(
                    child: Text(item.dateTimeHeader),
                  );
                },
                body: Container(
                  child: Text(item.climbs),
                ),
                isExpanded: item.isExpanded,
              );
            }).toList(),
          );
        });
  }
}

class ExpansionItem {
  ExpansionItem({this.isExpanded: false, this.dateTimeHeader, this.climbs});

  bool isExpanded;
  final String dateTimeHeader;
  final String climbs;

}

【问题讨论】:

    标签: firebase flutter dart expandablelistview stream-builder


    【解决方案1】:

    我也遇到了这个问题并设法开发了一个“解决方法”(提前抱歉,有点乱)。

    您的扩展图块未扩展的原因是由于扩展回调函数的性质。一旦你按下展开按钮,它也会导致你的 StreamBuilder 重建。因此,由于您在 StreamBuilder 中初始化“expansionList”,因此无论您按多少次,它都会将“isExpanded”重置为 false。因此,您最好的选择是在 StreamBuilder 之外初始化 expandList 并从内部对其进行修改。在下面查看我的解决方案,但我欢迎任何人对其进行优化和/或分享更好的解决方案。

    class ExpansionItem {
      String headerValue;
      bool isExpanded;
      SplitObject item;
    
      ExpansionItem({this.item, this.headerValue, this.isExpanded = false});
    }
    class MyExample extends StatefulWidget{
      @override
      _MyExampleState createState() => _MyExampleState();
    }
    
    class _MyExampleState extends State<MyExample> {
    
    //Pick a number as large as you see fit to always be more than necessary.
      List<ExpansionItem> expansionItems = List<ExpansionItem>.generate('anyNumber', (int index)=> ExpansionItem(isExpanded: false,));
    
      @override
      Widget build(BuildContext context) {
    
        return GestureDetector(
            child: Scaffold(
              appBar: AppBar(
                title: Text('Split',style: Theme.of(context).textTheme.headline3,),
              ),
              body: SingleChildScrollView(
                padding: const EdgeInsets.all(8),
                child: Container(
                  child: StreamBuilder(
                    builder: (context, streamData){
                      if(streamData.hasData){
                        List<SplitObject> items = streamData.data;
    
                        //Save data to Expansion list by iterating through it.
                        for (var i = 0; i < items.length; i++){
                          try {
                            expansionItems[i].item =items[i];
                            expansionItems[i].headerValue =items[i].itemName;
                          } catch (e) {
                            // Catch any range errors after trimming list.
                            if(e.toString().contains('RangeError')) {
                              expansionItems.add(ExpansionItem(
                                  item: items[i], headerValue: items[i].itemName));
                            }
                          }
    
                        }
                        // Trim list
                        expansionItems = expansionItems.getRange(0, items.length).toList();
    
                        return _buildListPanel(expansionItems);
                      } else {
                        return ListTile(
                          title: Text('No items to split.'),
                        );
                      }
                    },
                    stream: DatabaseService().splitItemData,
                  ),
                ),
              ),
            )
        );
      }
      Widget _buildListPanel(List<ExpansionItem> expansionItems){
    
        // print(expansionItems[0].isExpanded);
        return ExpansionPanelList(
          expansionCallback: (int index, bool isExpanded){
            setState(() {
              expansionItems[index].isExpanded = !isExpanded;
              // print(expansionItems[index].isExpanded);
            });
          },
          children: expansionItems.map<ExpansionPanel>((ExpansionItem item){
            return ExpansionPanel(
              headerBuilder: (BuildContext context, bool isExpanded){
                print(item.isExpanded);
                return Padding(
                  padding: const EdgeInsets.all(8.0),
                  child: Column(),
                );
              },
              body: Container(),
              isExpanded: item.isExpanded,
            );
          }).toList(),
        );
      }
    }
    

    【讨论】:

    • 感谢您的回复,对于我迟到的回复感到抱歉。最后我放弃了使用ExpansionPanellist,只自定义了一个ListView。
    猜你喜欢
    • 2021-02-13
    • 1970-01-01
    • 2021-07-11
    • 1970-01-01
    • 2021-06-07
    • 2020-01-22
    • 2020-02-11
    • 2018-02-26
    • 2013-11-09
    相关资源
    最近更新 更多