Flutter中堆叠BottomNavigationBar高度计算及显示异常求助
Flutter 底部导航栏堆叠组件问题解决
问题情况
- 最初在
bottomNavigationBar中使用Column堆叠组件,出现Column内容覆盖整个body的问题。 - 用
Container包裹Column并设置高度后,实现了底部堆叠,但存在底部溢出问题。 - 给
Column内组件添加GlobalKey,通过自定义函数获取高度,将函数调用放在initState后,堆叠导航栏不再显示。 - 添加
WidgetsBinding的PostFrameCallback也未解决,推测是组件未渲染导致高度为null。
原代码
import 'package:flutter/material.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatefulWidget { const MyApp({super.key}); @override State<MyApp> createState() => _MyAppState(); } class _MyAppState extends State<MyApp> { @override Widget build(BuildContext context) { return MaterialApp(home: const MyHomePage()); } } class MyHomePage extends StatefulWidget { const MyHomePage({super.key}); @override State<MyHomePage> createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { List<BottomNavigationBarItem>? _items = []; String _value = ""; int _index = 0; bool _showStackedBottomNavBar = false; final GlobalKey keyStackedBNBContainer = GlobalKey(); final GlobalKey keyStackedBNB_BNB = GlobalKey(); List<int> _listHeightOfStackedBNB = []; double _varForHeightOfStackedBNB = 0.0; @override void initState() { super.initState(); if (_items != null) { _items?.add( BottomNavigationBarItem(icon: Icon(Icons.people), label: "People"), ); _items?.add( BottomNavigationBarItem(icon: Icon(Icons.weekend), label: "Weekend"), ); _items?.add( BottomNavigationBarItem(icon: Icon(Icons.message), label: "Message"), ); } _varForHeightOfStackedBNB = _heightOfStackedBNB( keyStackedBNBContainer, keyStackedBNB_BNB, ); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( backgroundColor: Theme.of(context).primaryColor, title: const Text("Bottom sheet and navigation bar"), ), body: Column( children: [ Text("########## $_value"), ElevatedButton( onPressed: () { setState(() { _showStackedBottomNavBar = !_showStackedBottomNavBar; }); }, child: Text("Click Me!"), ), ], ), bottomNavigationBar: (_showStackedBottomNavBar && _varForHeightOfStackedBNB > -1.0) ? Container( height: _varForHeightOfStackedBNB, child: Column( mainAxisAlignment: MainAxisAlignment.end, children: [ Container( key: keyStackedBNBContainer, padding: EdgeInsets.all(15.0), height: 60.0, width: double.infinity, decoration: BoxDecoration(color: Colors.amberAccent), child: const Text("Bottom Navigation Bar"), ), BottomNavigationBar( key: keyStackedBNB_BNB, items: _items!, currentIndex: _index, onTap: (int newIndex) { setState(() { _index = newIndex; _value = "Current value is: ${_index.toString()}"; }); }, ), ], ), ) : Container(height: 60.0, color: Colors.red), ); } double _heightOfStackedBNB(GlobalKey gk01, GlobalKey gk02) { double totalHeight = 0.0; bool isAnyHeightNull = false; double height01 = 0.0; if (gk01.currentContext?.size?.height == null) { isAnyHeightNull = true; height01 = gk01.currentContext?.size?.height ?? 0.0; } double height02 = 0.0; if (gk02.currentContext?.size?.height == null) { isAnyHeightNull = true; height02 = gk02.currentContext?.size?.height ?? 0.0; } totalHeight = height01 + height02; return isAnyHeightNull ? -1.0 : totalHeight; } }
更新尝试(无效)
WidgetsBinding.instance.addPostFrameCallback((timestamp) { setState(() { _varForHeightOfStackedBNB = _heightOfStackedBNB( keyStackedBNBContainer, keyStackedBNB_BNB, ); }); });
问题根源
- 当
_showStackedBottomNavBar为false时,带GlobalKey的子组件并未被渲染,currentContext为null,导致_heightOfStackedBNB返回-1。即使后续切换为true,_varForHeightOfStackedBNB的值仍为-1,堆叠导航栏无法显示。 - 手动计算高度的思路冗余,
bottomNavigationBar本身可以自动适配子组件的高度,无需硬设height。
修复方案
- 移除所有
GlobalKey、高度计算相关的变量和函数。 - 给堆叠的
Column设置mainAxisSize: MainAxisSize.min,让Column仅占用子组件的总高度,避免无限扩展。 - 去掉包裹
Column的Container的height属性,让bottomNavigationBar自动适配高度。
修复后代码
import 'package:flutter/material.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatefulWidget { const MyApp({super.key}); @override State<MyApp> createState() => _MyAppState(); } class _MyAppState extends State<MyApp> { @override Widget build(BuildContext context) { return MaterialApp(home: const MyHomePage()); } } class MyHomePage extends StatefulWidget { const MyHomePage({super.key}); @override State<MyHomePage> createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { List<BottomNavigationBarItem> _items = []; String _value = ""; int _index = 0; bool _showStackedBottomNavBar = false; @override void initState() { super.initState(); _items.addAll([ const BottomNavigationBarItem(icon: Icon(Icons.people), label: "People"), const BottomNavigationBarItem(icon: Icon(Icons.weekend), label: "Weekend"), const BottomNavigationBarItem(icon: Icon(Icons.message), label: "Message"), ]); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( backgroundColor: Theme.of(context).primaryColor, title: const Text("Bottom sheet and navigation bar"), ), body: Column( children: [ Text("########## $_value"), ElevatedButton( onPressed: () { setState(() { _showStackedBottomNavBar = !_showStackedBottomNavBar; }); }, child: const Text("Click Me!"), ), ], ), bottomNavigationBar: _showStackedBottomNavBar ? Column( mainAxisSize: MainAxisSize.min, children: [ Container( padding: const EdgeInsets.all(15.0), height: 60.0, width: double.infinity, decoration: const BoxDecoration(color: Colors.amberAccent), child: const Text("Bottom Navigation Bar"), ), BottomNavigationBar( items: _items, currentIndex: _index, onTap: (int newIndex) { setState(() { _index = newIndex; _value = "Current value is: ${_index.toString()}"; }); }, ), ], ) : const SizedBox(height: 60, child: ColoredBox(color: Colors.red)), ); } }
说明
mainAxisSize: MainAxisSize.min让Column仅包裹子组件,不会占用额外空间。- 移除手动高度计算后,
bottomNavigationBar会自动识别子组件的总高度,既不会覆盖body,也不会出现溢出问题。 - 简化了
_items的初始化逻辑,避免不必要的可空判断。
内容的提问来源于stack exchange,提问作者rusty
相关产品推荐
相关产品推荐

