// 暖记响应式骨架 — 三级自适应布局 // 手机: 底部 TabBar | 平板: 侧边导航 | 桌面: 三栏 import 'package:flutter/material.dart'; import '../core/constants/breakpoints.dart'; /// 暖记自适应 Scaffold class ResponsiveScaffold extends StatefulWidget { const ResponsiveScaffold({ super.key, required this.selectedIndex, required this.onDestinationSelected, required this.body, this.floatingActionButton, this.appBarTitle, this.secondaryBody, }); final int selectedIndex; final ValueChanged onDestinationSelected; final Widget body; final Widget? floatingActionButton; final String? appBarTitle; final Widget? secondaryBody; @override State createState() => _ResponsiveScaffoldState(); } class _ResponsiveScaffoldState extends State { @override Widget build(BuildContext context) { final width = MediaQuery.sizeOf(context).width; final deviceType = Breakpoints.getDeviceType(width); switch (deviceType) { case DeviceType.mobile: return _MobileLayout( selectedIndex: widget.selectedIndex, onDestinationSelected: widget.onDestinationSelected, body: widget.body, floatingActionButton: widget.floatingActionButton, appBarTitle: widget.appBarTitle, ); case DeviceType.tablet: return _TabletLayout( selectedIndex: widget.selectedIndex, onDestinationSelected: widget.onDestinationSelected, body: widget.body, appBarTitle: widget.appBarTitle, ); case DeviceType.desktop: return _DesktopLayout( selectedIndex: widget.selectedIndex, onDestinationSelected: widget.onDestinationSelected, body: widget.body, secondaryBody: widget.secondaryBody, appBarTitle: widget.appBarTitle, ); } } } // ===== 导航项定义 ===== final _navItems = [ NavigationDestination( icon: const Icon(Icons.home_outlined), selectedIcon: const Icon(Icons.home), label: '首页', ), NavigationDestination( icon: const Icon(Icons.calendar_month_outlined), selectedIcon: const Icon(Icons.calendar_month), label: '日历', ), NavigationDestination( icon: const Icon(Icons.auto_awesome_outlined), selectedIcon: const Icon(Icons.auto_awesome), label: '心情', ), NavigationDestination( icon: const Icon(Icons.search_outlined), selectedIcon: const Icon(Icons.search), label: '搜索', ), NavigationDestination( icon: const Icon(Icons.person_outline), selectedIcon: const Icon(Icons.person), label: '我的', ), ]; const _railItems = [ NavigationRailDestination( icon: Icon(Icons.home_outlined), selectedIcon: Icon(Icons.home), label: Text('首页'), ), NavigationRailDestination( icon: Icon(Icons.calendar_month_outlined), selectedIcon: Icon(Icons.calendar_month), label: Text('日历'), ), NavigationRailDestination( icon: Icon(Icons.auto_awesome_outlined), selectedIcon: Icon(Icons.auto_awesome), label: Text('心情'), ), NavigationRailDestination( icon: Icon(Icons.search_outlined), selectedIcon: Icon(Icons.search), label: Text('搜索'), ), NavigationRailDestination( icon: Icon(Icons.person_outline), selectedIcon: Icon(Icons.person), label: Text('我的'), ), ]; // ===== 手机布局 — 底部 TabBar ===== class _MobileLayout extends StatelessWidget { const _MobileLayout({ required this.selectedIndex, required this.onDestinationSelected, required this.body, this.floatingActionButton, this.appBarTitle, }); final int selectedIndex; final ValueChanged onDestinationSelected; final Widget body; final Widget? floatingActionButton; final String? appBarTitle; @override Widget build(BuildContext context) { return Scaffold( appBar: appBarTitle != null ? AppBar(title: Text(appBarTitle!)) : null, body: body, floatingActionButton: floatingActionButton, bottomNavigationBar: NavigationBar( selectedIndex: selectedIndex, onDestinationSelected: onDestinationSelected, destinations: _navItems, ), ); } } // ===== 平板布局 — 侧边 NavigationRail ===== class _TabletLayout extends StatelessWidget { const _TabletLayout({ required this.selectedIndex, required this.onDestinationSelected, required this.body, this.appBarTitle, }); final int selectedIndex; final ValueChanged onDestinationSelected; final Widget body; final String? appBarTitle; @override Widget build(BuildContext context) { return Scaffold( appBar: appBarTitle != null ? AppBar(title: Text(appBarTitle!)) : null, body: Row( children: [ NavigationRail( selectedIndex: selectedIndex, onDestinationSelected: onDestinationSelected, destinations: _railItems, leading: Padding( padding: const EdgeInsets.symmetric(vertical: 16), child: Icon( Icons.edit_note_rounded, size: 32, color: Theme.of(context).colorScheme.primary, ), ), ), const VerticalDivider(thickness: 1, width: 1), Expanded(child: body), ], ), ); } } // ===== 桌面布局 — 三栏 ===== class _DesktopLayout extends StatelessWidget { const _DesktopLayout({ required this.selectedIndex, required this.onDestinationSelected, required this.body, this.secondaryBody, this.appBarTitle, }); final int selectedIndex; final ValueChanged onDestinationSelected; final Widget body; final Widget? secondaryBody; final String? appBarTitle; @override Widget build(BuildContext context) { return Scaffold( appBar: appBarTitle != null ? AppBar(title: Text(appBarTitle!)) : null, body: Row( children: [ NavigationRail( selectedIndex: selectedIndex, onDestinationSelected: onDestinationSelected, destinations: _railItems, extended: true, leading: Padding( padding: const EdgeInsets.symmetric(vertical: 16), child: Row( mainAxisSize: MainAxisSize.min, children: [ Icon( Icons.edit_note_rounded, size: 32, color: Theme.of(context).colorScheme.primary, ), const SizedBox(width: 12), Text( '暖记', style: Theme.of(context).textTheme.headlineSmall?.copyWith( fontFamily: 'Caveat', color: Theme.of(context).colorScheme.primary, ), ), ], ), ), ), const VerticalDivider(thickness: 1, width: 1), // 主内容区 Expanded( flex: 3, child: body, ), // 第二面板(日记详情/预览) if (secondaryBody != null) ...[ const VerticalDivider(thickness: 1, width: 1), Expanded( flex: 2, child: secondaryBody!, ), ], ], ), ); } }