Flutter:如何实现可展开NavigationRail覆盖PDF Viewer
解决方案
要实现NavigationRail展开时覆盖SfPdfViewer而非挤压它,核心是调整布局结构并利用以下关键属性/组件:
Stack组件:将SfPdfViewer作为底层内容,NavigationRail放在上层,确保导航栏展开时是覆盖而非挤占空间。MouseRegion:监听鼠标的进入/退出事件,切换导航栏的展开状态。NavigationRail的extended属性:控制导航栏是否展开,配合minWidth和extendedWidth定义收缩/展开时的宽度。AnimatedContainer:包裹NavigationRail,实现展开/收缩的平滑过渡动画,同时保证退出悬停后PDF能立即恢复全屏(动画结束后导航栏回到收缩宽度,底层PDF自然占满屏幕)。
示例代码
class PdfNavScreen extends StatefulWidget { @override _PdfNavScreenState createState() => _PdfNavScreenState(); } class _PdfNavScreenState extends State<PdfNavScreen> { bool _navExtended = false; @override Widget build(BuildContext context) { return Scaffold( body: Stack( children: [ // 底层PDF Viewer,占满整个屏幕空间 SfPdfViewer.network('https://your-pdf-url.com/file.pdf'), // 上层导航栏,监听鼠标悬停并实现宽度过渡 MouseRegion( onEnter: (_) => setState(() => _navExtended = true), onExit: (_) => setState(() => _navExtended = false), child: AnimatedContainer( duration: const Duration(milliseconds: 300), width: _navExtended ? 240 : 72, child: NavigationRail( extended: _navExtended, minWidth: 72, extendedWidth: 240, backgroundColor: Colors.grey[100]!.withOpacity(0.95), destinations: const [ NavigationRailDestination( icon: Icon(Icons.home_outlined), selectedIcon: Icon(Icons.home), label: Text('首页'), ), NavigationRailDestination( icon: Icon(Icons.book_outlined), selectedIcon: Icon(Icons.book), label: Text('文档'), ), ], selectedIndex: 0, onDestinationSelected: (index) {}, ), ), ), ], ), ); } }
关键说明
- 使用Stack布局后,SfPdfViewer始终占据整个屏幕,NavigationRail作为上层组件,展开时只会覆盖在PDF上方,不会挤压其空间。
- AnimatedContainer的过渡动画让导航栏的展开/收缩更流畅,同时避免状态切换时的突兀感,退出悬停后导航栏会快速收缩,PDF立即恢复全屏显示。
- 可根据需求调整
minWidth、extendedWidth和动画时长,适配不同的UI设计。
内容的提问来源于stack exchange,提问作者DrakeJest
相关产品推荐
相关产品推荐

