navigation-drawer
使用导航抽屉
提供了可导航到应用程序内部或访问访问外部应用程序功能,例如:切换账号(如手机QQ切换账号)。
可以一直显示在屏幕上,由菜单栏图标控制隐藏与显示。
导航抽屉被推荐使用:
需要五个或者五个以上的导航目的点。
具有两级或两级以上导航层次结构的应用程序
应用程序能够快速导航的不同地方
你在使用抽屉导航之前,你需要导入组件包:package:flutter/material.dart
你需要使用组件 MaterialApp
@override Widget build(BuildContext context) { return MaterialApp(); }
创建抽屉导航功能作为Scaffold属性drawer的值。
return Scaffold( ...... drawer: Drawer( ), ...... );
抽屉导航的子视图可以是ListView或包含ListView的Container。ListView的子级可以由DrawerHeader和ListTiles组成。
Flutter 没有明确底部或标准的抽屉导航。抽屉种类介绍
扫描二维码关注公众号,回复: 13446968 查看本文章
抽屉导航栏的可访问性
抽屉组件api支持通过semanticLabel属性标记可访问性。
子级中的内容可以有附加的可访问性标签。
抽屉导航解剖图
1、容器
2、视图头部(可选)
3、分割线(可选)
4、导航项文本遮盖层
5、手指触摸导航项文本
6、手指未触摸导航文本
7、小标题
8、屏幕除去导航栏的剩余区域
class _MyHomePageState extends State<MyHomePage> { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Activity_PhoneWindow_DecorView'), ), drawer: Drawer( child: Column( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[ Container( width: double.infinity, height: 30.0, color: Colors.blue, ), Padding( padding: const EdgeInsets.all(16.0), child: Text( 'Header / 视图头部(可选)', style: TextStyle(fontWeight: FontWeight.bold, fontSize: 12.0), ), ), Divider( height: 1, thickness: 1, ), ListTile( leading: Icon(Icons.favorite), title: Text( 'Active text overlay / 手指触摸导航项文本', textAlign: TextAlign.start, style: TextStyle(fontWeight: FontWeight.bold, fontSize: 10.0), ), onTap: () => null, ), ListTile( leading: Icon(Icons.favorite), title: Text( 'InActive text overlay / 手指未触摸导航文本', textAlign: TextAlign.start, style: TextStyle(fontWeight: FontWeight.bold, fontSize: 10.0), ), onTap: () => null, ), Padding( padding: const EdgeInsets.all(16.0), child: Text( 'Label/小标题', ), ), ], ), ), drawerScrimColor: Colors.blue.withOpacity(0.6), ); } }
抽屉导航类型
Standard navigation drawer / 标准导航抽屉
可以同时点击抽屉导航和屏幕内容。
用途:平板和台式机。
由于屏幕尺寸有限,它们不适合移动设备。
class _MyHomePageState extends State<MyHomePage> { @override Widget build(BuildContext context) { return Row( children: [ Drawer( child: ListView( // Important: Remove any padding from the ListView. padding: EdgeInsets.zero, children: <Widget>[ Padding( padding: const EdgeInsets.all(16.0), child: Text( '标准导航_顶部', style: TextStyle(fontSize: 12.0), ), ), Divider( height: 1, thickness: 1, ), ListTile( leading: Icon(Icons.favorite), title: Text( '标准导航_选项一', style: TextStyle(fontSize: 10.0), ), selected: _selectedDestination == 0, onTap: () => selectDestination(0), ), ListTile( leading: Icon(Icons.delete), title: Text( '标准导航_选项二', style: TextStyle(fontSize: 10.0), ), selected: _selectedDestination == 1, onTap: () => selectDestination(1), ), ListTile( leading: Icon(Icons.label), title: Text( '标准导航_选项三', style: TextStyle(fontSize: 10.0), ), selected: _selectedDestination == 2, onTap: () => selectDestination(2), ), Divider( height: 1, thickness: 1, ), ], ), ), VerticalDivider( width: 1, thickness: 1, ), Expanded( child: Scaffold( appBar: AppBar( title: Text(widget.title), ), body: Center( child: Container( child: Text( '$_selectedDestination', style: TextStyle(fontSize: 22.0, fontWeight: FontWeight.bold), )), ), )), ], ); } int _selectedDestination = 0; void selectDestination(int index) { setState(() { _selectedDestination = index; }); } }
Modal navigation drawer / 模态导航抽屉
只可以点击导航栏,屏幕内容无法触摸
位于应用程序的UI之上,不会影响屏幕的布局。
class _MyHomePageState extends State<MyHomePage> { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Activity_PhoneWindow_DecorView'), ), drawer: Drawer( child: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ const Text('This is the Drawer'), ElevatedButton( onPressed: null, child: const Text('Close Drawer'), ), ], ), ), ), body: Center( child: Container( width: double.infinity, height: double.infinity, color: Colors.green, child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start, children: [ _activity(), Container( padding: EdgeInsets.only(left: 10.0, top: 10.0), margin: EdgeInsets.all( 20.0, ), color: Colors.orange, width: MediaQuery.of(context).size.width, height: MediaQuery.of(context).size.height - 200.0, child: Column( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ _phoneWindow(), _decorView(), ], ), ), ], ), ), ), //child: Text.rich(TextSpan(text: 'final InlineSpan textSpan / The text to display as a [InlineSpan]')), ); } Container _decorView() { return Container( padding: EdgeInsets.only(left: 10.0, top: 10.0), margin: EdgeInsets.all( 20.0, ), color: Colors.redAccent, width: MediaQuery.of(context).size.width - 80.0, height: MediaQuery.of(context).size.height - 300.0, child: Column( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'DecorView', style: TextStyle( fontSize: 20.0, fontWeight: FontWeight.bold, color: Colors.white), ), Container( width: double.infinity, padding: EdgeInsets.only(bottom: 10.0, top: 10.0), margin: EdgeInsets.only(left: 10.0, top: 10.0, right: 20.0), color: Colors.black.withOpacity(0.5), alignment: Alignment.center, child: Text( 'TitleView', style: TextStyle( fontSize: 20.0, fontWeight: FontWeight.bold, color: Colors.white), ), ), Expanded( flex: 1, child: GestureDetector( onTap: () { Navigator.of(context).pushNamed('/TwoPage'); }, child: Container( width: double.infinity, padding: EdgeInsets.only(bottom: 10.0, top: 10.0), margin: EdgeInsets.only( left: 10.0, top: 10.0, right: 20.0, bottom: 20.0), color: Colors.black.withOpacity(0.5), alignment: Alignment.center, child: Text( 'ContentView', style: TextStyle( fontSize: 20.0, fontWeight: FontWeight.bold, color: Colors.white), ), ), ), ), ], ), ); } Text _phoneWindow() { return Text( 'PhoneWindow', style: TextStyle( fontSize: 20.0, fontWeight: FontWeight.bold, color: Colors.white), ); } Container _activity() { return Container( padding: EdgeInsets.only(left: 10.0, top: 10.0), child: Text( 'Activity', style: TextStyle( fontSize: 20.0, fontWeight: FontWeight.bold, color: Colors.white), ), ); } }
Bottom navigation drawer / 底部导航栏
底部导航抽屉是固定在屏幕底部而不是左侧或右侧边缘的模式抽屉。
仅仅用于底部导航。
注意:Flutter 中没有底部抽屉,但是可以通过创建由ListTile、分隔符和文本小部件组成的自定义小部件来创建底部导航。
PositionedTransition 被用着抽屉动画的显示与隐藏。
抽屉的打开和关闭应该通过点击脚手架中bottomNavigationBar中BottomAppBar内的菜单图标来触发。
class _MyHomePageState extends State<MyHomePage> { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Activity_PhoneWindow_DecorView'), ), bottomNavigationBar: BottomAppBar( child: Row( children: [ IconButton( icon: Icon(Icons.menu), onPressed: () { // Animate a bottom drawer }, ), Spacer(), IconButton(icon: Icon(Icons.search), onPressed: () {}), IconButton(icon: Icon(Icons.more_vert), onPressed: () {}), ], ), ), ); } }