feat(nav): 底部导航改为首页推荐追剧我的

This commit is contained in:
Zhou Weidong committed 2026-10-22 16:21:05 +08:00
1 parent ec3cb8f163
commit 91e869d589
34 files changed
+359 -263

No files matched your search

+6 -1
View File
@@ -69,6 +69,11 @@ abstract final class AppColors {
/// 底部导航底色。
static const bar = ink;
/// 底部导航专用:纯黑背景、选中白、未选中灰与轻分割线。
static const navBackground = Color(0xFF000000);
static const navSelected = Color(0xFFFFFFFF);
static const navDivider = Color(0xFF1C1C1E);
/// 卡片阴影(深色几乎不用阴影)。
static const cardShadow = Color(0x00000000);
@@ -121,7 +126,7 @@ abstract final class AppColors {
static const badgeBeige = raised;
/// 导航未选中。
static const navUnselected = muted;
static const navUnselected = Color(0xFF8A8A8E);
/// 播放器次要文字。
static const playerMuted = Color(0xA3FFFFFF);
+1 -1
View File
@@ -36,7 +36,7 @@ abstract final class AppDimens {
static const double previewCardTitle = 13;
static const double previewSectionTitle = 14;
static const double chipFont = 10;
static const double navLabel = 12;
static const double navLabel = 11;
static const double buttonHeight = 48;
static const double primaryButtonHeight = 52;
+2 -2
View File
@@ -193,8 +193,8 @@ abstract final class AppTheme {
),
),
bottomNavigationBarTheme: const BottomNavigationBarThemeData(
backgroundColor: AppColors.bar,
selectedItemColor: AppColors.blue,
backgroundColor: AppColors.navBackground,
selectedItemColor: AppColors.navSelected,
unselectedItemColor: AppColors.navUnselected,
elevation: 0,
type: BottomNavigationBarType.fixed,
+16 -20
View File
@@ -1,7 +1,5 @@
// Author: fruit.com.cn
import 'dart:ui';
import 'package:flutter/material.dart';
import '../theme/app_colors.dart';
@@ -26,12 +24,12 @@ class AppBottomNavItem {
final bool selected;
}
/// 四槽底部导航:所有页面统一深色底与浅色图标。
/// 四槽底部导航:纯黑背景,白色选中态,灰色未选中态。
class AppBottomNav extends StatelessWidget {
const AppBottomNav({
super.key,
required this.items,
this.backgroundColor = AppColors.bar,
this.backgroundColor = AppColors.navBackground,
this.barKey,
this.dark = false,
});
@@ -47,8 +45,10 @@ class AppBottomNav extends StatelessWidget {
key: barKey,
height: AppDimens.navHeight,
decoration: BoxDecoration(
color: dark ? AppColors.bar : backgroundColor.withValues(alpha: 0.96),
border: const Border(top: BorderSide(color: AppColors.border)),
color: dark ? AppColors.navBackground : backgroundColor,
border: const Border(
top: BorderSide(color: AppColors.navDivider, width: 0.5),
),
),
child: Row(
children: [
@@ -60,17 +60,9 @@ class AppBottomNav extends StatelessWidget {
],
),
);
if (dark) {
return ColoredBox(
color: AppColors.bar,
child: SafeArea(top: false, child: bar),
);
}
return ClipRect(
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 20, sigmaY: 20),
child: SafeArea(top: false, child: bar),
),
return ColoredBox(
color: AppColors.navBackground,
child: SafeArea(top: false, child: bar),
);
}
}
@@ -102,7 +94,9 @@ class _NavDestination extends StatelessWidget {
child: Icon(
item.selected ? item.selectedIcon : item.icon,
size: AppDimens.navIcon,
color: item.selected ? AppColors.blue : unselectedColor,
color: item.selected
? AppColors.navSelected
: unselectedColor,
),
),
const SizedBox(height: 3),
@@ -112,8 +106,10 @@ class _NavDestination extends StatelessWidget {
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontSize: AppDimens.navLabel,
fontWeight: item.selected ? FontWeight.w700 : FontWeight.w500,
color: item.selected ? AppColors.blue : unselectedColor,
fontWeight: item.selected ? FontWeight.w600 : FontWeight.w400,
color: item.selected
? AppColors.navSelected
: unselectedColor,
letterSpacing: 0,
),
),
+38
View File
@@ -0,0 +1,38 @@
// Author: fruit.com.cn
import 'package:flutter/material.dart';
import '../../l10n/app_localizations.dart';
/// 客户端根导航的固定顺序。
enum AppRootTab { home, recommend, following, mine }
extension AppRootTabUi on AppRootTab {
Key get tabKey => switch (this) {
AppRootTab.home => const Key('tab-home'),
AppRootTab.recommend => const Key('tab-recommend'),
AppRootTab.following => const Key('tab-follow'),
AppRootTab.mine => const Key('tab-mine'),
};
IconData get icon => switch (this) {
AppRootTab.home => Icons.home_outlined,
AppRootTab.recommend => Icons.smart_display_outlined,
AppRootTab.following => Icons.bookmark_border_rounded,
AppRootTab.mine => Icons.person_outline_rounded,
};
IconData get selectedIcon => switch (this) {
AppRootTab.home => Icons.home_rounded,
AppRootTab.recommend => Icons.smart_display_rounded,
AppRootTab.following => Icons.bookmark_rounded,
AppRootTab.mine => Icons.person_rounded,
};
String label(AppLocalizations l10n) => switch (this) {
AppRootTab.home => l10n.homeTab,
AppRootTab.recommend => l10n.recommendedTab,
AppRootTab.following => l10n.followingTab,
AppRootTab.mine => l10n.myTab,
};
}
+10 -2
View File
@@ -120,6 +120,7 @@ class AppSubpageHeader extends StatelessWidget {
this.actions,
this.onBack,
this.dark = false,
this.showBack = true,
});
final String title;
@@ -128,6 +129,7 @@ class AppSubpageHeader extends StatelessWidget {
final Widget? actions;
final VoidCallback? onBack;
final bool dark;
final bool showBack;
@override
Widget build(BuildContext context) {
@@ -140,8 +142,14 @@ class AppSubpageHeader extends StatelessWidget {
padding: const EdgeInsets.symmetric(horizontal: _horizontal),
child: Row(
children: [
AppSubpageBackButton(backKey: backKey, dark: dark, onBack: onBack),
const SizedBox(width: _backGap),
if (showBack) ...[
AppSubpageBackButton(
backKey: backKey,
dark: dark,
onBack: onBack,
),
const SizedBox(width: _backGap),
],
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,