style(theme): 客户端切换深色视觉风格
This commit is contained in:
1 parent
295c21513c
commit
4bc04fd8ae
75 files changed
+732
-330
No files matched your search
@@ -2,107 +2,143 @@
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// K28-S 浅色暖橙主题色板。
|
||||
/// 深色视觉色板。
|
||||
///
|
||||
/// 保留既有语义名,避免页面大范围改名;实际颜色统一由本文件控制。
|
||||
abstract final class AppColors {
|
||||
/// 主操作、选中态、播放进度。
|
||||
static const blue = Color(0xFFFF7A1A);
|
||||
/// 透明与媒体黑底。
|
||||
static const transparent = Colors.transparent;
|
||||
static const mediaBlack = Color(0xFF000000);
|
||||
|
||||
/// 阴影与遮罩层级。
|
||||
static const shadowSubtle = Color(0x14000000);
|
||||
static const shadowSoft = Color(0x33000000);
|
||||
static const shadow = Color(0x8A000000);
|
||||
static const shadowStrong = Color(0xE6000000);
|
||||
static const scrim = Color(0xD1000000);
|
||||
static const controlScrim = Color(0x80000000);
|
||||
static const controlSoftScrim = Color(0x42000000);
|
||||
static const scrubPreviewScrim = Color(0xDE000000);
|
||||
static const overlaySoft = Color(0x66000000);
|
||||
static const overlayBar = Color(0x4D000000);
|
||||
static const overlayMedium = Color(0x99000000);
|
||||
static const headerScrim = Color(0x59000000);
|
||||
|
||||
/// 主操作、选中态、播放进度(品牌橙)。
|
||||
static const blue = Color(0xFFFF6B2C);
|
||||
static const primary = blue;
|
||||
|
||||
/// 主操作按下态。
|
||||
static const bluePressed = Color(0xFFFF6A00);
|
||||
static const bluePressed = Color(0xFFE55A1F);
|
||||
|
||||
/// 粉色辅助强调色。
|
||||
static const blueSoft = Color(0xFFFF6A8A);
|
||||
/// 链接与次要高亮(禁止大面积铺色)。
|
||||
static const blueSoft = Color(0xFF22D3EE);
|
||||
static const secondary = blueSoft;
|
||||
static const lavender = blueSoft;
|
||||
|
||||
/// 金币与奖励。
|
||||
static const gold = Color(0xFFF3B34C);
|
||||
static const goldDeep = Color(0xFFD9A23A);
|
||||
static const bronze = Color(0xFFCD7F32);
|
||||
static const bronzeDeep = Color(0xFFA9713A);
|
||||
|
||||
/// 成功状态。
|
||||
static const success = Color(0xFF2FA873);
|
||||
|
||||
/// 收藏和喜欢使用粉色强调。
|
||||
static const favorite = secondary;
|
||||
/// 错误与危险操作。
|
||||
static const error = Color(0xFFFF6B6B);
|
||||
|
||||
/// 收藏与喜欢(非主色铺色,独立强调)。
|
||||
static const favorite = Color(0xFFFF6A8A);
|
||||
|
||||
/// 金币底色上的文字。
|
||||
static const onGold = Color(0xFF5A3511);
|
||||
static const onGold = Color(0xFF3D2408);
|
||||
|
||||
/// 主色上的文字与图标。
|
||||
static const onPrimary = Color(0xFFFFFFFF);
|
||||
|
||||
/// 页面背景。
|
||||
static const ink = Color(0xFFFFF8F0);
|
||||
static const ink = Color(0xFF0B1020);
|
||||
|
||||
/// 原生开屏与冷启动过渡底色。
|
||||
static const splashInk = Color(0xFF1F1B16);
|
||||
static const splashInk = ink;
|
||||
|
||||
/// 页面顶部暖色渐变起点。
|
||||
static const surfaceTop = Color(0xFFFFE9D6);
|
||||
/// 顶部与页面底同色,靠容器层次区分。
|
||||
static const surfaceTop = ink;
|
||||
|
||||
/// 底部导航底色。
|
||||
static const bar = Color(0xFFFFFDFB);
|
||||
static const bar = ink;
|
||||
|
||||
/// 卡片轻阴影。
|
||||
static const cardShadow = Color(0x14FF8A3D);
|
||||
/// 卡片阴影(深色几乎不用阴影)。
|
||||
static const cardShadow = Color(0x00000000);
|
||||
|
||||
/// 卡片与弹层。
|
||||
static const card = Color(0xFFFFFFFF);
|
||||
/// 卡片与列表容器。
|
||||
static const card = Color(0xFF151B2E);
|
||||
|
||||
/// 次要卡片表面。
|
||||
static const cardAlt = Color(0xFFFFF4E9);
|
||||
static const cardAlt = card;
|
||||
|
||||
/// 浮层、输入框和嵌套区域。
|
||||
static const raised = Color(0xFFFFF1E5);
|
||||
static const quick = Color(0xFFFFF0E1);
|
||||
static const input = Color(0xFFFFF4EA);
|
||||
/// 浮层、弹窗、输入与嵌套区域。
|
||||
static const raised = Color(0xFF1C2436);
|
||||
static const quick = raised;
|
||||
static const input = raised;
|
||||
|
||||
/// 评论输入框底色。
|
||||
static const commentInput = Color(0xFFF5EFE8);
|
||||
static const goldCard = Color(0xFFFFF4DF);
|
||||
static const commentInput = raised;
|
||||
static const goldCard = Color(0xFF2A2418);
|
||||
|
||||
/// 正文颜色。
|
||||
static const cream = Color(0xFF1F1B16);
|
||||
/// 正文颜色(与主文字同级)。
|
||||
static const cream = Color(0xEBFFFFFF);
|
||||
|
||||
/// 主文字。
|
||||
static const onSurface = Color(0xFF1F1B16);
|
||||
/// 主文字 rgba(255,255,255,0.92)。
|
||||
static const onSurface = Color(0xEBFFFFFF);
|
||||
|
||||
/// 次要文字。
|
||||
static const muted = Color(0xFF8C837B);
|
||||
/// 次要文字 rgba(255,255,255,0.64)。
|
||||
static const muted = Color(0xA3FFFFFF);
|
||||
|
||||
/// 弱提示与时间。
|
||||
static const subtle = Color(0xFFB3AAA1);
|
||||
/// 弱提示与禁用 rgba(255,255,255,0.38)。
|
||||
static const subtle = Color(0x61FFFFFF);
|
||||
|
||||
/// 橙色强调文案。
|
||||
static const accent = blue;
|
||||
|
||||
/// 卡片描边。
|
||||
static const border = Color(0xFFF0E4D6);
|
||||
/// 分割线 rgba(255,255,255,0.06)。
|
||||
static const border = Color(0x0FFFFFFF);
|
||||
|
||||
/// 玻璃面板描边。
|
||||
static const glassBorder = Color(0x66FFFFFF);
|
||||
static const glassBorder = Color(0x33FFFFFF);
|
||||
static const glassSurfaceStart = Color(0xEB1C2436);
|
||||
static const glassSurfaceEnd = Color(0xD1151B2E);
|
||||
|
||||
/// 粉色角标。
|
||||
static const badgePink = Color(0xFFFFE3EC);
|
||||
static const badgePinkText = Color(0xFFFF6A8A);
|
||||
/// 角标底与文字。
|
||||
static const badgePink = Color(0x33FF6A8A);
|
||||
static const badgePinkText = favorite;
|
||||
|
||||
/// 封面锁定数量与视频遮罩。
|
||||
static const overlayDark = Color(0x33000000);
|
||||
static const overlayDark = Color(0x66000000);
|
||||
|
||||
/// 封面集数胶囊。
|
||||
static const badgeBeige = Color(0xFFFFF0DF);
|
||||
static const badgeBeige = raised;
|
||||
|
||||
/// 导航未选中。
|
||||
static const navUnselected = muted;
|
||||
|
||||
/// 播放器次要文字。
|
||||
static const playerMuted = Color(0xFFBBBBBB);
|
||||
static const playerMuted = Color(0xA3FFFFFF);
|
||||
|
||||
/// 播放器控件胶囊与圆形底色。
|
||||
static const playerOverlayPill = Color(0xB3000000);
|
||||
|
||||
/// 进度条未激活轨道。
|
||||
static const inactiveTrack = Color(0x24FFFFFF);
|
||||
|
||||
/// 横幅/封面底部渐变。
|
||||
static const bannerScrimMid = Color(0x8A0B1020);
|
||||
static const bannerScrimEnd = Color(0xE6000000);
|
||||
|
||||
/// 票券虚线等主色描边。
|
||||
static const primaryBorder = Color(0x66FF6B2C);
|
||||
|
||||
static const outlineDark = border;
|
||||
static const outlineVariantDark = border;
|
||||
static const outlineLight = muted;
|
||||
|
||||
@@ -9,18 +9,20 @@ abstract final class AppDimens {
|
||||
static const double spaceXl = 24;
|
||||
|
||||
static const double pageHorizontal = 16;
|
||||
static const double cardRadius = 16;
|
||||
static const double authCardRadius = 20;
|
||||
static const double cardRadius = 12;
|
||||
static const double authCardRadius = 12;
|
||||
static const double cardPadding = 16;
|
||||
static const double innerRadius = 12;
|
||||
static const double innerRadius = 10;
|
||||
static const double innerPadding = 12;
|
||||
static const double pillRadius = 999;
|
||||
static const double glassSmallRadius = 16;
|
||||
static const double glassRadius = 20;
|
||||
static const double glassCardRadius = 20;
|
||||
static const double buttonRadius = 999;
|
||||
static const double coverRadius = 16;
|
||||
static const double sheetRadius = 20;
|
||||
static const double glassSmallRadius = 12;
|
||||
static const double glassRadius = 12;
|
||||
static const double glassCardRadius = 12;
|
||||
static const double buttonRadius = 10;
|
||||
static const double inputRadius = 10;
|
||||
static const double chipRadius = 6;
|
||||
static const double coverRadius = 12;
|
||||
static const double sheetRadius = 12;
|
||||
|
||||
static const double caption = 12;
|
||||
static const double emptyStateSubtitle = 12.5;
|
||||
@@ -61,13 +63,13 @@ abstract final class AppDimens {
|
||||
|
||||
static const double watchPlaceholderHeight = 114;
|
||||
static const double heroBannerHeight = 240;
|
||||
static const double heroBannerRadius = 20;
|
||||
static const double heroBannerRadius = 12;
|
||||
static const double heroTitle = 28;
|
||||
static const double heroSubtitle = 14;
|
||||
|
||||
static const double cardMeta = 12;
|
||||
static const double cardViews = 11;
|
||||
static const double cardTitle = 15;
|
||||
static const double cardShadowBlur = 18;
|
||||
static const double cardShadowY = 6;
|
||||
static const double cardShadowBlur = 0;
|
||||
static const double cardShadowY = 0;
|
||||
}
|
||||
+140
-24
@@ -6,9 +6,9 @@ import 'package:flutter/services.dart';
|
||||
import 'app_colors.dart';
|
||||
import 'app_dimens.dart';
|
||||
|
||||
/// K28-S 浅色暖橙主题。
|
||||
/// 深色视觉主题(默认且唯一)。
|
||||
abstract final class AppTheme {
|
||||
/// 页面顶部暖色到米白背景的渐变。
|
||||
/// 页面背景:深色扁平,靠容器层次区分。
|
||||
static const LinearGradient pageGradient = LinearGradient(
|
||||
begin: Alignment.topCenter,
|
||||
end: Alignment.bottomCenter,
|
||||
@@ -16,36 +16,50 @@ abstract final class AppTheme {
|
||||
stops: [0, 0.24],
|
||||
);
|
||||
|
||||
/// 卡片轻阴影。
|
||||
/// 卡片阴影关闭,改用底色与分割线。
|
||||
static const BoxShadow cardShadow = BoxShadow(
|
||||
color: AppColors.cardShadow,
|
||||
blurRadius: AppDimens.cardShadowBlur,
|
||||
offset: Offset(0, AppDimens.cardShadowY),
|
||||
);
|
||||
|
||||
/// 全局浅色暖橙主题。
|
||||
static ThemeData light() {
|
||||
const scheme = ColorScheme.light(
|
||||
static final BorderRadius _buttonRadius = BorderRadius.circular(
|
||||
AppDimens.buttonRadius,
|
||||
);
|
||||
static final BorderRadius _cardRadius = BorderRadius.circular(
|
||||
AppDimens.cardRadius,
|
||||
);
|
||||
static final BorderRadius _inputRadius = BorderRadius.circular(
|
||||
AppDimens.inputRadius,
|
||||
);
|
||||
|
||||
/// 全局深色主题。
|
||||
static ThemeData dark() {
|
||||
const scheme = ColorScheme.dark(
|
||||
primary: AppColors.blue,
|
||||
onPrimary: AppColors.onPrimary,
|
||||
secondary: AppColors.secondary,
|
||||
onSecondary: AppColors.onPrimary,
|
||||
primaryContainer: AppColors.surfaceTop,
|
||||
onSecondary: AppColors.ink,
|
||||
primaryContainer: AppColors.raised,
|
||||
onPrimaryContainer: AppColors.onSurface,
|
||||
secondaryContainer: AppColors.badgePink,
|
||||
onSecondaryContainer: AppColors.badgePinkText,
|
||||
surface: AppColors.ink,
|
||||
onSurface: AppColors.onSurface,
|
||||
surfaceContainerHighest: AppColors.raised,
|
||||
outline: AppColors.border,
|
||||
outlineVariant: AppColors.border,
|
||||
surfaceTint: AppColors.blue,
|
||||
surfaceTint: AppColors.transparent,
|
||||
inversePrimary: AppColors.bluePressed,
|
||||
error: AppColors.error,
|
||||
onError: AppColors.onPrimary,
|
||||
);
|
||||
final base = ThemeData(
|
||||
useMaterial3: true,
|
||||
brightness: Brightness.light,
|
||||
brightness: Brightness.dark,
|
||||
colorScheme: scheme,
|
||||
scaffoldBackgroundColor: AppColors.ink,
|
||||
canvasColor: AppColors.ink,
|
||||
fontFamily: 'PlusJakartaSans',
|
||||
progressIndicatorTheme: const ProgressIndicatorThemeData(
|
||||
color: AppColors.blue,
|
||||
@@ -61,7 +75,23 @@ abstract final class AppTheme {
|
||||
unselectedLabelColor: AppColors.muted,
|
||||
),
|
||||
textButtonTheme: TextButtonThemeData(
|
||||
style: TextButton.styleFrom(foregroundColor: AppColors.blue),
|
||||
style: TextButton.styleFrom(
|
||||
foregroundColor: AppColors.secondary,
|
||||
shape: RoundedRectangleBorder(borderRadius: _buttonRadius),
|
||||
),
|
||||
),
|
||||
elevatedButtonTheme: ElevatedButtonThemeData(
|
||||
style: ButtonStyle(
|
||||
backgroundColor: WidgetStateProperty.resolveWith(_buttonColor),
|
||||
foregroundColor: const WidgetStatePropertyAll(AppColors.onPrimary),
|
||||
elevation: const WidgetStatePropertyAll(0),
|
||||
minimumSize: const WidgetStatePropertyAll(
|
||||
Size(0, AppDimens.buttonHeight),
|
||||
),
|
||||
shape: WidgetStatePropertyAll(
|
||||
RoundedRectangleBorder(borderRadius: _buttonRadius),
|
||||
),
|
||||
),
|
||||
),
|
||||
filledButtonTheme: FilledButtonThemeData(
|
||||
style: ButtonStyle(
|
||||
@@ -70,7 +100,9 @@ abstract final class AppTheme {
|
||||
minimumSize: const WidgetStatePropertyAll(
|
||||
Size(0, AppDimens.buttonHeight),
|
||||
),
|
||||
shape: const WidgetStatePropertyAll(StadiumBorder()),
|
||||
shape: WidgetStatePropertyAll(
|
||||
RoundedRectangleBorder(borderRadius: _buttonRadius),
|
||||
),
|
||||
),
|
||||
),
|
||||
outlinedButtonTheme: OutlinedButtonThemeData(
|
||||
@@ -82,14 +114,46 @@ abstract final class AppTheme {
|
||||
side: const WidgetStatePropertyAll(
|
||||
BorderSide(color: AppColors.border),
|
||||
),
|
||||
shape: const WidgetStatePropertyAll(StadiumBorder()),
|
||||
shape: WidgetStatePropertyAll(
|
||||
RoundedRectangleBorder(borderRadius: _buttonRadius),
|
||||
),
|
||||
),
|
||||
),
|
||||
inputDecorationTheme: InputDecorationTheme(
|
||||
filled: true,
|
||||
fillColor: AppColors.input,
|
||||
hintStyle: const TextStyle(color: AppColors.subtle),
|
||||
labelStyle: const TextStyle(color: AppColors.muted),
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: _inputRadius,
|
||||
borderSide: const BorderSide(color: AppColors.border),
|
||||
),
|
||||
enabledBorder: OutlineInputBorder(
|
||||
borderRadius: _inputRadius,
|
||||
borderSide: const BorderSide(color: AppColors.border),
|
||||
),
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderRadius: _inputRadius,
|
||||
borderSide: const BorderSide(color: AppColors.blue),
|
||||
),
|
||||
),
|
||||
chipTheme: ChipThemeData(
|
||||
backgroundColor: AppColors.raised,
|
||||
selectedColor: AppColors.blue.withValues(alpha: 0.22),
|
||||
labelStyle: const TextStyle(color: AppColors.onSurface),
|
||||
secondaryLabelStyle: const TextStyle(color: AppColors.muted),
|
||||
side: const BorderSide(color: AppColors.border),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(AppDimens.chipRadius),
|
||||
),
|
||||
),
|
||||
appBarTheme: const AppBarTheme(
|
||||
backgroundColor: AppColors.ink,
|
||||
backgroundColor: AppColors.card,
|
||||
foregroundColor: AppColors.onSurface,
|
||||
elevation: 0,
|
||||
systemOverlayStyle: SystemUiOverlayStyle.dark,
|
||||
scrolledUnderElevation: 0,
|
||||
surfaceTintColor: AppColors.transparent,
|
||||
systemOverlayStyle: SystemUiOverlayStyle.light,
|
||||
titleTextStyle: TextStyle(
|
||||
color: AppColors.onSurface,
|
||||
fontFamily: 'Outfit',
|
||||
@@ -98,19 +162,47 @@ abstract final class AppTheme {
|
||||
),
|
||||
),
|
||||
iconTheme: const IconThemeData(color: AppColors.onSurface),
|
||||
dividerTheme: const DividerThemeData(color: AppColors.border),
|
||||
cardTheme: const CardThemeData(
|
||||
dividerTheme: const DividerThemeData(
|
||||
color: AppColors.border,
|
||||
thickness: 1,
|
||||
space: 1,
|
||||
),
|
||||
cardTheme: CardThemeData(
|
||||
color: AppColors.card,
|
||||
elevation: 0,
|
||||
shadowColor: AppColors.transparent,
|
||||
surfaceTintColor: AppColors.transparent,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(Radius.circular(AppDimens.cardRadius)),
|
||||
side: BorderSide(color: AppColors.border),
|
||||
borderRadius: _cardRadius,
|
||||
side: const BorderSide(color: AppColors.border),
|
||||
),
|
||||
),
|
||||
dialogTheme: DialogThemeData(
|
||||
backgroundColor: AppColors.raised,
|
||||
surfaceTintColor: AppColors.transparent,
|
||||
shape: RoundedRectangleBorder(borderRadius: _cardRadius),
|
||||
titleTextStyle: const TextStyle(
|
||||
color: AppColors.onSurface,
|
||||
fontFamily: 'Outfit',
|
||||
fontSize: AppDimens.sectionTitle,
|
||||
fontWeight: FontWeight.w700,
|
||||
),
|
||||
contentTextStyle: const TextStyle(
|
||||
color: AppColors.muted,
|
||||
fontSize: AppDimens.body,
|
||||
),
|
||||
),
|
||||
bottomNavigationBarTheme: const BottomNavigationBarThemeData(
|
||||
backgroundColor: AppColors.bar,
|
||||
selectedItemColor: AppColors.blue,
|
||||
unselectedItemColor: AppColors.navUnselected,
|
||||
elevation: 0,
|
||||
type: BottomNavigationBarType.fixed,
|
||||
),
|
||||
bottomSheetTheme: const BottomSheetThemeData(
|
||||
backgroundColor: Colors.transparent,
|
||||
modalBackgroundColor: Colors.transparent,
|
||||
surfaceTintColor: Colors.transparent,
|
||||
backgroundColor: AppColors.transparent,
|
||||
modalBackgroundColor: AppColors.transparent,
|
||||
surfaceTintColor: AppColors.transparent,
|
||||
),
|
||||
switchTheme: SwitchThemeData(
|
||||
thumbColor: WidgetStateProperty.resolveWith(
|
||||
@@ -124,8 +216,13 @@ abstract final class AppTheme {
|
||||
),
|
||||
),
|
||||
snackBarTheme: const SnackBarThemeData(
|
||||
backgroundColor: AppColors.onSurface,
|
||||
contentTextStyle: TextStyle(color: AppColors.onPrimary),
|
||||
backgroundColor: AppColors.raised,
|
||||
contentTextStyle: TextStyle(color: AppColors.onSurface),
|
||||
actionTextColor: AppColors.secondary,
|
||||
),
|
||||
listTileTheme: const ListTileThemeData(
|
||||
iconColor: AppColors.onSurface,
|
||||
textColor: AppColors.onSurface,
|
||||
),
|
||||
);
|
||||
final textTheme = base.textTheme
|
||||
@@ -142,10 +239,29 @@ abstract final class AppTheme {
|
||||
headlineMedium: _display(base.textTheme.headlineMedium),
|
||||
headlineSmall: _display(base.textTheme.headlineSmall),
|
||||
titleLarge: _display(base.textTheme.titleLarge),
|
||||
bodyLarge: base.textTheme.bodyLarge?.copyWith(
|
||||
color: AppColors.onSurface,
|
||||
),
|
||||
bodyMedium: base.textTheme.bodyMedium?.copyWith(
|
||||
color: AppColors.onSurface,
|
||||
),
|
||||
bodySmall: base.textTheme.bodySmall?.copyWith(color: AppColors.muted),
|
||||
labelLarge: base.textTheme.labelLarge?.copyWith(
|
||||
color: AppColors.onSurface,
|
||||
),
|
||||
labelMedium: base.textTheme.labelMedium?.copyWith(
|
||||
color: AppColors.muted,
|
||||
),
|
||||
labelSmall: base.textTheme.labelSmall?.copyWith(
|
||||
color: AppColors.subtle,
|
||||
),
|
||||
);
|
||||
return base.copyWith(textTheme: textTheme);
|
||||
}
|
||||
|
||||
/// 兼容旧调用点,统一落到深色主题。
|
||||
static ThemeData light() => dark();
|
||||
|
||||
static TextStyle? _display(TextStyle? style) =>
|
||||
style?.copyWith(fontFamily: 'Outfit', color: AppColors.onSurface);
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ class AppBottomNavItem {
|
||||
final bool selected;
|
||||
}
|
||||
|
||||
/// 四槽底部导航:首页 feed 用深色样式,其它页面保持浅色暖橙风格。
|
||||
/// 四槽底部导航:所有页面统一深色底与浅色图标。
|
||||
class AppBottomNav extends StatelessWidget {
|
||||
const AppBottomNav({
|
||||
super.key,
|
||||
@@ -47,24 +47,22 @@ class AppBottomNav extends StatelessWidget {
|
||||
key: barKey,
|
||||
height: AppDimens.navHeight,
|
||||
decoration: BoxDecoration(
|
||||
color: dark ? Colors.black : backgroundColor.withValues(alpha: 0.95),
|
||||
border: Border(
|
||||
top: BorderSide(color: dark ? Colors.white12 : AppColors.border),
|
||||
),
|
||||
color: dark ? AppColors.bar : backgroundColor.withValues(alpha: 0.96),
|
||||
border: const Border(top: BorderSide(color: AppColors.border)),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
for (final item in items)
|
||||
_NavDestination(
|
||||
item: item,
|
||||
unselectedColor: dark ? Colors.white70 : AppColors.navUnselected,
|
||||
unselectedColor: AppColors.navUnselected,
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
if (dark) {
|
||||
return ColoredBox(
|
||||
color: Colors.black,
|
||||
color: AppColors.bar,
|
||||
child: SafeArea(top: false, child: bar),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ Future<bool> ensureSignedIn(BuildContext context) async {
|
||||
Text(
|
||||
l10n.authGateTitle,
|
||||
style: const TextStyle(
|
||||
color: Colors.white,
|
||||
color: AppColors.onSurface,
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w800,
|
||||
),
|
||||
@@ -98,7 +98,7 @@ class AuthGatePanel extends StatelessWidget {
|
||||
l10n.authGateTitle,
|
||||
textAlign: TextAlign.center,
|
||||
style: const TextStyle(
|
||||
color: Colors.white,
|
||||
color: AppColors.onSurface,
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.w800,
|
||||
),
|
||||
|
||||
@@ -5,6 +5,7 @@ import 'package:flutter/material.dart';
|
||||
|
||||
import '../config/app_config.dart';
|
||||
import '../config/server_endpoint.dart';
|
||||
import '../theme/app_colors.dart';
|
||||
|
||||
const String _title = '设置服务地址';
|
||||
const String _save = '保存';
|
||||
@@ -94,7 +95,7 @@ class _CatalogEndpointDialogState extends State<_CatalogEndpointDialog> {
|
||||
const Text(
|
||||
_localNetworkHint,
|
||||
key: Key('catalog-debug-endpoint-hint'),
|
||||
style: TextStyle(fontSize: 12, color: Colors.grey),
|
||||
style: TextStyle(fontSize: 12, color: AppColors.muted),
|
||||
),
|
||||
if (_error != null) ...[
|
||||
const SizedBox(height: 8),
|
||||
|
||||
@@ -4,6 +4,8 @@ import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../theme/app_colors.dart';
|
||||
|
||||
const Key _toastKey = Key('centered-toast');
|
||||
const Duration _fadeDuration = Duration(milliseconds: 200);
|
||||
const Duration _visibleDuration = Duration(seconds: 2);
|
||||
@@ -11,9 +13,8 @@ const double _toastRadius = 12;
|
||||
const double _toastMaxWidth = 320;
|
||||
const double _toastHorizontalInset = 20;
|
||||
const double _toastVerticalInset = 12;
|
||||
const double _toastBackgroundOpacity = 0.78;
|
||||
const TextStyle _toastTextStyle = TextStyle(
|
||||
color: Colors.white,
|
||||
color: AppColors.onSurface,
|
||||
fontSize: 14,
|
||||
height: 1.4,
|
||||
fontWeight: FontWeight.w500,
|
||||
@@ -108,10 +109,9 @@ class _CenteredToastState extends State<_CenteredToast>
|
||||
constraints: const BoxConstraints(maxWidth: _toastMaxWidth),
|
||||
padding: _toastPadding,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.black.withValues(
|
||||
alpha: _toastBackgroundOpacity,
|
||||
),
|
||||
color: AppColors.raised,
|
||||
borderRadius: BorderRadius.circular(_toastRadius),
|
||||
border: Border.all(color: AppColors.border),
|
||||
),
|
||||
child: Text(
|
||||
widget.message,
|
||||
|
||||
@@ -87,12 +87,11 @@ class _EmptyMark extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final dark = Theme.of(context).brightness == Brightness.dark;
|
||||
return Icon(
|
||||
icon,
|
||||
key: const Key('empty-state-icon'),
|
||||
size: compact ? _compactIconSize : _regularIconSize,
|
||||
color: dark ? AppColors.gold : AppColors.blue,
|
||||
color: AppColors.blueSoft,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import 'package:flutter/material.dart';
|
||||
import '../theme/app_colors.dart';
|
||||
import '../theme/app_dimens.dart';
|
||||
|
||||
/// 首页信息卡与浮层控件使用的浅色玻璃面板。
|
||||
/// 首页信息卡与浮层控件使用的深色玻璃面板。
|
||||
class GlassPanel extends StatelessWidget {
|
||||
const GlassPanel({
|
||||
super.key,
|
||||
@@ -38,7 +38,7 @@ class GlassPanel extends StatelessWidget {
|
||||
const LinearGradient(
|
||||
begin: Alignment.topLeft,
|
||||
end: Alignment.bottomRight,
|
||||
colors: [Color(0xE6FFFFFF), Color(0xB3FFFDFB)],
|
||||
colors: [AppColors.glassSurfaceStart, AppColors.glassSurfaceEnd],
|
||||
),
|
||||
),
|
||||
child: Padding(padding: padding ?? EdgeInsets.zero, child: child),
|
||||
|
||||
@@ -16,7 +16,7 @@ class RemoteImage extends StatelessWidget {
|
||||
this.showFallbackIcon = false,
|
||||
this.fallbackIconKey,
|
||||
this.fallbackAspectRatio,
|
||||
this.fallbackColor = AppColors.bar,
|
||||
this.fallbackColor = AppColors.raised,
|
||||
});
|
||||
|
||||
final String path;
|
||||
|
||||
@@ -16,9 +16,6 @@ const double _iconSize = 22;
|
||||
const double _iconWeight = 600;
|
||||
const double _borderWidth = 1;
|
||||
const double _shadowBlur = 8;
|
||||
const Color _lightShadowColor = Color(0x14000000);
|
||||
const Color _darkBackground = Color(0x59000000);
|
||||
const Color _darkShadowColor = Color(0x33000000);
|
||||
const Offset _lightShadowOffset = Offset(0, 2);
|
||||
|
||||
/// 二级页面统一圆形操作按钮,返回、分享和更多共用同一尺寸与表面样式。
|
||||
@@ -52,14 +49,14 @@ class AppSubpageCircleButton extends StatelessWidget {
|
||||
shape: BoxShape.circle,
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: dark ? _darkShadowColor : _lightShadowColor,
|
||||
color: dark ? AppColors.shadowSoft : AppColors.shadowSubtle,
|
||||
blurRadius: _shadowBlur,
|
||||
offset: dark ? Offset.zero : _lightShadowOffset,
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Material(
|
||||
color: dark ? _darkBackground : AppColors.card,
|
||||
color: dark ? AppColors.headerScrim : AppColors.card,
|
||||
shape: CircleBorder(
|
||||
side: dark
|
||||
? BorderSide.none
|
||||
@@ -75,7 +72,7 @@ class AppSubpageCircleButton extends StatelessWidget {
|
||||
child: Center(
|
||||
child: Icon(
|
||||
icon,
|
||||
color: dark ? Colors.white : AppColors.onSurface,
|
||||
color: AppColors.onSurface,
|
||||
size: _iconSize,
|
||||
weight: _iconWeight,
|
||||
),
|
||||
@@ -134,8 +131,8 @@ class AppSubpageHeader extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final foreground = dark ? Colors.white : AppColors.onSurface;
|
||||
final secondary = dark ? Colors.white70 : AppColors.muted;
|
||||
final foreground = AppColors.onSurface;
|
||||
final secondary = AppColors.muted;
|
||||
return SizedBox(
|
||||
key: const Key('subpage-header'),
|
||||
height: subtitle == null ? _height : _heightWithSubtitle,
|
||||
|
||||
Reference in new issue
Block a user