Flutter 3.24.3 中 ListView 内的 ListView 中的错误

问题描述 投票:0回答:1

用一个非常简短、具体和实用的方式来理解:这是一个 ListView 位于另一个 ListView 中的错误。现在,更多关于这些 Widget 的构建方式的详细信息: 一个简单的 Scaffold,其主体显示一个 ListView(无论是 ListView 还是 ListView.builder,两者都将具有相同的行为,因此,同样的错误。)其中有一个 Column Widget,里面有两个 Widget:一个 StatefulWidget 和另一个 ListView.builder Widget,并且 Column Widget 内的这个 ListView.builder Widget 有一个 ListTile Widget,它只显示信息:带有索引的文本和删除图标。而 StatefulWidget 包含另一个 ListView.builder。

通过尽可能简单、最基本和干净的方式构建这个简单的结构,您会发现 StatefulWidget 的行为存在一个非常奇怪的问题。问题是:它“卡在”特定位置,不是控制 ListView Widget 的列表中的位置,而是布局本身,这是极其奇怪的。即使您删除了具有 StatefulWidget 的 Column Widget,它也不会消失,而是保留下来,无论您在调用 StatefulWidget 时是否使用 const。

这个极其奇怪的问题已经花了我整整一周的时间,我厌倦了试图弄清楚发生了什么,我什至认为我要疯了。

我为此深受创伤,所以我创建了一个极其简单的DartPad,只有150行代码,下面我将代码分享给大家,以便大家测试。

想到一个几乎让我失去理智的问题。

希望Flutter团队尽快看到并修复这个奇怪的问题。

更改 DartPad 中的 Flutter 版本(Main、Stable、Beta)并且始终保持相同的行为。在任何情况下,我都不会更改计算机上安装的 Flutter,因为我对需要为客户的特定项目保留的文件进行了编辑。

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: ListViewWithDelete(),
    );
  }
}

class ListViewWithDelete extends StatefulWidget {
  @override
  _ListViewWithDeleteState createState() => _ListViewWithDeleteState();
}

class _ListViewWithDeleteState extends State<ListViewWithDelete> {
  List<String> items = List<String>.generate(10, (index) => 'Item ${index + 1}');

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('ListView com Botão de Excluir'),
      ),
      body: Column(
        children: [
          Expanded(
            child: ListView.builder(
              itemCount: items.length,
              itemBuilder: (context, index) {
                return Column(
                  children: [
                    AulaWidget(),
                    ListTile(
                      leading: IconButton(
                        icon: Icon(Icons.delete),
                        onPressed: () {
                          setState(() {
                            items.removeAt(index);
                          });
                        },
                      ),
                      title: Text(items[index]),
                    ),
                  ],
                );
              },
            ),
          ),
          Padding(
            padding: const EdgeInsets.all(8.0),
            child: ElevatedButton(
              onPressed: () {
                setState(() {
                  items.add('Item ${items.length + 1}');
                });
              },
              child: Text('Adicionar Item'),
            ),
          ),
        ],
      ),
    );
  }
}

class AulaWidget extends StatefulWidget {
  @override
  _AulaWidgetState createState() => _AulaWidgetState();
}

class _AulaWidgetState extends State<AulaWidget> {
  List<String> listaDeAulas = List<String>.generate(5, (index) => 'Aula $index');

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        ListView.builder(
          itemCount: listaDeAulas.length,
          shrinkWrap: true,
          physics: const NeverScrollableScrollPhysics(),
          itemBuilder: (BuildContext context, int index) {
            return ListTile(
              leading: IconButton(
                icon: const Icon(Icons.delete),
                onPressed: () {
                  setState(() {
                    listaDeAulas.removeAt(index);
                  });
                },
              ),
              title: Text("Sinais de Trânsito ${listaDeAulas[index]}"),
            );
          },
        ),
        const SizedBox(height: 16),
        Row(
          children: [
            Expanded(
              child: ElevatedButton(
                onPressed: () {
                  setState(() {
                    listaDeAulas.add('Aula ${listaDeAulas.length}');
                  });
                },
                child: const Text('Adicionar Aula'),
              ),
            ),
          ],
        ),
      ],
    );
  }

  void _showConfirmationDialog(BuildContext context) {
    showDialog(
      context: context,
      builder: (BuildContext context) {
        return AlertDialog(
          title: const Text("Adicionar Nova Aula"),
          content: const Text("Deseja adicionar uma nova aula?"),
          actions: <Widget>[
            TextButton(
              child: const Text("Cancelar"),
              onPressed: () {
                Navigator.of(context).pop();
              },
            ),
            TextButton(
              child: const Text("Confirmar"),
              onPressed: () {
                setState(() {
                  listaDeAulas.add('Aula ${listaDeAulas.length}');
                });
                Navigator.of(context).pop();
              },
            ),
          ],
        );
      },
    );
  }
}
flutter
1个回答
0
投票

简而言之,您不需要使用嵌套的 ListView,因为内部 ListView 替换为 Column 并渲染子级。

class _AulaWidgetState extends State<AulaWidget> {
  List<String> listaDeAulas = List<String>.generate(5, (index) => 'Aula $index');

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        ...listaDeAulas.map((e) => ListTile(
              leading: IconButton(
                icon: const Icon(Icons.delete),
                onPressed: () {
                  setState(() {
                    listaDeAulas.remove(e);
                  });
                },
              ),
              title: Text("Sinais de Trânsito ${e}"),
            )),
        const SizedBox(height: 16),
        Row(
          children: [
            Expanded(
              child: ElevatedButton(
                onPressed: () {
                  setState(() {
                    listaDeAulas.add('Aula ${listaDeAulas.length}');
                  });
                },
                child: const Text('Adicionar Aula'),
              ),
            ),
          ],
        ),
      ],
    );
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.