开篇寄语
这一篇文章主要是学习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; }); }, ), ), ], ), ); } }
生成效果如下图所示:
点击前 点击后
- 我的微信
- 微信扫一扫加好友
- 我的微信公众号
- 扫描关注公众号