0
点赞
收藏
分享

微信扫一扫

在 Flutter 中使用 NavigationRail 和 BottomNavigationBar

在 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 像素,则不会呈现底部标签栏,而会显示左侧导航栏。

以下是它的工作原理:

截图

在 Flutter 中使用 NavigationRail 和 BottomNavigationBar_ico

代码

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

// 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
})

参考:

  • ​​navigation:设计​​(material.io)
  • ​​NavigationRail 类​​(flutter.dev)
  • ​​NavigationRailDestination​​类 (flutter.dev)
  • ​​BottomNavigationBar 类​​(flutter.dev)

后记

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

举报

相关推荐

0 条评论