有图有真相:
想要实现一个面包屑导航栏需要考虑一下问题:
1,实现一个面包屑导航栏的效果并不难
2,面包屑下方的页面状态如何维护
3,导航栏和下方页面如何实现数据同步
这里说一下本人的愚见,大佬们有其他思路可以在评论区留言,大家相互学习:
1,导航栏界面,我直接用一个Row布局生成的
2,首先面包屑下方的页面状态可以使用Navigator进行维护,这样省去了好多处理路由的问题,并配置GlobalKey,用来在任何位置都能找到自己的Navigator;这里用到的Navigator和MaterialAPP 中的不是一个,需要注意;
3,数据同步,使用Provider;
下面直接看完整源码:
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
/// 创建日期: 2020/8/25
/// 作者: lijianbin
/// 描述:
///使用Navigator和Provider实现面包屑导航按钮
class BlockWidget extends StatelessWidget {
final String title;
const BlockWidget({Key key, this.title}) : super(key: key);
@override
Widget build(BuildContext context) {
return Row(
mainAxisSize: MainAxisSize.min,
children: [Text(title), Icon(Icons.keyboard_arrow_right)],
);
}
}
///路由页面
class NavigatorPage extends StatefulWidget {
final String title;
final Widget child;
const NavigatorPage({Key key, this.title, this.child}) : super(key: key);
@override
_NavigatorPageState createState() => _NavigatorPageState();
}
class _NavigatorPageState extends State<NavigatorPage> {
@override
Widget build(BuildContext context) {
return widget.child;
}
}
///路由控制器
class NavigatorController with ChangeNotifier {
List<NavigatorPage> _history = List();
List<NavigatorPage> get history => _history;
get size => _history.length;
///入栈
void push(NavigatorPage page) {
NavigatorState navigator = navigatorKey.currentState;
navigator.push(MaterialPageRoute(builder: (context) {
return page;
}));
_history.add(page);
notifyListeners();
}
///出栈
void pop() {
NavigatorState navigator = navigatorKey.currentState;
if (navigator.canPop()) {
navigator.pop();
_history.removeLast();
notifyListeners();
}
}
///出栈到指定索引
void popUntil(int index) {
while (size > index) {
pop();
}
}
}
final GlobalKey<NavigatorState> navigatorKey = GlobalKey();
///路由导航器首页
class NavigatorHomeWidget extends StatelessWidget {
final NavigatorPage home;
const NavigatorHomeWidget({Key key, this.home}) : super(key: key);
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider.value(
value: NavigatorController(),
child: Column(
children: [
Container(
alignment: Alignment.centerLeft,
color: Colors.white,
width: double.infinity,
child: Consumer<NavigatorController>(
builder: (context, NavigatorController data, child) {
List<NavigatorPage> pages = List();
pages.add(home);
pages.addAll(data.history);
List<GestureDetector> blocks = List();
for (int i = 0; i < pages.length; i++) {
blocks.add(
GestureDetector(
onTap: () {
data.popUntil(i);
},
child: BlockWidget(title: pages[i].title),
),
);
}
return SingleChildScrollView(
reverse: true,
scrollDirection: Axis.horizontal,
child: Row(
children: blocks,
),
);
},
),
),
Expanded(
child: Builder(
builder: (context) {
return Navigator(
key: navigatorKey,
initialRoute: '/',
onGenerateRoute: (settings) {
WidgetBuilder builder;
switch (settings.name) {
case '/':
builder = (context) => home;
break;
}
return MaterialPageRoute(
builder: builder, settings: settings);
},
);
},
),
),
],
),
);
}
}
demo中的引用:
void main() {
runApp(MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('面包屑导航'),
),
body: HomePage()),
));
}
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
List<NavigatorPage> history = List();
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
color: Colors.grey,
child: Center(
child: Container(
height: 500,
child: NavigatorHomeWidget(
home: NavigatorPage(
title: "首页",
child: PA(
title: '首页',
),
),
),
),
),
),
);
}
}
class PA extends StatefulWidget {
final title;
const PA({Key key, this.title}) : super(key: key);
@override
_PAState createState() => _PAState();
}
var index = 0;
class _PAState extends State<PA> {
@override
Widget build(BuildContext context) {
return Container(
color: Colors.greenAccent,
child: Column(
children: [
RaisedButton(
child: Text('push'),
onPressed: () {
Provider.of<NavigatorController>(context, listen: false).push(
NavigatorPage(
title: "page:${++index}",
child: PA(
title: '${index}',
),
),
);
},
),
RaisedButton(
child: Text('pop'),
onPressed: () {
Provider.of<NavigatorController>(context, listen: false).pop();
}),
Container(
child: Text('当前页:${widget.title}'),
),
],
),
);
}
}