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

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

描述

persistent_bottom_nav_bar 是一个Flutter库,用于创建持久/静态的底部导航栏。它提供了丰富的自定义选项,并支持多种样式和功能。

特点

  • 高度可定制:你可以根据需要调整底部导航栏的外观。
  • 屏幕推送控制:可以推送新的屏幕并选择是否显示底部导航栏。
  • 20种样式:提供多种预设样式供你选择。
  • 透明度支持:特定标签页中导航栏可以设置为半透明。
  • 动画图标:支持带有动画效果的图标。
  • 处理返回键:自动处理安卓设备上的硬件或软件返回键。
  • 更多特性:包括基于iOS风格的导航栏、自定义样式等。

快速开始

添加依赖

在项目的pubspec.yaml文件中添加依赖:

dependencies:
  persistent_bottom_nav_bar: any

导入库

然后在Dart代码中导入此库:

import 'package:persistent_bottom_nav_bar/persistent_bottom_nav_bar.dart';

初始化控制器

声明并初始化一个PersistentTabController来管理当前选中的标签页:

PersistentTabController _controller = PersistentTabController(initialIndex: 0);

创建主应用界面

使用PersistentTabView作为主容器,其中包含要显示的不同页面以及对应的底部导航项。

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

  @override
  Widget build(BuildContext context) {
    return PersistentTabView(
      context,
      controller: _controller,
      screens: _buildScreens(),
      items: _navBarsItems(),
      handleAndroidBackButtonPress: true, // 默认值为true
      resizeToAvoidBottomInset: true,     // 当键盘弹出时是否调整布局,默认为true
      stateManagement: true,               // 是否启用状态管理,默认为true
      hideNavigationBarWhenKeyboardAppears: true,
      popBehaviorOnSelectedNavBarItemPress: PopActionScreensType.all,
      padding: const EdgeInsets.only(top: 8),
      backgroundColor: Colors.grey.shade900,
      isVisible: true,
      animationSettings: const NavBarAnimationSettings(
        navBarItemAnimation: ItemAnimationSettings(
          duration: Duration(milliseconds: 400),
          curve: Curves.ease,
        ),
        screenTransitionAnimation: ScreenTransitionAnimationSettings(
          animateTabTransition: true,
          duration: Duration(milliseconds: 200),
          screenTransitionAnimationType: ScreenTransitionAnimationType.fadeIn,
        ),
      ),
      confineToSafeArea: true,
      navBarHeight: kBottomNavigationBarHeight,
      navBarStyle: _navBarStyle, // 根据需要选择导航栏样式
    );
  }
}

定义页面列表与导航项

分别定义每个标签页对应的页面(_buildScreens)及它们的导航栏项(_navBarsItems)。

List<Widget> _buildScreens() {
  return [
    MainScreen(),
    SettingsScreen()
  ];
}

List<PersistentBottomNavBarItem> _navBarsItems() {
  return [
    PersistentBottomNavBarItem(
      icon: Icon(CupertinoIcons.home),
      title: "Home",
      activeColorPrimary: CupertinoColors.activeBlue,
      inactiveColorPrimary: CupertinoColors.systemGrey,
      scrollController: _scrollController1,
      routeAndNavigatorSettings: RouteAndNavigatorSettings(
        initialRoute: "/",
        routes: {
          "/first": (final context) => const MainScreen2(),
          "/second": (final context) => const MainScreen3(),
        },
      ),
    ),
    PersistentBottomNavBarItem(
      icon: Icon(CupertinoIcons.settings),
      title: "Settings",
      activeColorPrimary: CupertinoColors.activeBlue,
      inactiveColorPrimary: CupertinoColors.systemGrey,
      scrollController: _scrollController2,
      routeAndNavigatorSettings: RouteAndNavigatorSettings(
        initialRoute: "/",
        routes: {
          "/first": (final context) => const MainScreen2(),
          "/second": (final context) => const MainScreen3(),
        },
      ),
    ),
  ];
}

导航函数

对于新页面的推送,可以使用提供的专用方法,这些方法允许你指定是否要在新页面上显示底部导航栏。

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,
);

此外还有其他辅助函数如pushDynamicScreen用于推送模态窗口,popUntilFirstScreenOnSelectedTabScreen用于返回到选定标签的第一个页面等。

自定义导航栏样式

如果想要创建独特的导航栏外观,可以通过实现自己的小部件来替换默认样式,并将其实例传递给PersistentTabView中的customWidget属性。

class CustomNavBarWidget extends StatelessWidget {
  final int selectedIndex;
  final List<PersistentBottomNavBarItem> items;
  final ValueChanged<int> onItemSelected;

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

  Widget _buildItem(PersistentBottomNavBarItem item, bool isSelected) {
    return Container(
      alignment: Alignment.center,
      height: 60.0,
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          Flexible(
            child: IconTheme(
              data: IconThemeData(
                size: 26.0,
                color: isSelected
                    ? (item.activeColorSecondary ?? 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 ?? item.activeColorPrimary)
                        : item.inactiveColorPrimary,
                    fontWeight: FontWeight.w400,
                    fontSize: 12.0,
                  ),
                ),
              ),
            ),
          )
        ],
      ),
    );
  }

  @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(),
        ),
      ),
    );
  }
}

最后,在PersistentTabView中使用这个自定义的小部件:

PersistentTabView.custom(
  context,
  controller: _controller,
  screens: ...,
  itemCount: 5,
  customWidget: CustomNavBarWidget(
    items: _navBarsItems(),
    selectedIndex: _controller.index,
    onItemSelected: (index) {
      setState(() {
        _controller.index = index; // 这一步很重要!不要遗漏
      });
    },
  ),
  ...
);

以上就是关于如何在Flutter项目中使用persistent_bottom_nav_bar插件的基本介绍和示例代码。希望这能帮助你在应用程序中实现稳定且美观的底部导航体验。


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

1 回复

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


当然,以下是一个关于如何使用 persistent_bottom_nav_bar 插件在 Flutter 中实现持久化底部导航栏的代码案例。这个插件允许你创建一个底部导航栏,并且在用户重新打开应用时保持其状态。

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

dependencies:
  flutter:
    sdk: flutter
  persistent_bottom_nav_bar: ^4.0.3  # 请使用最新版本

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

接下来,你可以在你的 Flutter 应用中实现持久化底部导航栏。以下是一个完整的示例代码:

import 'package:flutter/material.dart';
import 'package:persistent_bottom_nav_bar/persistent-theme.dart';
import 'package:persistent_bottom_nav_bar/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: PersistentTabScreen(
        controller: _getBottomNavBarController(),
        items: _navBarsItems(),
        conf: PersistentTabControllerConfiguration(
          hideNavigationBarWhenKeyboardShows: true,
          decoration: NavBarDecoration(
            colorBehindNavBar: Colors.white,
          ),
          popBehavior: PopBehavior.close_to_first_non_permanent_tab,
          popActionScreens: PopActionScreensType.all,
          screenTransitionAnimation: ScreenTransitionAnimation.slide,
          itemAnimationProperties: ItemAnimationProperties(
            duration: Duration(milliseconds: 200),
            curve: Curves.ease,
          ),
          navBarStyle: NavBarStyle.style12,
        ),
        initialIndex: 0, // 初始页面索引
        onItemSelected: (index) {
          // 页面切换回调
        },
        backgroundColor: Colors.white,
        handleAndroidBackButtonPress: true, // 是否处理Android返回按钮
        resizeToAvoidBottomInset: true,
        stateManagement: true, // 启用状态管理以持久化导航栏状态
      ),
    );
  }

  PersistentTabController _getBottomNavBarController() {
    bool hasRestoredState = false;
    PersistentTabController _controller = PersistentTabController(initialIndex: 0);

    _controller.addListener(() {
      if (!hasRestoredState) {
        hasRestoredState = true;
        // 在这里你可以恢复之前的状态,例如从SharedPreferences读取
      }
    });

    return _controller;
  }

  List<PersistentBottomNavBarItem> _navBarsItems() {
    return [
      PersistentBottomNavBarItem(
        icon: Icon(Icons.home),
        title: ("Home"),
        activeColorPrimary: Colors.blue,
        inactiveColorPrimary: Colors.grey,
        routeAndNavigatorSettings: RouteAndNavigatorSettings(
          initialRoute: "/",
          routes: {
            "/": (context) => HomeScreen(),
          },
        ),
      ),
      PersistentBottomNavBarItem(
        icon: Icon(Icons.search),
        title: ("Search"),
        activeColorPrimary: Colors.blue,
        inactiveColorPrimary: Colors.grey,
        routeAndNavigatorSettings: RouteAndNavigatorSettings(
          initialRoute: "/search",
          routes: {
            "/search": (context) => SearchScreen(),
          },
        ),
      ),
      PersistentBottomNavBarItem(
        icon: Icon(Icons.add),
        title: ("Add"),
        activeColorPrimary: Colors.blue,
        inactiveColorPrimary: Colors.grey,
        routeAndNavigatorSettings: RouteAndNavigatorSettings(
          initialRoute: "/add",
          routes: {
            "/add": (context) => AddScreen(),
          },
        ),
      ),
      PersistentBottomNavBarItem(
        icon: Icon(Icons.profile),
        title: ("Profile"),
        activeColorPrimary: Colors.blue,
        inactiveColorPrimary: Colors.grey,
        routeAndNavigatorSettings: RouteAndNavigatorSettings(
          initialRoute: "/profile",
          routes: {
            "/profile": (context) => ProfileScreen(),
          },
        ),
      ),
    ];
  }
}

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

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

class AddScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Add Screen'),
      ),
      body: Center(
        child: Text('Add Screen Content'),
      ),
    );
  }
}

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

这个示例代码展示了如何使用 persistent_bottom_nav_bar 插件来创建一个底部导航栏,并且启用了状态管理以持久化导航栏的状态。每个导航项都关联到一个不同的屏幕(如 HomeScreen, SearchScreen 等),并且当用户切换到不同的页面时,底部导航栏的状态会被持久化。

请确保你已经理解了每个部分的作用,并根据你的实际需求进行调整。

回到顶部