Flutter for OpenHarmony 实战:bottom_navy_bar 优雅的波纹式底部导航

前言

追求 UI 的“呼吸感”是现代移动端开发的潮流。传统的底部导航栏往往只是图标和文字的切换,稍显生硬。bottom_navy_bar 则提供了一种更具动感、更加紧凑的方案:当 Tab 被选中时,图标和文字会伴随着优雅的波纹膨胀开来,视觉效果极佳。

HarmonyOS NEXT 这个强调“轻量”与“灵动”设计语言的系统中,集成这种海军风导航栏,能让你的鸿蒙 App 显得别具一格。


一、 为什么在鸿蒙开发中尝试 NavyBar?

1.1 空间的极致利用与视觉对比

传统的底部导航栏(BottomNavigationBar)通常是固定的图标+文字结构,页面较多时显得拥挤。bottom_navy_bar 采用“非对称伸缩”逻辑:未选中项收缩为单纯的 Icon,选中项则展开为一个带有背景色和文字标签的“胶囊体”。这种设计在 HarmonyOS NEXT 的窄屏下能节省空间,在折叠屏展开后的宽屏下则展现出强烈的逻辑焦点。

1.2 丝滑的线性插值动画

该插件内部通过 AnimatedContainerAnimatedDefaultTextStyle 实现了极其流畅的宽度变换和文字渐显。在鸿蒙设备的高刷屏上,当手指划过页签,那种波纹扩散与平滑位移的视觉体验,远比简单的 Tab 切换更具“高级感”。


二、 技术内幕:拆解 NavyBar 的“形变”魔术

2.1 布局约束转换

当用户点击时,内部会触发一个 curve 限定的宽度动画。选中项的 Constraint 会从小圆点状态扩展为“图标+文字+间距”的总和。由于使用了线性插值系数(Tween),这种变换在视觉上是连续且无跳变的。

2.2 响应式背景染色

波纹效果的本质是给 activeColor 施加了一个低透明度的背景层。这在鸿蒙的“磨砂玻璃(Frosted Glass)”背景下,能形成迷人的渐变融合效果。


三、 集成指南

3.1 添加依赖

pubspec.yaml 中添加以下代码:

dependencies:
  bottom_navy_bar: ^6.1.0

四、 核心关键技术分解

4.1 核心参数深度配置

在适配鸿蒙时,我们重点关注圆角(CornerRadius)品牌色(ActiveColor)

import 'package:bottom_navy_bar/bottom_navy_bar.dart';

BottomNavyBar(
  selectedIndex: _currentIndex,
  showElevation: false, // 💡 建议关闭自带阴影,改用 Container 托管实现全屏宽阴影
  itemCornerRadius: 24, // 💡 适配:鸿蒙标志性的大圆角半径
  curve: Curves.easeInOutBack, 
  onItemSelected: (index) => setState(() => _currentIndex = index),
  items: <BottomNavyBarItem>[
    BottomNavyBarItem(
      icon: const Icon(Icons.flash_on),
      title: const Text('动态'),
      activeColor: Color(0xFF007DFF), // 💡 鸿蒙品牌蓝
    ),
    // ... 其他 Item
  ],
)

在这里插入图片描述

4.2 全面屏“沉浸式底座”适配

为了让底栏背景延伸到物理屏幕边缘,同时文字内容避开手势区,我们需要采用 Container + SafeArea 的嵌套方案。

Container(
  decoration: BoxDecoration(
    color: Colors.white,
    boxShadow: [ BoxShadow(color: Colors.black12, blurRadius: 10) ],
  ),
  child: SafeArea(
    child: BottomNavyBar(...),
  ),
)

在这里插入图片描述


五、 完整示例:鸿蒙波纹底栏实战

本示例展示了如何在 HarmonyOS NEXT 环境下构建一个高颜值的底部导航。特别处理了底部安全区的视觉连续性。

import 'package:flutter/material.dart';
import 'package:bottom_navy_bar/bottom_navy_bar.dart';

class BottomNavyBarDemoPage extends StatefulWidget {
  const BottomNavyBarDemoPage({super.key});

  
  State<BottomNavyBarDemoPage> createState() => _BottomNavyBarDemoPageState();
}

class _BottomNavyBarDemoPageState extends State<BottomNavyBarDemoPage> {
  int _currentIndex = 0;
  final _pageController = PageController();

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('鸿蒙灵动底栏 (NavyBar)')),
      body: PageView(
        controller: _pageController,
        onPageChanged: (index) => setState(() => _currentIndex = index),
        children: [ _buildPage('首页'), _buildPage('设置') ],
      ),
      // 💡 最佳实践:使用外层 Container 托管背景色和顶部阴影
      bottomNavigationBar: Container(
        decoration: BoxDecoration(
          color: Colors.white,
          boxShadow: [
            BoxShadow(
              color: Colors.black.withOpacity(0.05),
              blurRadius: 10,
              offset: const Offset(0, -5),
            ),
          ],
        ),
        child: SafeArea(
          child: BottomNavyBar(
            backgroundColor: Colors.transparent, // 背景透明,复用底层 Container 颜色
            selectedIndex: _currentIndex,
            showElevation: false, // 禁用自带阴影
            itemCornerRadius: 24,
            onItemSelected: (index) {
              setState(() => _currentIndex = index);
              _pageController.animateToPage(index, 
                  duration: const Duration(milliseconds: 300), curve: Curves.ease);
            },
            items: [
              BottomNavyBarItem(
                icon: Icon(Icons.home_filled),
                title: Text('首页'),
                activeColor: Color(0xFF007DFF), 
              ),
              BottomNavyBarItem(
                icon: Icon(Icons.settings),
                title: Text('设置'),
                activeColor: Colors.teal,
              ),
            ],
          ),
        ),
      ),
    );
  }

  Widget _buildPage(String text) => Center(child: Text(text));
}

在这里插入图片描述


六、 适配鸿蒙的避坑指南

6.1 解决安全区“视觉断层”

在 HarmonyOS NEXT 的全面屏设备上,如果直接使用 SafeArea 包裹底栏,底部会留出一段 Scafffold 的背景色(默认灰色)。

  • 解决方案:将 SafeArea 放入一个指定背景色的 Container 中。这样 Container 的颜色会延伸到物理边缘,而 SafeArea 负责将按钮顶入安全区域,视觉效果浑然一体。

6.2 统一顶边阴影

bottom_navy_bar 自带的阴影(showElevation: true)通常只作用于组件自身范围内。

  • 优化建议:禁用内部阴影,在最外层 Container 上使用 BoxShadow。这能确保阴影横跨整个屏幕宽度,并包裹下方的安全区,呈现出完美的“底座感”。

6.3 适配高度变化的场景

鸿蒙系统的输入法呼出或分屏调整时,界面高度会剧烈波动。建议为 BottomNavyBar 设置固定的内部容器高度(如 56~60dp),确保在复杂的系统级 UI 变换中,导航栏不会因内容溢出而导致布局崩溃。


七、 总结

通过 bottom_navy_bar 方案,我们不仅在鸿蒙平台上实现了一个基础的导航功能,更通过对安全区背景和阴影细节的打磨,展示了 Flutter 在实现平台级沉浸式体验上的巨大潜力。


🌐 欢迎加入开源鸿蒙跨平台社区开源鸿蒙跨平台开发者社区

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐