我想检查列表中是否存在任何小部件?

时间:2019-08-31 10:26:42

标签: flutter

我想从列表中加载页面,当用户在抽屉中点击某个项目时,他可以转到该页面(如果已打开),否则该小部件将加载到所选页面中。 但是我找不到列表if(myList.contains(Widget1())) => print('it exist');中是否已经存在该小部件。一个人告诉我覆盖hashCodeoperator==

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
}

2 个答案:

答案 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(),
      ) ,
    );
...