如何在可扩展列表视图的扩展部分添加常规列表视图

时间:2021-06-04 14:31:43

标签: flutter flutter-layout

我有以下问题,我想将常规列表视图添加到可扩展列表视图的扩展部分,我已尝试使用以下代码进行操作:

    body: ListTile(
                leading: Checkbox(
                    value: info.completed,
                    onChanged: (value) {
                      setState(() {
// Here you toggle the checked item state
                        infos.firstWhere((currentInfo) => info == currentInfo)
                          ..completed = value;
                      });
                    }),
                title: ListView.builder(
                    itemCount: info.expandedValueData.length ,
                    itemBuilder: (context, index) {
                      return Card(
                        child: ListTile(
                          title: Text(info.expandedValueData[index].title,
                              style: TextStyle(
                                  decoration: info.completed
                                      ? TextDecoration.lineThrough
                                      : null))),
                        );
                    },),
                subtitle: Text(
                    "Drücke auf den Mülleimer, um diesen Abschnitt bis zum Neustart der App zu löschen"),
                trailing: IconButton(
                  icon: Icon(Icons.delete),
                  onPressed: () {
                    setState(() {
                      infos.removeWhere((currentInfo) => info == currentInfo);
                    });
                  },
                )),

这样我就没有收到任何错误,但是如果我打开一个列表磁贴,它并没有描绘出我想要的数据,它只是空的,这里有一张图片:

enter image description here

有什么建议我做错了什么以及如何解决吗?

编辑:所以这或多或少是基本代码,我找到了部分问题的解决方案(第 62 行),您将看到是否测试了描述列表的代码,但无论如何,我获取渲染 Flex 溢出,并且可扩展部分中的每个文本图块旁边都没有放置可勾选框

这里是完整的代码(可能添加了我应该添加的更多数据)

    import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Scaffold(
        body: ExpansionTile(
          title: Text("Generelles Vorgehen"),
          children: [ExpansionList()],
        ),
      ),
    );
  }
}

class ExpansionList extends StatefulWidget {
  final Info info;
  const ExpansionList({
    Key key,
    this.info,
  }) : super(key: key);
  @override
  _ExpansionListState createState() => _ExpansionListState();
}

class _ExpansionListState extends State<ExpansionList> {
  Widget _buildListPanel() {
    return ExpansionPanelList(
      expansionCallback: (int index, bool isExpanded) {
        setState(() {
          infos[index].isExpanded = !isExpanded;
        });
      },
      children: infos.map<ExpansionPanel>((Info info) {
        return ExpansionPanel(
            headerBuilder: (BuildContext context, bool isExpanded) {
              return ListTile(
                title: Text(info.headerValue),
              );
            },
            body: ListTile(
                leading: Checkbox(
                    value: info.completed,
                    onChanged: (value) {
                      setState(() {
// Here you toggle the checked item state
                        infos.firstWhere((currentInfo) => info == currentInfo)
                          ..completed = value;
                      });
                    }),
                title: SizedBox(
                  height: 200, //this was the solution I dont know why, but you have to specify a hight here, so that the content gets whon
                  child: ListView.builder(
                    itemCount: info.expandedValueData.length,
                    itemBuilder: (context, index) {
                      return Card(
                        child: ListTile(
                            title: Text(info.expandedValueData[index].title,
                                style: TextStyle(
                                    decoration: info.completed
                                        ? TextDecoration.lineThrough
                                        : null))),
                      );
                    },
                  ),
                ),
                subtitle: Text(
                    "Drücke auf den Mülleimer, um diesen Abschnitt bis zum Neustart der App zu löschen"),
                trailing: IconButton(
                  icon: Icon(Icons.delete),
                  onPressed: () {
                    setState(() {
                      infos.removeWhere((currentInfo) => info == currentInfo);
                    });
                  },
                )),
            isExpanded: info.isExpanded);
      }).toList(),
    );
  }

  @override
  Widget build(BuildContext context) {
    return SingleChildScrollView(
      child: Container(
        child: _buildListPanel(),
      ),
    );
  }
}


class expandedValue{
  final int id;
  final String title;

  const expandedValue({
    this.id,
    this.title,
  });
}

class Info {
  String headerValue;
  bool isExpanded;
  bool completed;
  final List<expandedValue> expandedValueData;

  Info(
      {this.headerValue,
        this.isExpanded = false,
        this.completed = false,
        this.expandedValueData});
}

List<Info> infos = [
  Info(
    headerValue: "Außenansicht",
    expandedValueData: <expandedValue>[
      expandedValue(id: 1, title: "Roststellen"),
      expandedValue(
          id: 2,
          title:
          "Farbunterschiede im Lack, Unregelmäßigkeiten [Problemstellen übermalt]"),
      expandedValue(
          id: 3,
          title: "kleine Kratzer [hinter Karosserie größere Folgeschäden?]"),
      expandedValue(
          id: 4, title: "Dichtungen an Scheiben & Türen [porös, rissig]"),
      expandedValue(
          id: 5,
          title:
          "Vorallem Windschutzscheibe auf Kratzer untersuchen [Gefahr größerer Rissbildung ]"),
      expandedValue(
          id: 6,
          title:
          "Lampen untersuchen, funktionsfähig? Innen beschlagene Scheinwerfer [Gefahr durch Wasserschaden]"),
      expandedValue(id: 7, title: "Reifen [Risse o. abgefahrenes Profil?]"),
    ],
  ),
  Info(
    headerValue: "Innenraum",
    expandedValueData: <expandedValue>[
      expandedValue(
          id: 1,
          title: "klappern Türen oder deren Seitenverkleidung beim Schließen?"),
      expandedValue(id: 2, title: "funktionierende Elektrik"),
      expandedValue(id: 3, title: "Sitze"),
      expandedValue(id: 4, title: "Rest"),
    ],
  ),
  Info(
    headerValue: "Motorraum",
    expandedValueData: <expandedValue>[
      expandedValue(
          id: 1,
          title:
          "Motor schon vom Verkäufer warmgelaufen? [eventuell sollen Startprobleme vertuscht werden]"),
      expandedValue(
          id: 2,
          title: "Batteriepole angerostet? [Gefahr vorzeitiger Entladung]"),
      expandedValue(
          id: 3, title: "Gibt es Öl oder Bremsflüssigkeitsspuren an:"),
      expandedValue(
          id: 4,
          title:
          "Sprudelt Kühlswasser bei laufendem Motor [eventuell Zylinderkopfdichtung defekt]"),
      expandedValue(id: 5, title: "Ölstand prüfen"),
    ],
  ),
  Info(
    headerValue: "Unterboden",
    expandedValueData: <expandedValue>[
      expandedValue(id: 1, title: "Roststellen?"),
      expandedValue(
          id: 2,
          title:
          "neuer Unterbodenschutz? [möglicher Versuch Problemstellen zu verdecken (z.B Schweißnähte etc.)]"),
      expandedValue(
          id: 3, title: "sitzt der Auspuff fest, arbeitet der Motor leise?"),
    ],
  ),
  Info(
    headerValue: "Dokumenten- & Zahlencheck",
    expandedValueData: <expandedValue>[
      expandedValue(id: 1, title: "Reperaturenabrechnungen vorhanden?"),
      expandedValue(
          id: 2,
          title:
          "macht Laufleistung Sinn? Mögliche Lufleistungen im Bereich von über 150 000 km, wenn:"),
      expandedValue(id: 3, title: "Zulassungsbescheinigung Teil 1&2 "),
      expandedValue(id: 4, title: "Wartungen & Rechnungen"),
    ],
  ),
  Info(
    headerValue: "Probefahrt",
    expandedValueData: <expandedValue>[
      expandedValue(id: 1, title: "vor der Fahrt:"),
      expandedValue(id: 2, title: "bei der Fahrt"),
      expandedValue(id: 3, title: "nach der Fahrt"),
    ],
  ),
  Info(
    headerValue: "Garantie, Gewehrleistung und Vertrag ",
    expandedValueData: <expandedValue>[
      expandedValue(
          id: 1,
          title:
          "auf Rechmäßigkeit prüfen, wegen Haftungsgründen verweisen wir hier auf andere Seiten, wie die der Allianz oder Cosmosdirekt o. ä. "),
    ],
  ),
];

1 个答案:

答案 0 :(得分:1)

要解决溢出问题,您可以将小部件包装在 SingleChildScrollView 中,只要您绘制的内容超过屏幕上的可用空间,您就应该使用它或 ListView 来滚动。

至于每个磁贴旁边的复选框,您在创建每个 ListView.builderexpandedValue 之前绘制复选框,因此它只为包含 listivew 的 listTile 创建一次,而不是为每个项目创建。在 listview.builder 中构造复选框可以解决这个问题。

我还在 expandedValue 类中添加了一个布尔属性,以便能够单独检查每个项目(IDK,如果这是您正在寻找的行为)。

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Scaffold(
        body: SingleChildScrollView(
          child: ExpansionTile(
            title: Text("Generelles Vorgehen"),
            children: [ExpansionList()],
          ),
        ),
      ),
    );
  }
}

class ExpansionList extends StatefulWidget {
  final Info info;

  const ExpansionList({
    Key key,
    this.info,
  }) : super(key: key);

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

class _ExpansionListState extends State<ExpansionList> {
  Widget _buildListPanel() {
    return ExpansionPanelList(
      expansionCallback: (int index, bool isExpanded) {
        setState(() {
          infos[index].isExpanded = !isExpanded;
        });
      },
      children: infos.map<ExpansionPanel>((Info info) {
        return ExpansionPanel(
            headerBuilder: (BuildContext context, bool isExpanded) {
              return ListTile(
                title: Text(info.headerValue),
              );
            },
            body: ListTile(
              title: SizedBox(
                height: 200,
                //this was the solution I dont know why, but you have to specify a hight here, so that the content gets whon
                child: ListView.builder(
                  itemCount: info.expandedValueData.length,
                  itemBuilder: (context, index) {
                    var currentExpandedValue=info.expandedValueData[index];
                    return Card(
                      child: ListTile(
                        leading: Checkbox(
                            value: currentExpandedValue.newlyIsExpandedValue,
                            onChanged: (value) {
                              setState(() {
// Here you toggle the checked item state
                                currentExpandedValue.newlyIsExpandedValue=value;
                              });
                            }),
                        title: Text(info.expandedValueData[index].title,
                            style: TextStyle(decoration: currentExpandedValue.newlyIsExpandedValue ? TextDecoration.lineThrough : null)),
                        trailing: IconButton(
                          icon: Icon(Icons.delete),
                          onPressed: () {
                            setState(() {
                              info.expandedValueData.removeWhere((currentInfo) => currentExpandedValue == currentInfo);
                            });
                          },
                        ),
                      ),
                    );
                  },
                ),
              ),
              subtitle: Text("Drücke auf den Mülleimer, um diesen Abschnitt bis zum Neustart der App zu löschen"),
            ),
            isExpanded: info.isExpanded);
      }).toList(),
    );
  }

  @override
  Widget build(BuildContext context) {
    return SingleChildScrollView(
      child: Container(
        child: _buildListPanel(),
      ),
    );
  }
}

class expandedValue {
  final int id;
  final String title;
   bool newlyIsExpandedValue;
   expandedValue( {
    this.id,
    this.title,
    this.newlyIsExpandedValue=false,
  });
}

class Info {
  String headerValue;
  bool isExpanded;
  bool completed;
  final List<expandedValue> expandedValueData;

  Info({this.headerValue, this.isExpanded = false, this.completed = false, this.expandedValueData});
}

List<Info> infos = [
  Info(
    headerValue: "Außenansicht",
    expandedValueData: <expandedValue>[
      expandedValue(id: 1, title: "Roststellen"),
      expandedValue(id: 2, title: "Farbunterschiede im Lack, Unregelmäßigkeiten [Problemstellen übermalt]"),
      expandedValue(id: 3, title: "kleine Kratzer [hinter Karosserie größere Folgeschäden?]"),
      expandedValue(id: 4, title: "Dichtungen an Scheiben & Türen [porös, rissig]"),
      expandedValue(id: 5, title: "Vorallem Windschutzscheibe auf Kratzer untersuchen [Gefahr größerer Rissbildung ]"),
      expandedValue(
          id: 6,
          title: "Lampen untersuchen, funktionsfähig? Innen beschlagene Scheinwerfer [Gefahr durch Wasserschaden]"),
      expandedValue(id: 7, title: "Reifen [Risse o. abgefahrenes Profil?]"),
    ],
  ),
  Info(
    headerValue: "Innenraum",
    expandedValueData: <expandedValue>[
      expandedValue(id: 1, title: "klappern Türen oder deren Seitenverkleidung beim Schließen?"),
      expandedValue(id: 2, title: "funktionierende Elektrik"),
      expandedValue(id: 3, title: "Sitze"),
      expandedValue(id: 4, title: "Rest"),
    ],
  ),
  Info(
    headerValue: "Motorraum",
    expandedValueData: <expandedValue>[
      expandedValue(
          id: 1, title: "Motor schon vom Verkäufer warmgelaufen? [eventuell sollen Startprobleme vertuscht werden]"),
      expandedValue(id: 2, title: "Batteriepole angerostet? [Gefahr vorzeitiger Entladung]"),
      expandedValue(id: 3, title: "Gibt es Öl oder Bremsflüssigkeitsspuren an:"),
      expandedValue(id: 4, title: "Sprudelt Kühlswasser bei laufendem Motor [eventuell Zylinderkopfdichtung defekt]"),
      expandedValue(id: 5, title: "Ölstand prüfen"),
    ],
  ),
  Info(
    headerValue: "Unterboden",
    expandedValueData: <expandedValue>[
      expandedValue(id: 1, title: "Roststellen?"),
      expandedValue(
          id: 2,
          title: "neuer Unterbodenschutz? [möglicher Versuch Problemstellen zu verdecken (z.B Schweißnähte etc.)]"),
      expandedValue(id: 3, title: "sitzt der Auspuff fest, arbeitet der Motor leise?"),
    ],
  ),
  Info(
    headerValue: "Dokumenten- & Zahlencheck",
    expandedValueData: <expandedValue>[
      expandedValue(id: 1, title: "Reperaturenabrechnungen vorhanden?"),
      expandedValue(
          id: 2, title: "macht Laufleistung Sinn? Mögliche Lufleistungen im Bereich von über 150 000 km, wenn:"),
      expandedValue(id: 3, title: "Zulassungsbescheinigung Teil 1&2 "),
      expandedValue(id: 4, title: "Wartungen & Rechnungen"),
    ],
  ),
  Info(
    headerValue: "Probefahrt",
    expandedValueData: <expandedValue>[
      expandedValue(id: 1, title: "vor der Fahrt:"),
      expandedValue(id: 2, title: "bei der Fahrt"),
      expandedValue(id: 3, title: "nach der Fahrt"),
    ],
  ),
  Info(
    headerValue: "Garantie, Gewehrleistung und Vertrag ",
    expandedValueData: <expandedValue>[
      expandedValue(
          id: 1,
          title:
              "auf Rechmäßigkeit prüfen, wegen Haftungsgründen verweisen wir hier auf andere Seiten, wie die der Allianz oder Cosmosdirekt o. ä. "),
    ],
  ),
];