Flutter持久化底部导航栏插件persistent_bottom_nav_bar_2的使用

发布于 1周前 作者 ionicwang 来自 Flutter

Flutter 持久化底部导航栏插件 persistent_bottom_nav_bar_2 的使用

Persistent Bottom Navigation Bar

pub package version

license

github stars

一个用于 Flutter 的持久化底部导航栏。

注意:那些从 <strong>pre 2.0.0</strong> 版本迁移的人应该查看最新的文档和说明,因为 2.0.0 更新引入了许多破坏性的更改。

[持久行为]

样式

样式15 样式16
[样式1] [样式10]
样式1 样式9
[样式1] [样式10]
样式7 样式10
[样式3] [样式5]
样式12 样式13
[样式6] [样式8]
样式3 样式6
[样式6] [样式8]
浮雕 浮雕无副标题
[浮雕1] [浮雕2]

注意:这些并不包括所有样式变化

功能

  • 高度可定制的持久底部导航栏。
  • 可以推送到新屏幕,并且可以有或没有底部导航栏。
  • 底部导航栏有 20 种样式。
  • 包含用于推送新屏幕的函数,可以选择是否包含底部导航栏,例如 pushNewScreen()pushNewScreenWithRouteSettings()
  • 基于 Flutter 的 Cupertino(iOS)底部导航栏。
  • 可以为特定标签设置为半透明。
  • 可以自定义导航栏的样式。更多信息请参见自定义导航栏样式
  • 处理硬件/软件 Android 返回按钮。

开始使用

在你的 Flutter 项目中添加依赖:

dependencies:
  persistent_bottom_nav_bar: any

导入包:

import 'package:persistent_bottom_nav_bar/persistent_tab_view.dart';

持久底部导航栏使用 PersistentTabController 作为控制器。声明如下:

PersistentTabController _controller;

_controller = PersistentTabController(initialIndex: 0);

主要要声明的 widget 是 PersistentTabView。注意,这个 widget 包括 SCAFFOLD(基于 CupertinoTabScaffold),所以不需要单独声明它。以下是一个示例:

class MyApp extends StatelessWidget {
  const MyApp({Key key}) : super(key: key);

  [@override](/user/override)
  Widget build(BuildContext context) {
    return PersistentTabView(
        context,
        controller: _controller,
        screens: _buildScreens(),
        items: _navBarsItems(),
        confineInSafeArea: true,
        backgroundColor: Colors.white, // 默认值为 Colors.white。
        handleAndroidBackButtonPress: true, // 默认值为 true。
        resizeToAvoidBottomInset: true, // 如果希望键盘出现时移动屏幕,则需要设置为 true。默认值为 true。
        stateManagement: true, // 默认值为 true。
        hideNavigationBarWhenKeyboardShows: true, // 推荐将 `resizeToAvoidBottomInset` 设置为 true 来使用此参数。默认值为 true。
        decoration: NavBarDecoration(
          borderRadius: BorderRadius.circular(10.0),
          colorBehindNavBar: Colors.white,
        ),
        popAllScreensOnTapOfSelectedTab: true,
        popActionScreens: PopActionScreensType.all,
        itemAnimationProperties: ItemAnimationProperties( // 导航栏项目的动画属性。
          duration: Duration(milliseconds: 200),
          curve: Curves.ease,
        ),
        screenTransitionAnimation: ScreenTransitionAnimation( // 选择的标签切换时的屏幕过渡动画。
          animateTabTransition: true,
          curve: Curves.ease,
          duration: Duration(milliseconds: 200),
        ),
        navBarStyle: NavBarStyle.style1, // 使用此属性选择导航栏样式。
    );
  }
}
List<Widget> _buildScreens() {
  return [
    MainScreen(),
    SettingsScreen()
  ];
}
List<PersistentBottomNavBarItem> _navBarsItems() {
  return [
      PersistentBottomNavBarItem(
          icon: Icon(CupertinoIcons.home),
          title: ("Home"),
          activeColorPrimary: CupertinoColors.activeBlue,
          inactiveColorPrimary: CupertinoColors.systemGrey,
      ),
      PersistentBottomNavBarItem(
          icon: Icon(CupertinoIcons.settings),
          title: ("Settings"),
          activeColorPrimary: CupertinoColors.activeBlue,
          inactiveColorPrimary: CupertinoColors.systemGrey,
      ),
  ];
}

导航器功能

注意:你仍然可以使用常规的 Navigator 函数,如 ‘pushNamed’,但请确保检查你的 PersistentBottomNavBarItemrouteAndNavigatorSettings 参数中的路由设置和其他导航相关属性。

要推送新屏幕,可以使用以下函数来控制某个屏幕上的底部导航栏的可见性。你可以使用自己的逻辑来实现平台特定的行为。一种解决方案是使用 withNavBar 属性并根据平台进行切换。

在平台特定的行为中,当推送新屏幕时,在 Android 上会推送没有底部导航栏的屏幕,但在 iOS 上会保持底部导航栏。这是每个平台的默认行为。

PersistentNavBarNavigator.pushNewScreen(
    context,
    screen: MainScreen(),
    withNavBar: true, // 可选值,默认为 true。
    pageTransitionAnimation: PageTransitionAnimation.cupertino,
);
PersistentNavBarNavigator.pushNewScreenWithRouteSettings(
    context,
    settings: RouteSettings(name: MainScreen.routeName),
    screen: MainScreen(),
    withNavBar: true,
    pageTransitionAnimation: PageTransitionAnimation.cupertino,
);

如果你要推送新的模态屏幕,使用以下函数:

PersistentNavBarNavigator.pushDynamicScreen(
    context,
    screen: HomeModalScreen(),
    withNavBar: true,
);

一些有用的提示

  • 跳转到给定标签的导航图中的任意屏幕:
Navigator.of(context).popUntil((route) {
  return route.settings.name == "ScreenToPopBackTo";
});
  • 跳转回给定标签的第一个屏幕:
Navigator.of(context).popUntil(ModalRoute.withName("/"));

Navigator.of(context).pushAndRemoveUntil(
  CupertinoPageRoute(
    builder: (BuildContext context) {
      return FirstScreen();
    },
  ),
  (_) => false,
);
  • 若要在导航栏顶部推送底部视图,请使用 showModalBottomScreen 并将其属性 useRootNavigator 设置为 true。有关示例,请参阅示例项目。

自定义导航栏样式

如果你想为导航栏自定义样式,请遵循以下步骤:

  1. 声明你的自定义 widget。请注意,你需要自己处理 onSelectedItem 函数和整数 selectedIndex 以维护完整功能。同样,请注意你可以定义自己的导航栏项模型,而不是使用提供的 PersistentBottomNavBarItem。以下是更好的理解示例:
class CustomNavBarWidget extends StatelessWidget {
  final int selectedIndex;
  final List<PersistentBottomNavBarItem> items; // 注意:你可以在这里声明自己的模型,而不仅仅是 `PersistentBottomNavBarItem`。
  final ValueChanged<int> onItemSelected;

  CustomNavBarWidget({
    Key key,
    this.selectedIndex,
    @required this.items,
    this.onItemSelected,
  });

  Widget _buildItem(PersistentBottomNavBarItem item, bool isSelected) {
    return Container(
      alignment: Alignment.center,
      height: 60.0,
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        crossAxisAlignment: CrossAxisAlignment.center,
        mainAxisSize: MainAxisSize.min,
        children: <Widget>[
          Flexible(
            child: IconTheme(
              data: IconThemeData(
                size: 26.0,
                color: isSelected
                    ? (item.activeColorSecondary == null
                        ? item.activeColorPrimary
                        : item.activeColorSecondary)
                    : item.inactiveColorPrimary == null
                        ? item.activeColorPrimary
                        : item.inactiveColorPrimary),
              child: item.icon,
            ),
          ),
          Padding(
            padding: const EdgeInsets.only(top: 5.0),
            child: Material(
              type: MaterialType.transparency,
              child: FittedBox(
                child: Text(
                  item.title,
                  style: TextStyle(
                    color: isSelected
                        ? (item.activeColorSecondary == null
                            ? item.activeColorPrimary
                            : item.activeColorSecondary)
                        : item.inactiveColorPrimary,
                    fontWeight: FontWeight.w400,
                    fontSize: 12.0,
                  ),
                ),
              ),
            ),
          )
        ],
      ),
    );
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Container(
      color: Colors.white,
      child: Container(
        width: double.infinity,
        height: 60.0,
        child: Row(
          mainAxisAlignment: MainAxisAlignment.spaceAround,
          children: items.map((item) {
            int index = items.indexOf(item);
            return Flexible(
              child: GestureDetector(
                onTap: () {
                  this.onItemSelected(index);
                },
                child: _buildItem(item, selectedIndex == index),
              ),
            );
          }).toList(),
        ),
      ),
    );
  }
}
  1. 在主 PersistentTabView widget 中,将 navBarStyle 属性设置为 NavBarStyle.custom,并将刚刚创建的自定义 widget 传递给 customWidget 属性,如下所示:
class MyApp extends StatelessWidget {
  const MyApp({Key key}) : super(key: key);

  [@override](/user/override)
  Widget build(BuildContext context) {
    return PersistentTabView.custom(
      context,
      controller: _controller,
      itemCount: items.length, // 这在自定义样式的情况下是必需的!传递导航栏项目的数量。
      screens: _buildScreens(),
      confineInSafeArea: true,
      handleAndroidBackButtonPress: true,
      onItemSelected: (int) {
        setState(() {});
      },
      customWidget: CustomNavBarWidget( // 你的自定义 widget 在这里
        items: _navBarsItems(),
        selectedIndex: _controller.index,
        onItemSelected: (index) {
          setState(() {
            _controller.index = index; // 注意:这是关键!不要遗漏。
          });
        },
      ),
    );
  }
}

更多关于Flutter持久化底部导航栏插件persistent_bottom_nav_bar_2的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter持久化底部导航栏插件persistent_bottom_nav_bar_2的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,下面是一个关于如何使用 persistent_bottom_nav_bar_2 插件在 Flutter 中实现持久化底部导航栏的示例代码。

首先,确保你的 pubspec.yaml 文件中已经添加了 persistent_bottom_nav_bar_2 依赖:

dependencies:
  flutter:
    sdk: flutter
  persistent_bottom_nav_bar_v2: ^4.0.3  # 请注意版本号,根据实际情况进行调整

然后运行 flutter pub get 来获取依赖。

接下来是一个完整的示例代码,展示了如何使用 persistent_bottom_nav_bar_2 插件:

import 'package:flutter/material.dart';
import 'package:persistent_bottom_nav_bar_v2/persistent-theme.dart';
import 'package:persistent_bottom_nav_bar_v2/persistent_bottom_nav_bar.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Persistent Bottom Nav Bar Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: PersistentBottomNavBarDemo(),
    );
  }
}

class PersistentBottomNavBarDemo extends StatefulWidget {
  @override
  _PersistentBottomNavBarDemoState createState() => _PersistentBottomNavBarDemoState();
}

class _PersistentBottomNavBarDemoState extends State<PersistentBottomNavBarDemo>
    with SingleTickerProviderStateMixin {
  int _selectedIndex = 0;
  final List<PersistentBottomNavBarItem> _navItems = [
    PersistentBottomNavBarItem(
      icon: Icon(Icons.home),
      title: ("Home"),
      activeColorPrimary: Colors.blue,
      inactiveColorPrimary: Colors.grey,
    ),
    PersistentBottomNavBarItem(
      icon: Icon(Icons.search),
      title: ("Search"),
      activeColorPrimary: Colors.red,
      inactiveColorPrimary: Colors.grey,
    ),
    PersistentBottomNavBarItem(
      icon: Icon(Icons.library_books),
      title: ("Library"),
      activeColorPrimary: Colors.green,
      inactiveColorPrimary: Colors.grey,
    ),
    PersistentBottomNavBarItem(
      icon: Icon(Icons.profile),
      title: ("Profile"),
      activeColorPrimary: Colors.purple,
      inactiveColorPrimary: Colors.grey,
    ),
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: IndexedStack(
        index: _selectedIndex,
        children: [
          HomeScreen(),
          SearchScreen(),
          LibraryScreen(),
          ProfileScreen(),
        ],
      ),
      bottomNavigationBar: PersistentBottomNavBar(
        navBarStyle: NavBarStyle.style12,
        items: _navItems,
        currentIndex: _selectedIndex,
        onItemSelected: (index) {
          setState(() {
            _selectedIndex = index;
          });
        },
        animationDuration: Duration(milliseconds: 200),
        backgroundColor: Colors.white,
        persistentBehavior: PersistentBehavior.none,
        hideNavigationBarWhenKeyboardShows: true,
        elevation: 8.0,
        forceIconsUp: false,
      ),
    );
  }
}

class HomeScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Text('Home Screen'),
    );
  }
}

class SearchScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Text('Search Screen'),
    );
  }
}

class LibraryScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Text('Library Screen'),
    );
  }
}

class ProfileScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Text('Profile Screen'),
    );
  }
}

在这个示例中:

  1. 我们定义了一个 PersistentBottomNavBarDemo 类,它包含了一个底部导航栏 (PersistentBottomNavBar) 和一个 IndexedStack,用于显示当前选中的页面。
  2. PersistentBottomNavBarItem 列表包含了四个导航项,每个导航项都有一个图标和标题,以及激活和未激活时的颜色。
  3. PersistentBottomNavBaronItemSelected 回调用于更新当前选中的索引,并重新构建界面。
  4. HomeScreenSearchScreenLibraryScreenProfileScreen 是四个简单的页面,它们分别显示不同的文本。

这个示例展示了如何使用 persistent_bottom_nav_bar_2 插件创建一个具有持久化功能的底部导航栏。你可以根据需要进一步自定义和扩展这个示例。

回到顶部