
开篇寄语
这一篇文章主要是学习Navigation,就是页面中的各种导航,页面的切换之类的,这个在设计App中也很常见,可以极大扩充App的页面广度和深度,让用户更长时间驻留在App上,导航发挥了重要的作用,所以不可不学也,本篇介绍几种常见的导航形式,其实前一篇文章AppBar中也有一部分,主要是底部导航,也算是导航一种啦,有兴趣可以看一看,咱们开始吧。
前情提要
- 《Flutter制作自己的第一个全平台APP学习之Widgets篇》
- 《Flutter制作自己的第一个全平台APP学习之Layouts篇》
- 《Flutter制作自己的第一个全平台APP学习之Lists篇》
- 《Flutter制作自己的第一个全平台APP学习之AppBar篇》
内容详情
以下内容大多是更改lib下的main.dart文件内容,删掉里面的内容,复制粘贴代码,开启调试就可以出现了。
Tabs
- 上方出现的菜单栏,可以进行选择,类似于之前学过的底部菜单栏,可以进行选择,试举一例:
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: TabBarDemo(),
);
}
}
class TabBarDemo extends StatefulWidget {
@override
_TabBarDemoState createState() => _TabBarDemoState();
}
class _TabBarDemoState extends State<TabBarDemo>
with SingleTickerProviderStateMixin {
late TabController _controller;
int _selectedIndex = 0;
List<Widget> list = [
Tab(icon: Icon(Icons.card_travel)),
Tab(icon: Icon(Icons.add_shopping_cart)),
];
@override
void initState() {
super.initState();
// Create TabController for getting the index of current tab
_controller = TabController(length: list.length, vsync: this);
_controller.addListener(() {
setState(() {
_selectedIndex = _controller.index;
});
print("Selected Index: " + _controller.index.toString());
});
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
bottom: TabBar(
onTap: (index) {
// Should not used it as it only called when tab options are clicked,
// not when user swapped
},
controller: _controller,
tabs: list,
),
title: Text('Tabs Demo'),
),
body: TabBarView(
controller: _controller,
children: [
Center(
child: Text(
_selectedIndex.toString(),
style: TextStyle(fontSize: 40),
)),
Center(
child: Text(
_selectedIndex.toString(),
style: TextStyle(fontSize: 40),
)),
],
),
),
);
}
}
生成的效果如下图所示:

Routes
- 分页跳转,点击首页跳转到第二页,点击第二页跳转到第三页,在构建App中是一种很实用的方法,试举例如下:
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: HomeScreen(),
);
}
}
class HomeScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Center(
child: TextButton(
child: Text('View Details'),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return DetailScreen();
}),
);
},
),
),
);
}
}
class DetailScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Center(
child: TextButton(
child: Text('Pop!'),
onPressed: () {
Navigator.pop(context);
},
),
),
);
}
}
生成效果如下图所示:

首页 
跳转页
除了使用Navigator,还可以使用routes,试举例如下:
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
routes: {
'/': (context) => HomeScreen(),
'/details': (context) => DetailScreen(),
},
);
}
}
class HomeScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Center(
child: TextButton(
child: Text('View Details'),
onPressed: () {
Navigator.pushNamed(
context,
'/details',
);
},
),
),
);
}
}
class DetailScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Center(
child: TextButton(
child: Text('Pop!'),
onPressed: () {
Navigator.pop(context);//也可换成这样Navigator.popUntil(context, ModalRoute.withName('/'));
},
),
),
);
}
}
生成的效果与之前的一致。
Drawer
- 左侧弹出菜单,点击左上角从左侧弹出一个占据多半屏的栏,也是一种菜单形式,试举例如下:
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
routes: {
'/': (context) => HomeScreen(),
},
);
}
}
class HomeScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Drawer Demo'),
),
drawer: Drawer(
child: ListView(
padding: EdgeInsets.zero,
children: const <Widget>[
DrawerHeader(
decoration: BoxDecoration(
color: Colors.blue,
),
child: Text(
'Drawer Header',
style: TextStyle(
color: Colors.white,
fontSize: 24,
),
),
),
ListTile(
leading: Icon(Icons.message),
title: Text('Messages'),
),
ListTile(
leading: Icon(Icons.account_circle),
title: Text('Profile'),
),
ListTile(
leading: Icon(Icons.settings),
title: Text('Settings'),
),
],
),
),
);
}
}
生成效果如下图所示:

有左侧的,自然就有右侧的,试举例如下:
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
// Hide the debug banner
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
home: HomePage(),
);
}
}
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
endDrawer: Drawer(
child: Container(
alignment: Alignment.center,
child: Text('Hello!'),
),
),
appBar: AppBar(
title: Text('Flutter Demo'),
),
body: SafeArea(
child: Center(),
));
}
}
生成效果如下图所示:

分页滑动
- TabBar的变型,可以选取不同的页面,试举例如下:
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: MyScreen(),
);
}
}
class MyScreen extends StatelessWidget {
static const kIcons = <Icon>[
Icon(Icons.event),
Icon(Icons.home),
Icon(Icons.android),
Icon(Icons.alarm),
Icon(Icons.face),
Icon(Icons.language),
];
@override
Widget build(BuildContext context) {
return DefaultTabController(
length: kIcons.length,
// Use a Builder here, otherwise `DefaultTabController.of(context)` below
// returns null.
child: Builder(
builder: (BuildContext context) => Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: <Widget>[
const TabPageSelector(),
Expanded(
child: IconTheme(
data: IconThemeData(
size: 128.0,
color: Theme.of(context).colorScheme.secondary,
),
child: const TabBarView(children: kIcons),
),
),
ElevatedButton(
onPressed: () {
final TabController? controller =
DefaultTabController.of(context);
if (!controller!.indexIsChanging) {
controller.animateTo(kIcons.length - 1);
}
},
child: const Text('SKIP'),
)
],
),
),
));
}
}
生成效果如下图所示:

NavigationRail
- 这个是另外一种导航菜单,可以延伸展开,有比较强的灵活度,试举一例:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
/// This Widget is the main application widget.
class MyApp extends StatelessWidget {
static const String _title = 'Flutter Code Sample';
@override
Widget build(BuildContext context) {
return MaterialApp(
title: _title,
home: MyStatefulWidget(),
);
}
}
class MyStatefulWidget extends StatefulWidget {
MyStatefulWidget({Key? key}) : super(key: key);
@override
_MyStatefulWidgetState createState() => _MyStatefulWidgetState();
}
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
var selectedIndex = 0;
var isRailExtended = false;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Navigation rail"),
),
body: Row(
children: <Widget>[
NavigationRail(
selectedIndex: selectedIndex,
onDestinationSelected: (index) {
setState(() {
selectedIndex = index;
});
},
extended: isRailExtended,
elevation: 10,
leading: Text("You can add\n widget on leading"),
destinations: [
NavigationRailDestination(
icon: Icon(Icons.ac_unit), label: Text("Ice flake")),
NavigationRailDestination(
icon: Icon(Icons.access_time), label: Text("Main time")),
NavigationRailDestination(
icon: Icon(Icons.mic), label: Text("Start record")),
NavigationRailDestination(
icon: Icon(Icons.business_center),
label: Text("My Bussiness")),
NavigationRailDestination(
icon: Icon(Icons.photo_camera), label: Text("View camera")),
NavigationRailDestination(
icon: Icon(Icons.book), label: Text("Some audiobook")),
],
trailing: OutlinedButton(
child: Text("Toggle rail"),
onPressed: () {
setState(() {
isRailExtended = !isRailExtended;
});
},
),
),
],
),
);
}
}
生成效果如下图所示:

点击前 
点击后
- 我的微信
- 微信扫一扫加好友
-
- 我的微信公众号
- 扫描关注公众号
-





