import 'package:flutter/material.dart'; import 'package:flutter_breadcrumb/flutter_breadcrumb.dart'; import 'package:provider/provider.dart'; class _BreadCrumbNode { String name; Widget widget; _BreadCrumbNode? next; _BreadCrumbNode(this.name, this.widget); } class BreadCrumbController extends ChangeNotifier { final Widget defaultRoute; final String rootName; late _BreadCrumbNode _rootPage = _BreadCrumbNode(rootName, defaultRoute); late Widget _currentpage = _rootPage.widget; void pushPage(Widget widget, String name) { _last(_rootPage).next = _BreadCrumbNode(name, widget); _currentpage = widget; notifyListeners(); } void switchPage(String name) { final pageNode = _findPage(name, _rootPage); if (pageNode != null) { _currentpage = pageNode.widget; // hope for garbage collector to free the floating items (; pageNode.next = null; } notifyListeners(); } List getNames() { return _genNameList(_rootPage); } Widget getCurrentPage() { return _currentpage; } _BreadCrumbNode _last(_BreadCrumbNode node) { if (node.next != null) { return _last(node.next!); } else { return node; } } _BreadCrumbNode? _findPage(String name, _BreadCrumbNode node) { if (node.name == name) { return node; } if (node.next != null) { return _findPage(name, node.next!); } else { return null; } } List _genNameList(_BreadCrumbNode node) { if (node.next != null) { return _genNameList(node.next!)..insert(0, node.name); } else { return [node.name]; } } BreadCrumbController(this.defaultRoute, this.rootName); } class BreadCrumbPage extends StatefulWidget { const BreadCrumbPage( {Key? key, required this.mainPage, required this.rootName}) : super(key: key); final Widget mainPage; final String rootName; @override State createState() => _BreadCrumbPageState(); } class _BreadCrumbPageState extends State { @override Widget build(BuildContext context) { return ChangeNotifierProvider( create: (BuildContext context) => BreadCrumbController(widget.mainPage, widget.rootName), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Padding( padding: const EdgeInsets.only(left: 12, top: 8, bottom: 8), child: Consumer( builder: (_, controller, __) => BreadCrumb( items: controller .getNames() .map((e) => BreadCrumbItem( padding: const EdgeInsets.all(2), content: Text(e, style: Theme.of(context).textTheme.labelMedium), onTap: () { controller.switchPage(e); }, )) .toList(growable: false), divider: Icon( Icons.chevron_right, color: Theme.of(context).textTheme.labelMedium?.color, ), ), ), ), Divider(color: Colors.white.withOpacity(0.3), height: 1), Consumer( builder: (_, value, __) => value.getCurrentPage(), ) // currentPage ], ), ); } }