Flutter 当类用作值而不是字符串时,颤振下拉菜单失败
我有以下代码Flutter 当类用作值而不是字符串时,颤振下拉菜单失败,flutter,dart,Flutter,Dart,我有以下代码 import 'package:flutter/material.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'My App', theme: ThemeData(
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'My App',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: SimpleScreen());
}
}
class SimpleScreen extends StatefulWidget {
@override
_SimpleScreenState createState() => _SimpleScreenState();
}
class _SimpleScreenState extends State<SimpleScreen> {
ItemCls currentValue = ItemCls(name: 'one', price: 1);
List<DropdownMenuItem> _menuItems = <DropdownMenuItem>[
DropdownMenuItem(
child: new Container(
child: new Text("Item#1"),
width: 200.0,
),
value: ItemCls(name: 'one', price: 1)),
DropdownMenuItem(
child: new Container(
child: new Text("Item#2"),
width: 200.0,
),
value: ItemCls(name: 'two', price: 2))
];
@override
Widget build(BuildContext context) {
return new Scaffold(
body: Center(
child: DropdownButton(
value: currentValue,
items: _menuItems,
onChanged: onChanged,
style: Theme.of(context).textTheme.title,
),
));
}
void onChanged(value) {
setState(() {
currentValue = value;
});
// print(value);
}
}
class ItemCls {
final String name;
final double price;
const ItemCls({
@required this.name,
@required this.price,
}) : assert(name != null),
assert(price != null);
}
导入“包装:颤振/材料.省道”;
void main()=>runApp(MyApp());
类MyApp扩展了无状态小部件{
@凌驾
小部件构建(构建上下文){
返回材料PP(
标题:“我的应用程序”,
主题:主题数据(
主样本:颜色。蓝色,
),
主页:SimpleScreen());
}
}
类SimpleScreen扩展StatefulWidget{
@凌驾
_SimpleScreenState createState()=>\u SimpleScreenState();
}
类_SimpleScreenState扩展了状态{
ItemCls currentValue=ItemCls(名称:“一”,价格:1);
列表_菜单项=[
下拉菜单项(
子容器:新容器(
子项:新文本(“第1项”),
宽度:200.0,
),
价值:ItemCls(名称:“一”,价格:1)),
下拉菜单项(
子容器:新容器(
子项:新文本(“第2项”),
宽度:200.0,
),
价值:ItemCls(名称:'2',价格:2))
];
@凌驾
小部件构建(构建上下文){
归还新脚手架(
正文:中(
孩子:下拉按钮(
值:当前值,
项目:\菜单项,
一旦改变:一旦改变,
样式:Theme.of(context).textTheme.title,
),
));
}
更改后无效(值){
设置状态(){
当前值=当前值;
});
//印刷品(价值);
}
}
类项CLS{
最后的字符串名;
最终双倍价格;
常数项({
@需要此名称,
@需要这个价格,
}):assert(name!=null),
断言(价格!=null);
}
这是失败的
在构建SimpleScreen(dirty,
依赖项:[[u LocalizationsScope-[GlobalKey[b1ff3],
_InheritedTheme],状态:_SimpleScreenState#d473f):“包:颤振/src/material/dropdown.dart”:失败的断言:行
620位置15:'items==null | | items.isEmpty | | value==null||
items.where((DropdownMenuItem项)=>item.value==value).length
==1”:不正确
每个
下拉菜单项中的值必须是唯一的。Dart通过两种方式确保唯一性:定义==
运算符和调用对象上的hashCode
。您需要将这两个项添加到ItemCls
类:
class ItemCls{
最后的字符串名;
最终双倍价格;
常数项({
@需要此名称,
@需要这个价格,
}):assert(name!=null),
断言(价格!=null);
布尔运算符==(动态其他){
返回其他is ItemCls&&
this.name==other.name&&
this.price==其他.price;
}
@凌驾
int获取哈希代码{
//源代码的散列码算法https://www.sitepoint.com/how-to-implement-javas-hashcode-correctly/
int hashCode=1;
hashCode=(23*hashCode)+this.name.hashCode;
hashCode=(23*hashCode)+this.price.hashCode;
返回哈希码;
}
}
原因
实例ItemCls currentValue=ItemCls(名称:“一”,价格:1)代码>不相等值:ItemCls(名称:'one',价格:1)),
它们有不同的地址并被视为不同的值
因此,下拉按钮认为默认值ItemCls(名称:'one',价格:1)
在选择列表中不存在
解决方案
使用List
包含您的选择,并将currentValue
指向列表的第一个值
ItemCls currentValue;
static List<ItemCls> itemList = [
ItemCls(name: 'one', price: 1),
ItemCls(name: 'two', price: 2)
];
...
DropdownMenuItem<ItemCls>(
child: new Container(
child: new Text("Item#1"),
width: 200.0,
),
value: itemList[0]),
...
void initState() {
// TODO: implement initState
currentValue = itemList[0];
}
ItemCls当前值;
静态列表项列表=[
项目CLS(名称:“一”,价格:1),
ItemCls(名称:'2',价格:2)
];
...
下拉菜单项(
子容器:新容器(
子项:新文本(“第1项”),
宽度:200.0,
),
值:itemList[0]),
...
void initState(){
//TODO:实现initState
currentValue=itemList[0];
}
工作演示
完整代码
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'My App',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: SimpleScreen());
}
}
class SimpleScreen extends StatefulWidget {
@override
_SimpleScreenState createState() => _SimpleScreenState();
}
class _SimpleScreenState extends State<SimpleScreen> {
ItemCls currentValue;
static List<ItemCls> itemList = [
ItemCls(name: 'one', price: 1),
ItemCls(name: 'two', price: 2)
];
List<DropdownMenuItem<ItemCls>> _menuItems = <DropdownMenuItem<ItemCls>>[
DropdownMenuItem<ItemCls>(
child: new Container(
child: new Text("Item#1"),
width: 200.0,
),
value: itemList[0]),
DropdownMenuItem<ItemCls>(
child: new Container(
child: new Text("Item#2"),
width: 200.0,
),
value: itemList[1])
];
@override
void initState() {
// TODO: implement initState
currentValue = itemList[0];
}
@override
Widget build(BuildContext context) {
return new Scaffold(
body: Center(
child: DropdownButton<ItemCls>(
value: currentValue,
items: _menuItems,
onChanged: onChanged,
style: Theme.of(context).textTheme.title,
),
));
}
void onChanged(value) {
setState(() {
currentValue = value;
});
// print(value);
}
}
class ItemCls {
final String name;
final double price;
const ItemCls({
@required this.name,
@required this.price,
}) : assert(name != null),
assert(price != null);
}
导入“包装:颤振/材料.省道”;
void main()=>runApp(MyApp());
类MyApp扩展了无状态小部件{
@凌驾
小部件构建(构建上下文){
返回材料PP(
标题:“我的应用程序”,
主题:主题数据(
主样本:颜色。蓝色,
),
主页:SimpleScreen());
}
}
类SimpleScreen扩展StatefulWidget{
@凌驾
_SimpleScreenState createState()=>\u SimpleScreenState();
}
类_SimpleScreenState扩展了状态{
项目CLS当前值;
静态列表项列表=[
项目CLS(名称:“一”,价格:1),
ItemCls(名称:'2',价格:2)
];
列表_菜单项=[
下拉菜单项(
子容器:新容器(
子项:新文本(“第1项”),
宽度:200.0,
),
值:itemList[0]),
下拉菜单项(
子容器:新容器(
子项:新文本(“第2项”),
宽度:200.0,
),
值:itemList[1])
];
@凌驾
void initState(){
//TODO:实现initState
currentValue=itemList[0];
}
@凌驾
小部件构建(构建上下文){
归还新脚手架(
正文:中(
孩子:下拉按钮(
值:当前值,
项目:\菜单项,
一旦改变:一旦改变,
样式:Theme.of(context).textTheme.title,
),
));
}
更改后无效(值){
设置状态(){
当前值=当前值;
});
//印刷品(价值);
}
}
类项CLS{
最后的字符串名;
最终双倍价格;
常数项({
@需要此名称,
@需要这个价格,
}):assert(name!=null),
断言(价格!=null);
}