如何在横屏模式下将Flutter BottomNavigationBar放置在屏幕左侧
预期视图

实现方案
该需求可以直接实现,无需额外第三方依赖,推荐优先使用Flutter官方提供的NavigationRail组件配合横竖屏检测实现,这是最适配原生设计规范的方案。
具体实现逻辑如下:
- 使用
OrientationBuilder监听屏幕横竖屏状态变化 - 竖屏状态下渲染常规底部
BottomNavigationBar - 横屏状态下隐藏底部导航,在屏幕左侧渲染
NavigationRail侧边导航栏
示例代码:
import 'package:flutter/material.dart'; void main() => runApp(const MyApp()); class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( title: '横竖屏导航切换 demo', theme: ThemeData(primarySwatch: Colors.blue), home: const NavDemoPage(), ); } } class NavDemoPage extends StatefulWidget { const NavDemoPage({super.key}); @override State<NavDemoPage> createState() => _NavDemoPageState(); } class _NavDemoPageState extends State<NavDemoPage> { int _selectedIndex = 0; // 页面列表 final List<Widget> _pages = const [ Center(child: Text('首页')), Center(child: Text('分类')), Center(child: Text('我的')), ]; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('导航切换演示')), body: OrientationBuilder( builder: (context, orientation) { // 横屏状态:左侧导航栏+右侧内容 if (orientation == Orientation.landscape) { return Row( children: [ NavigationRail( selectedIndex: _selectedIndex, onDestinationSelected: (index) { setState(() => _selectedIndex = index); }, labelType: NavigationRailLabelType.all, destinations: const [ NavigationRailDestination( icon: Icon(Icons.home), label: Text('首页'), ), NavigationRailDestination( icon: Icon(Icons.category), label: Text('分类'), ), NavigationRailDestination( icon: Icon(Icons.person), label: Text('我的'), ), ], ), const VerticalDivider(thickness: 1, width: 1), // 内容区域 Expanded(child: _pages[_selectedIndex]), ], ); } // 竖屏状态:正常内容区域,底部放导航栏 else { return _pages[_selectedIndex]; } }, ), // 竖屏才显示底部导航栏 bottomNavigationBar: OrientationBuilder( builder: (context, orientation) { return orientation == Orientation.portrait ? BottomNavigationBar( currentIndex: _selectedIndex, onTap: (index) { setState(() => _selectedIndex = index); }, items: const [ BottomNavigationBarItem(icon: Icon(Icons.home), label: '首页'), BottomNavigationBarItem(icon: Icon(Icons.category), label: '分类'), BottomNavigationBarItem(icon: Icon(Icons.person), label: '我的'), ], ) : const SizedBox.shrink(); }, ), ); } }
替代方案
如果你一定要复用原有BottomNavigationBar的样式而不想用NavigationRail,也可以直接在横屏状态的Row组件左侧直接放入改造后的BottomNavigationBar,将其type设置为BottomNavigationBarType.fixed,同时包裹在RotatedBox或者调整宽度适配竖排展示即可,不过这种方案需要自行适配点击事件和样式,兼容性不如官方NavigationRail。
内容的提问来源于stack exchange,提问作者Chanaka
相关产品推荐
相关产品推荐

