在 Flutter 中使用 NavigationRail 和 BottomNavigationBar

举报
坚果的博客 发表于 2022/03/14 08:30:42 2022/03/14
【摘要】 在 Flutter 中使用 NavigationRail 和 BottomNavigationBar作者:坚果公众号:"大前端之旅"华为云享专家,InfoQ签约作者,阿里云专家博主,51CTO博客首席体验官,开源项目GVA成员之一,专注于大前端技术的分享,包括Flutter,鸿蒙,小程序,安卓,VUE,JavaScript等。本文将向您展示如何使用NavigationRail和BottomN...

在 Flutter 中使用 NavigationRail 和 BottomNavigationBar

作者:坚果

公众号:"大前端之旅"

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

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


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


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

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

MediaQuery.of(context).size.width

这个例子

应用预览

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

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

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

以下是它的工作原理:

截图

chip

代码

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

// main.dart
import '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 创建现代自适应用户界面的简单但有效的技术。考虑到这些知识,您可以为从智能手机到平板电脑和笔记本电脑的各种设备构建更直观、更有吸引力的应用程序。因此,您的应用程序将获得越来越多的用户,并有更大的成功机会。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。