我想从列表中加载页面,当用户在抽屉中点击某个项目时,他可以转到该页面(如果已打开),否则该小部件将加载到所选页面中。
但是我找不到列表if(myList.contains(Widget1())) => print('it exist');
中是否已经存在该小部件。一个人告诉我覆盖hashCode
和operator==
class Widget6 extends StatelessWidget {
final String title = 'Widget6';
final Icon icon = Icon(Icons.assessment);
@override
Widget build(BuildContext context) {
return Center(
child: icon,
);
}
@override
bool operator ==(dynamic other) {
final Widget6 typedOther = other;
return title == typedOther.title && icon == typedOther.icon;
}
@override
int get hashCode => hashValues(title, icon);
}
如果这样做,我将无法对这些小部件使用任何子小部件。正在获取异常,例如:type 'Center' is not a subtype of type 'Widget6'
。我从flutter画廊复制了此文档,但找不到很好的文档/指南。抱歉,我是初学者。
下面的完整代码
class _MyHomePageState extends State<MyHomePage> {
List pageList = [
Widget1(),
Widget2(),
Widget3(),
Widget4(),
];
PageController _pageController;
int _selectedIndex = 0;
@override
void initState() {
_pageController = PageController(
initialPage: _selectedIndex,
);
super.initState();
}
void navigatePage(Widget widget) {
// problem is here
if (pageList.contains(widget)) {
_pageController.animateToPage(pageList.indexOf(widget, 0),
duration: Duration(milliseconds: 300), curve: Curves.ease);
}
else {
setState(() {
pageList.removeAt(_pageController.page.toInt());
pageList.insert(_pageController.page.toInt(), widget);
});
_pageController.animateToPage(_pageController.page.toInt(),
duration: Duration(milliseconds: 300), curve: Curves.ease);
}
Navigator.pop(context);
}
@override
Widget build(BuildContext context) {
return Scaffold(
drawer: Drawer(
child: ListView(
children: <Widget>[
ListTile(
title: Text('Widget1'),
onTap: () => navigatePage(
Widget1(),
),
),
ListTile(
title: Text('Widget2'),
onTap: () => navigatePage(
Widget2(),
),
),
ListTile(
title: Text('Widget3'),
onTap: () => navigatePage(
Widget3(),
),
),
ListTile(
title: Text('Widget4'),
onTap: () => navigatePage(
Widget4(),
),
),
ListTile(
title: Text('Widget5'),
onTap: () => navigatePage(
Widget5(),
),
),
ListTile(
title: Text('Widget6'),
onTap: () => navigatePage(
Widget6(),
),
),
],
),
),
appBar: AppBar(
title: Text(widget.title),
),
body: PageView.builder(
onPageChanged: (newPage) {
setState(() {
this._selectedIndex = newPage;
});
},
controller: _pageController,
itemBuilder: (context, index) {
return Container(
child: pageList[index],
);
},
itemCount: pageList.length,
),
bottomNavigationBar: BottomNavigationBar(
currentIndex: _selectedIndex,
onTap: (index) => setState(() {
_selectedIndex = index;
_pageController.animateToPage(index,
duration: Duration(milliseconds: 300), curve: Curves.ease);
}),
items: pageList.map((page) {
return BottomNavigationBarItem(
backgroundColor: Colors.deepOrangeAccent,
icon: page.icon,
title: Text(page.title));
}).toList(),
),
);
}
}
此处为虚拟小部件列表
class Widget1 extends StatelessWidget {
final String title = 'Widget1';
final Icon icon = Icon(Icons.school);
@override
Widget build(BuildContext context) {
return Center(
child: icon,
);
}
}
class Widget2 extends StatelessWidget {
// only title and icon are changed
}
class Widget3 extends StatelessWidget {
// only title and icon are changed
}
class Widget4 extends StatelessWidget {
// only title and icon are changed
}
class Widget5 extends StatelessWidget {
// only title and icon are changed
}
class Widget6 extends StatelessWidget {
// only title and icon are changed
}
答案 0 :(得分:1)
好的,我找到了解决方案。它与operator==
覆盖有关
我错过了这一行if (runtimeType != other.runtimeType) return false;
整个代码保持不变。
@override
// ignore: hash_and_equals
bool operator ==(dynamic other) {
if (runtimeType != other.runtimeType) return false;
final Widget6 typedOther = other;
return title == typedOther.title;
}
答案 1 :(得分:0)
@Ahmed对不起,我很晚才回答,我决定将其放入答案而不是评论中。
一个解决方案是您的,它可以覆盖==
,但我当时想使用Key
,然后使用类似以下方式来代替contains
方法:
if(myList.indexWhere((Widget widget)=> widget.key==_key) != -1)...
您可以将图标和标题存储为地图或模块,而不必制作6个不同的小部件。
您可以创建另一个文件,像这样module.dart
:
class Module {
final String title;
final Icon icon;
Module(this.title, this.icon);
@override
int get hashCode => hashValues(title.hashCode, icon.hashCode);
@override
bool operator ==(other) {
if (!identical(this, other)) {
return false;
}
return other is Module &&
this.title.compareTo(other.title) == 0 &&
this.icon == other.icon;
}
}
然后创建另一个构建页面的文件,说mywidget.dart
,如下所示:
class MyWidget extends StatelessWidget {
final Module module;
MyWidget({Key key,@required this.module}) : super(key: key);
@override
Widget build(BuildContext context) {
return Center(
child: module.icon,
);
}
}
然后在每个ListTile的onTap
上,像这样导航:
...
ListTile(
title: Text('Widget1'),
onTap: () => navigatePage(
MyWidget(module: Module('Widget1', Icon(Icons.school)),)
),
),
...
因此,不是存储小部件,而是存储声明的Type(此处模块)。
您也可以使用列表的map
为每个模块构建ListTile
中的每个ListView
,而不必一个个地进行。 (如果抽屉上的每个项目都相似),则类似这样:
List<Module> myTabs = [
Module('Widget1', Icon(Icons.school)),
Module('Widget2', Icon(Icons.home)),
];
...
Drawer(
child: ListView(
children:myTabs.map((Module module)=> ListTile(
title:Text( module.title),
onTap: navigatePage(MyWidget(module: module,)),
)).toList(),
) ,
);
...