137 lines
3.8 KiB
Dart
137 lines
3.8 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:go_router/go_router.dart';
|
|
import '../../core/router/routes.dart';
|
|
|
|
class MainShell extends StatelessWidget {
|
|
final Widget child;
|
|
|
|
const MainShell({super.key, required this.child});
|
|
|
|
// 设计色彩
|
|
static const Color _orange = Color(0xFFFF6B00);
|
|
static const Color _grayText = Color(0xFF9CA3AF);
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Scaffold(
|
|
body: child,
|
|
bottomNavigationBar: Container(
|
|
decoration: BoxDecoration(
|
|
color: Colors.white,
|
|
boxShadow: [
|
|
BoxShadow(
|
|
color: Colors.black.withOpacity(0.05),
|
|
blurRadius: 10,
|
|
offset: const Offset(0, -2),
|
|
),
|
|
],
|
|
),
|
|
child: SafeArea(
|
|
top: false,
|
|
child: Container(
|
|
height: 56,
|
|
padding: const EdgeInsets.symmetric(horizontal: 16),
|
|
child: Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: [
|
|
_buildNavItem(
|
|
context,
|
|
icon: Icons.favorite_outline,
|
|
activeIcon: Icons.favorite,
|
|
label: '贡献值',
|
|
index: 0,
|
|
),
|
|
_buildNavItem(
|
|
context,
|
|
icon: Icons.swap_horiz_outlined,
|
|
activeIcon: Icons.swap_horiz,
|
|
label: '兑换',
|
|
index: 1,
|
|
),
|
|
_buildNavItem(
|
|
context,
|
|
icon: Icons.account_balance_wallet_outlined,
|
|
activeIcon: Icons.account_balance_wallet,
|
|
label: '资产',
|
|
index: 2,
|
|
),
|
|
_buildNavItem(
|
|
context,
|
|
icon: Icons.person_outline,
|
|
activeIcon: Icons.person,
|
|
label: '我的',
|
|
index: 3,
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildNavItem(
|
|
BuildContext context, {
|
|
required IconData icon,
|
|
required IconData activeIcon,
|
|
required String label,
|
|
required int index,
|
|
}) {
|
|
final currentIndex = _calculateSelectedIndex(context);
|
|
final isSelected = currentIndex == index;
|
|
|
|
return GestureDetector(
|
|
onTap: () => _onItemTapped(index, context),
|
|
behavior: HitTestBehavior.opaque,
|
|
child: SizedBox(
|
|
width: 64,
|
|
child: Column(
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
children: [
|
|
Icon(
|
|
isSelected ? activeIcon : icon,
|
|
size: 24,
|
|
color: isSelected ? _orange : _grayText,
|
|
),
|
|
const SizedBox(height: 4),
|
|
Text(
|
|
label,
|
|
style: TextStyle(
|
|
fontSize: 11,
|
|
fontWeight: isSelected ? FontWeight.w600 : FontWeight.w400,
|
|
color: isSelected ? _orange : _grayText,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
int _calculateSelectedIndex(BuildContext context) {
|
|
final location = GoRouterState.of(context).uri.path;
|
|
if (location.startsWith(Routes.contribution)) return 0;
|
|
if (location.startsWith(Routes.trading)) return 1;
|
|
if (location.startsWith(Routes.asset)) return 2;
|
|
if (location.startsWith(Routes.profile)) return 3;
|
|
return 0;
|
|
}
|
|
|
|
void _onItemTapped(int index, BuildContext context) {
|
|
switch (index) {
|
|
case 0:
|
|
context.go(Routes.contribution);
|
|
break;
|
|
case 1:
|
|
context.go(Routes.trading);
|
|
break;
|
|
case 2:
|
|
context.go(Routes.asset);
|
|
break;
|
|
case 3:
|
|
context.go(Routes.profile);
|
|
break;
|
|
}
|
|
}
|
|
}
|