我的Flutter ListView总是从列表中删除最后一个项目

dldeef67  于 2023-01-06  发布在  Flutter
关注(0)|答案(2)|浏览(173)

我正在创建一个Flutter小部件,当我尝试从我正在使用的列表中删除一个项目时,它总是删除最后一个,我想这可能是一个Key问题,但没有适合它,有人知道我如何解决这个问题吗?

密码

创建_游戏.dart

import 'package:flutter/material.dart';
import 'package:pontinho/components/custom_input.dart';

class CreateGame extends StatefulWidget {
  const CreateGame({super.key});

  @override
  State<CreateGame> createState() => _CreateGameState();
}

class _CreateGameState extends State<CreateGame> {
  List<String> names = [''];

  void changeName(int nameIndex, String change) {
    setState(() {
      names[nameIndex] = change;
    });
  }

  void removeName(int nameIndex) {
    print(names);
    print(nameIndex);
    setState(() {
      names.removeAt(nameIndex);
    });
  }

  ListView createNamesInput() {
    return ListView.builder(
      itemCount: names.length,
      shrinkWrap: true,
      itemBuilder: (context, index) {
        return ListTile(
          key: ObjectKey(index),
          title: CustomInput(
            key: ObjectKey(index),
            labelText: "Nome",
            onChanged: (String changed) => changeName(index, changed),
            text: names[index],
            onRemoved: () => removeName(index),
          ),
        );
      },
    );
    // return names
    //     .asMap()
    //     .entries
    //     .map((el) => CustomInput(
    //           key: ObjectKey('${el.key}'),
    //           labelText: "Nome",
    //           onChanged: changeName,
    //           index: el.key,
    //           text: names[el.key],
    //           onRemoved: removeName,
    //         ))
    //     .toList();
  }

  void addName() {
    setState(() {
      names.add('');
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        leading: GestureDetector(
          onTap: (() => Navigator.pop(context)),
          child: const Icon(
            Icons.arrow_back,
            color: Colors.black,
            size: 40,
          ),
        ),
        backgroundColor: Colors.white,
        titleTextStyle: const TextStyle(
          color: Colors.black,
          fontSize: 20,
        ),
        title: const Text("CRIE SEU JOGO"),
      ),
      body: Padding(
        padding: const EdgeInsets.symmetric(
          vertical: 8,
          horizontal: 16,
        ),
        // child: createNamesInput(),
        child: Column(
          children: [
            createNamesInput(),
            Padding(
              padding: const EdgeInsets.symmetric(vertical: 10),
              child: Row(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  TextButton(
                    onPressed: addName,
                    child: Row(
                      children: const [
                        Icon(Icons.add),
                        Text('Adicionar Jogador'),
                      ],
                    ),
                  ),
                ],
              ),
            ),
            SizedBox(
              width: double.infinity,
              height: 50,
              child: ElevatedButton(
                onPressed: () => print('Iniciar!'),
                child: const Text('Iniciar!'),
              ),
            )
          ],
        ),
      ),
    );
  }
}

自定义输入.dart

import 'package:flutter/material.dart';

typedef OneArgumentCallback = void Function(String changed);

class CustomInput extends StatefulWidget {
  final OneArgumentCallback onChanged;
  final VoidCallback onRemoved;
  final String labelText;
  final String text;

  const CustomInput({
    super.key,
    required this.onChanged,
    required this.labelText,
    required this.text,
    required this.onRemoved,
  });

  @override
  State<CustomInput> createState() => _CustomInputState();
}

class _CustomInputState extends State<CustomInput> {
  late final TextEditingController inputController;

  @override
  void initState() {
    super.initState();
    inputController = TextEditingController(text: widget.text);
  }

  void changeContent(String value) {
    widget.onChanged(
      value,
    );
  }

  @override
  Widget build(BuildContext context) {
    return TextFormField(
      key: widget.key,
      controller: inputController,
      textDirection: TextDirection.ltr,
      decoration: InputDecoration(
        border: const UnderlineInputBorder(),
        labelText: widget.labelText,
        suffixIcon: IconButton(
          onPressed: () => widget.onRemoved(),
          icon: const Icon(
            Icons.close,
            color: Colors.red,
          ),
        ),
      ),
      autocorrect: false,
      onChanged: (value) => changeContent(value),
    );
  }
}
holgip5t

holgip5t1#

事实上,这是一个key问题,您必须创建一个组合键,该组合键对于每个项目必须是唯一的,我将indexnames[index]合并,

CustomInput(
  key: ObjectKey('$index:${names[index]}'),
  labelText: "Nome",
  onChanged: (String changed) => changeName(index, changed),
  text: names[index],
  onRemoved: () => removeName(index),
),

注意,如果您单独尝试这段代码,文本字段将失去焦点,因为键已更改,这将通过删除onChange中的setState来解决

void changeName(int nameIndex, String change) {
  names[nameIndex] = change;
}

在这里,您不需要setState,因为在文本字段中键入内容时,UI将默认更新
我希望我已经说清楚了

aiazj4mn

aiazj4mn2#

我在想可能是个问题
没错您需要使用names[index]作为Key的值:

ListTile(
          key: ObjectKey(names[index]),
          title: CustomInput(

相关问题