英文:
How to fix _TypeError (type 'List<Animal?>' is not a subtype of type 'List<Animal>?' of 'value')
问题
无法理解我的代码有什么问题。无论我尝试什么,当尝试确认多选小部件中的选择时,我仍然会收到此错误。
这是我的代码。
```dart
class _ParticipantsToSelectState extends State<ParticipantsToSelect> {
static List<Animal> _animals = [
Animal(id: 1, name: "Lion"),
Animal(id: 2, name: "Flamingo"),
Animal(id: 3, name: "Hippo"),
Animal(id: 4, name: "Horse"),
Animal(id: 5, name: "Tiger"),
Animal(id: 6, name: "Penguin"),
Animal(id: 7, name: "Spider"),
Animal(id: 8, name: "Snake"),
Animal(id: 9, name: "Bear"),
Animal(id: 10, name: "Beaver"),
];
final _items = _animals
.map((animal) => MultiSelectItem<Animal>(animal, animal.name))
.toList();
List<Animal?>? _selectedAnimals3 = [];
final _multiSelectKey = GlobalKey<FormFieldState<List<Animal>?>>(); // 在此处更新
@override
void initState() {
_selectedAnimals3 = _animals;
super.initState();
}
@override
Widget build(BuildContext context) {
return Expanded(
child: MultiSelectBottomSheetField<Animal>(
key: _multiSelectKey,
initialChildSize: 0.7,
maxChildSize: 0.95,
title: Text("Animals"),
buttonText: Text("Favorite Animals"),
items: _items,
searchable: true,
validator: (values) {
if (values == null || values.isEmpty) {
return "Required";
}
List<String> names = values.map((e) => e!.name).toList(); // 在此处更新
if (names.contains("Frog")) {
return "Frogs are weird!";
}
return null;
},
onConfirm: (List<Animal?>? values) { // 在此处更新
setState(() {
_selectedAnimals3 = values;
});
_multiSelectKey.currentState?.validate();
},
chipDisplay: MultiSelectChipDisplay(
onTap: (item) {
setState(() {
_selectedAnimals3!.remove(item);
});
_multiSelectKey.currentState?.validate();
},
),
),
);
}
}
我尝试将_selectedAnimals3和'values'都转换,并使用_animals进行初始化,但仍然出现相同的错误。我需要在确认时将_selectedAnimals3 填充为所选项。
<details>
<summary>英文:</summary>
I am unable to understand what's wrong with my code. Whatever I try I am still getting this error when trying to confirm my selection in multiselect widget.
Here's my code.
class _ParticipantsToSelectState extends State<ParticipantsToSelect> {
static List<Animal> _animals = [
Animal(id: 1, name: "Lion"),
Animal(id: 2, name: "Flamingo"),
Animal(id: 3, name: "Hippo"),
Animal(id: 4, name: "Horse"),
Animal(id: 5, name: "Tiger"),
Animal(id: 6, name: "Penguin"),
Animal(id: 7, name: "Spider"),
Animal(id: 8, name: "Snake"),
Animal(id: 9, name: "Bear"),
Animal(id: 10, name: "Beaver"),
];
final _items = _animals
.map((animal) => MultiSelectItem<Animal>(animal, animal.name))
.toList();
List<Animal?>? _selectedAnimals3 = [];
final _multiSelectKey = GlobalKey<FormFieldState<List<Animal>?>>(); // Update here
@override
void initState() {
_selectedAnimals3 = _animals;
super.initState();
}
@override
Widget build(BuildContext context) {
return Expanded(
child: MultiSelectBottomSheetField<Animal>(
key: _multiSelectKey,
initialChildSize: 0.7,
maxChildSize: 0.95,
title: Text("Animals"),
buttonText: Text("Favorite Animals"),
items: _items,
searchable: true,
validator: (values) {
if (values == null || values.isEmpty) {
return "Required";
}
List<String> names = values.map((e) => e!.name).toList(); // Update here
if (names.contains("Frog")) {
return "Frogs are weird!";
}
return null;
},
onConfirm: (List<Animal?>? values) { // Update here
setState(() {
_selectedAnimals3 = values;
});
_multiSelectKey.currentState?.validate();
},
chipDisplay: MultiSelectChipDisplay(
onTap: (item) {
setState(() {
_selectedAnimals3!.remove(item);
});
_multiSelectKey.currentState?.validate();
},
),
),
);
}
}
I tried to cast _selectedAnimals3 and also 'values' and then initialize it with _animals but getting the same error. I need to get _selectedAnimals3 populated with selected items when confirming it.
</details>
# 答案1
**得分**: 0
这是关于这个库的一个已知问题很久了,为了避免这个问题,你应该将`MultiSelectBottomSheetField<Animal?>`的类型参数设为可为空。
你的代码应该如下所示:
```dart
class _ParticipantsToSelectState extends State<ParticipantsToSelect> {
static final List<Animal> _animals = [
Animal(id: 1, name: "Lion"),
Animal(id: 2, name: "Flamingo"),
Animal(id: 3, name: "Hippo"),
Animal(id: 4, name: "Horse"),
Animal(id: 5, name: "Tiger"),
Animal(id: 6, name: "Penguin"),
Animal(id: 7, name: "Spider"),
Animal(id: 8, name: "Snake"),
Animal(id: 9, name: "Bear"),
Animal(id: 10, name: "Beaver"),
];
final _items = _animals.map((animal) => MultiSelectItem<Animal>(animal, animal.name)).toList();
List<Animal?> _selectedAnimals3 = [];
final _multiSelectKey = GlobalKey<FormFieldState<List<Animal>>>(); // 在这里进行更新
@override
void initState() {
_selectedAnimals3 = _animals;
super.initState();
}
@override
Widget build(BuildContext context) {
return Expanded(
child: MultiSelectBottomSheetField<Animal?>(
key: _multiSelectKey,
initialChildSize: 0.7,
maxChildSize: 0.95,
title: const Text("Animals"),
buttonText: const Text("Favorite Animals"),
items: _items,
searchable: true,
validator: (values) {
if (values == null || values.isEmpty) {
return "Required";
}
List<String> names = values.map((e) => e!.name).toList(); // 在这里进行更新
if (names contains ("Frog")) {
return "Frogs are weird!";
}
return null;
},
onConfirm: (List<Animal?> values) {
// 在这里进行更新
setState(() {
_selectedAnimals3 = values;
});
_multiSelectKey.currentState?.validate();
},
chipDisplay: MultiSelectChipDisplay(
onTap: (item) {
setState(() {
_selectedAnimals3.remove(item);
});
_multiSelectKey.currentState?.validate();
},
),
),
);
}
}
我建议你找到其他库来满足你的需求。
已编辑
我已经分支了这个库来解决这个问题。
我看到有多个待审核的PR,开发者似乎不活跃。
在pubspecs.yaml
中添加以下行:
multi_select_flutter:
git: https://github.com/alexsunderlion/multi_select_flutter.git
然后你的代码应该如下所示:
class _ParticipantsToSelectState extends State<ParticipantsToSelect> {
static final List<Animal> _animals = [
Animal(id: 1, name: "Lion"),
Animal(id: 2, name: "Flamingo"),
Animal(id: 3, name: "Hippo"),
Animal(id: 4, name: "Horse"),
Animal(id: 5, name: "Tiger"),
Animal(id: 6, name: "Penguin"),
Animal(id: 7, name: "Spider"),
Animal(id: 8, name: "Snake"),
Animal(id: 9, name: "Bear"),
Animal(id: 10, name: "Beaver"),
];
final _items = _animals.map((animal) => MultiSelectItem<Animal>(animal, animal.name)).toList();
List<Animal> _selectedAnimals3 = [];
final _multiSelectKey = GlobalKey<FormFieldState<List<Animal>>>(); // 在这里进行更新
@override
void initState() {
_selectedAnimals3 = _animals;
super.initState();
}
@override
Widget build(BuildContext context) {
return Expanded(
child: MultiSelectBottomSheetField<Animal>(
key: _multiSelectKey,
initialChildSize: 0.7,
maxChildSize: 0.95,
title: const Text("Animals"),
buttonText: const Text("Favorite Animals"),
items: _items,
searchable: true,
validator: (values) {
if (values == null || values.isEmpty) {
return "Required";
}
List<String> names = values.map((e) => e.name).toList(); // 在这里进行更新
if (names.contains("Frog")) {
return "Frogs are weird!";
}
return null;
},
onConfirm: (List<Animal> values) {
// 在这里进行更新
setState(() {
_selectedAnimals3 = values;
});
_multiSelectKey.currentState?.validate();
},
chipDisplay: MultiSelectChipDisplay(
onTap: (item) {
setState(() {
_selectedAnimals3.remove(item);
});
_multiSelectKey.currentState?.validate();
},
),
),
);
}
}
英文:
This is a known issue on this library for long back, to avoid this issue, you should make MultiSelectBottomSheetField<Animal?>
type parameter as nullable.
Your code should be like as following
class _ParticipantsToSelectState extends State<ParticipantsToSelect> {
static final List<Animal> _animals = [
Animal(id: 1, name: "Lion"),
Animal(id: 2, name: "Flamingo"),
Animal(id: 3, name: "Hippo"),
Animal(id: 4, name: "Horse"),
Animal(id: 5, name: "Tiger"),
Animal(id: 6, name: "Penguin"),
Animal(id: 7, name: "Spider"),
Animal(id: 8, name: "Snake"),
Animal(id: 9, name: "Bear"),
Animal(id: 10, name: "Beaver"),
];
final _items = _animals.map((animal) => MultiSelectItem<Animal>(animal, animal.name)).toList();
List<Animal?> _selectedAnimals3 = [];
final _multiSelectKey = GlobalKey<FormFieldState<List<Animal>>>(); // Update here
@override
void initState() {
_selectedAnimals3 = _animals;
super.initState();
}
@override
Widget build(BuildContext context) {
return Expanded(
child: MultiSelectBottomSheetField<Animal?>(
key: _multiSelectKey,
initialChildSize: 0.7,
maxChildSize: 0.95,
title: const Text("Animals"),
buttonText: const Text("Favorite Animals"),
items: _items,
searchable: true,
validator: (values) {
if (values == null || values.isEmpty) {
return "Required";
}
List<String> names = values.map((e) => e!.name).toList(); // Update here
if (names.contains("Frog")) {
return "Frogs are weird!";
}
return null;
},
onConfirm: (List<Animal?> values) {
// Update here
setState(() {
_selectedAnimals3 = values;
});
_multiSelectKey.currentState?.validate();
},
chipDisplay: MultiSelectChipDisplay(
onTap: (item) {
setState(() {
_selectedAnimals3.remove(item);
});
_multiSelectKey.currentState?.validate();
},
),
),
);
}
}
I suggest you to find some other library to achieve your requirement.
Edited
I have forked the library to solve this issue.
I have seen there are multiple PRs under review, looks developer is inactive.
Add change the pubspecs.yaml
with following line
multi_select_flutter:
git: https://github.com/alexsunderlion/multi_select_flutter.git
And you code should be as following.
class _ParticipantsToSelectState extends State<ParticipantsToSelect> {
static final List<Animal> _animals = [
Animal(id: 1, name: "Lion"),
Animal(id: 2, name: "Flamingo"),
Animal(id: 3, name: "Hippo"),
Animal(id: 4, name: "Horse"),
Animal(id: 5, name: "Tiger"),
Animal(id: 6, name: "Penguin"),
Animal(id: 7, name: "Spider"),
Animal(id: 8, name: "Snake"),
Animal(id: 9, name: "Bear"),
Animal(id: 10, name: "Beaver"),
];
final _items = _animals.map((animal) => MultiSelectItem<Animal>(animal, animal.name)).toList();
List<Animal> _selectedAnimals3 = [];
final _multiSelectKey = GlobalKey<FormFieldState<List<Animal>>>(); // Update here
@override
void initState() {
_selectedAnimals3 = _animals;
super.initState();
}
@override
Widget build(BuildContext context) {
return Expanded(
child: MultiSelectBottomSheetField<Animal>(
key: _multiSelectKey,
initialChildSize: 0.7,
maxChildSize: 0.95,
title: const Text("Animals"),
buttonText: const Text("Favorite Animals"),
items: _items,
searchable: true,
validator: (values) {
if (values == null || values.isEmpty) {
return "Required";
}
List<String> names = values.map((e) => e.name).toList(); // Update here
if (names.contains("Frog")) {
return "Frogs are weird!";
}
return null;
},
onConfirm: (List<Animal> values) {
// Update here
setState(() {
_selectedAnimals3 = values;
});
_multiSelectKey.currentState?.validate();
},
chipDisplay: MultiSelectChipDisplay(
onTap: (item) {
setState(() {
_selectedAnimals3.remove(item);
});
_multiSelectKey.currentState?.validate();
},
),
),
);
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论