写点什么

在 Flutter 中使用 NavigationRail 和 BottomNavigationBar

作者:坚果
  • 2022 年 3 月 14 日
  • 本文字数:3945 字

    阅读完需:约 13 分钟

在 Flutter 中使用 NavigationRail 和 BottomNavigationBar

作者:坚果

公众号:"大前端之旅"

华为云享专家,InfoQ 签约作者,阿里云专家博主,51CTO 博客首席体验官,开源项目GVA成员之一,专注于大前端技术的分享,包括 Flutter,鸿蒙,小程序,安卓,VUE,JavaScript 等。


本文将向您展示如何使用 NavigationRail BottomNavigationBar 在 Flutter 中创建****自适应布局。我们将浏览一下这个概念,然后通过一个完整的例子来在实践中应用这个概念。


NavigationRail 小部件用于创建位于应用左侧或右侧的“垂直标签栏”。它非常适合平板电脑、笔记本电脑、电视等宽屏设备。它通常包含多个视图,让用户可以轻松地在不同视图之间切换。


BottomNavigationBar 部件用于创建非常适合智能手机的底部标签栏。它由多个选项卡组成,让用户可以轻松地在视图之间导航。


我们可以使用 NavigationRail BottomNavigationBar 来构建现代自适应布局。当屏幕很大时,我们显示 NavigationRail,当屏幕较小时,我们显示 BottomNavigationBar。一次只出现其中一个。要检测屏幕宽度,我们可以使用:


MediaQuery.of(context).size.width
复制代码

这个例子

应用预览

我们要构建的应用程序有一个导航栏、一个底部标签栏和 4 个不同的视图:主页、Feed、收藏夹和设置。每个视图都与底部标签栏的一个标签和导航栏的一个项目相连。


  • 如果屏幕宽度小于 640 像素,则将呈现底部标签栏,而不会显示左侧导航栏。

  • 如果屏幕宽度等于或大于 640 像素,则不会呈现底部标签栏,而会显示左侧导航栏。


以下是它的工作原理:

截图

代码

这是生成上述应用程序的完整代码(带有解释):


// main.dartimport 'package:flutter/material.dart';
void main() { runApp(const MyApp());}
class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return MaterialApp( // Remove the debug banner debugShowCheckedModeBanner: false, title: '大前端之旅', theme: ThemeData(primarySwatch: Colors.indigo), home: const HomeScreen()); }}
class HomeScreen extends StatefulWidget { const HomeScreen({Key? key}) : super(key: key);
@override _HomeScreenState createState() => _HomeScreenState();}
class _HomeScreenState extends State<HomeScreen> { // The contents of views // Only the content associated with the selected tab is displayed on the screen final List<Widget> _mainContents = [ // Content for Home tab Container( color: Colors.yellow.shade100, alignment: Alignment.center, child: const Text( 'Home', style: TextStyle(fontSize: 40), ), ), // Content for Feed tab Container( color: Colors.purple.shade100, alignment: Alignment.center, child: const Text( 'Feed', style: TextStyle(fontSize: 40), ), ), // Content for Favorites tab Container( color: Colors.red.shade100, alignment: Alignment.center, child: const Text( 'Favorites', style: TextStyle(fontSize: 40), ), ), // Content for Settings tab Container( color: Colors.pink.shade300, alignment: Alignment.center, child: const Text( 'Settings', style: TextStyle(fontSize: 40), ), ) ];
// The index of the selected tab // In the beginning, the Home tab is selected int _selectedIndex = 0;
@override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('大前端之旅'), ), // Show the bottom tab bar if screen width < 640 bottomNavigationBar: MediaQuery.of(context).size.width < 640 ? BottomNavigationBar( currentIndex: _selectedIndex, unselectedItemColor: Colors.grey, selectedItemColor: Colors.indigoAccent, // called when one tab is selected onTap: (int index) { setState(() { _selectedIndex = index; }); }, // bottom tab items items: const [ BottomNavigationBarItem( icon: Icon(Icons.home), label: 'Home'), BottomNavigationBarItem( icon: Icon(Icons.feed), label: 'Feed'), BottomNavigationBarItem( icon: Icon(Icons.favorite), label: 'Favorites'), BottomNavigationBarItem( icon: Icon(Icons.settings), label: 'Settings') ]) : null, body: Row( mainAxisSize: MainAxisSize.max, children: [ // Show the navigaiton rail if screen width >= 640 if (MediaQuery.of(context).size.width >= 640) NavigationRail( minWidth: 55.0, selectedIndex: _selectedIndex, // Called when one tab is selected onDestinationSelected: (int index) { setState(() { _selectedIndex = index; }); }, labelType: NavigationRailLabelType.all, selectedLabelTextStyle: const TextStyle( color: Colors.amber, ), leading: Column( children: const [ SizedBox( height: 8, ), CircleAvatar( radius: 20, child: Icon(Icons.person), ), ], ), unselectedLabelTextStyle: const TextStyle(), // navigation rail items destinations: const [ NavigationRailDestination( icon: Icon(Icons.home), label: Text('Home')), NavigationRailDestination( icon: Icon(Icons.feed), label: Text('Feed')), NavigationRailDestination( icon: Icon(Icons.favorite), label: Text('Favorites')), NavigationRailDestination( icon: Icon(Icons.settings), label: Text('Settings')), ], ),
// Main content // This part is always shown // You will see it on both small and wide screen Expanded(child: _mainContents[_selectedIndex]), ], ), ); }}
复制代码

构造函数和引用

NavigationRail 构造函数:


NavigationRail({  Key? key,   Color? backgroundColor,   bool extended = false,   Widget? leading,   Widget? trailing,   required List<NavigationRailDestination> destinations,   required int selectedIndex,   ValueChanged<int>? onDestinationSelected,   double? elevation,   double? groupAlignment,   NavigationRailLabelType? labelType,   TextStyle? unselectedLabelTextStyle,   TextStyle? selectedLabelTextStyle,   IconThemeData? unselectedIconTheme,   IconThemeData? selectedIconTheme,   double? minWidth,   double? minExtendedWidth,   bool? useIndicator,   Color? indicatorColor})
复制代码


BottomNavigationBar 构造函数:


BottomNavigationBar({  Key? key,   required List<BottomNavigationBarItem> items,   ValueChanged<int>? onTap,   int currentIndex = 0,   double? elevation,   BottomNavigationBarType? type,   Color? fixedColor,   Color? backgroundColor,   double iconSize = 24.0,   Color? selectedItemColor,   Color? unselectedItemColor,   IconThemeData? selectedIconTheme,   IconThemeData? unselectedIconTheme,   double selectedFontSize = 14.0,   double unselectedFontSize = 12.0,   TextStyle? selectedLabelStyle,   TextStyle? unselectedLabelStyle,   bool? showSelectedLabels,   bool? showUnselectedLabels,   MouseCursor? mouseCursor,   bool? enableFeedback,   BottomNavigationBarLandscapeLayout? landscapeLayout})
复制代码


参考:


后记

您已经学习了一种使用 NavigationRail 和 BottomNavigationBar 创建现代自适应用户界面的简单但有效的技术。考虑到这些知识,您可以为从智能手机到平板电脑和笔记本电脑的各种设备构建更直观、更有吸引力的应用程序。因此,您的应用程序将获得越来越多的用户,并有更大的成功机会。

发布于: 48 分钟前阅读数: 4
用户头像

坚果

关注

此间若无火炬,我便是唯一的光 2020.10.25 加入

公众号:“大前端之旅”,华为云享专家,InfoQ签约作者,51CTO博客首席体验官,专注于大前端技术的分享,包括Flutter,小程序,安卓,VUE,JavaScript。

评论

发布
暂无评论
在 Flutter 中使用 NavigationRail 和 BottomNavigationBar_3月日更_坚果_InfoQ写作平台