feat(flutter): 统一二级页头并恢复新剧暖色

This commit is contained in:
Zhou Weidong committed 2026-10-20 15:55:12 +08:00
1 parent 7b2970d5c5
commit 1c6c92170d
26 files changed
+492 -427

No files matched your search

+5 -40
View File
@@ -3,6 +3,7 @@
import 'package:flutter/material.dart';
import '../theme/app_colors.dart';
import 'subpage_header.dart';
/// 二级页面通用骨架:返回栏 + 标题/副标题 + 可滚动内容,无底部导航。
class PlainPageScaffold extends StatelessWidget {
@@ -30,47 +31,11 @@ class PlainPageScaffold extends StatelessWidget {
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.fromLTRB(6, 4, 14, 0),
child: Row(
children: [
IconButton(
key: backKey,
tooltip: MaterialLocalizations.of(
context,
).backButtonTooltip,
onPressed: () => Navigator.of(context).maybePop(),
icon: const Icon(
Icons.chevron_left_rounded,
color: AppColors.onSurface,
size: 26,
),
),
Expanded(
child: Text(
title,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: const TextStyle(
color: AppColors.onSurface,
fontSize: 20,
fontWeight: FontWeight.w800,
),
),
),
],
),
AppSubpageHeader(
title: title,
subtitle: subtitle,
backKey: backKey,
),
if (subtitle != null)
Padding(
padding: const EdgeInsets.fromLTRB(16, 0, 16, 8),
child: Text(
subtitle!,
maxLines: 2,
overflow: TextOverflow.ellipsis,
style: const TextStyle(color: AppColors.muted, fontSize: 12),
),
),
Expanded(child: child),
],
),
+130
View File
@@ -0,0 +1,130 @@
// Author: fruit.com.cn
import 'package:flutter/material.dart';
import '../theme/app_colors.dart';
const double _height = 52;
const double _heightWithSubtitle = 64;
const double _horizontal = 14;
const double _backSize = 36;
const double _backGap = 12;
const double _titleFontSize = 18;
const double _subtitleFontSize = 12;
const double _actionGap = 8;
const double _iconSize = 20;
/// 二级页面统一返回按钮,浅色页使用 card 圆底,深色页使用透明底。
class AppSubpageBackButton extends StatelessWidget {
const AppSubpageBackButton({
super.key,
required this.backKey,
this.dark = false,
this.onBack,
});
final Key backKey;
final bool dark;
final VoidCallback? onBack;
@override
Widget build(BuildContext context) {
return SizedBox(
key: backKey,
width: _backSize,
height: _backSize,
child: Tooltip(
message: MaterialLocalizations.of(context).backButtonTooltip,
child: Material(
color: dark ? Colors.transparent : AppColors.card,
shape: const CircleBorder(),
clipBehavior: Clip.antiAlias,
child: InkWell(
onTap: onBack ?? () => Navigator.of(context).maybePop(),
child: Icon(
Icons.chevron_left_rounded,
color: dark ? Colors.white : AppColors.onSurface,
size: _iconSize,
),
),
),
),
);
}
}
/// 二级页面统一页头:返回按钮、左对齐标题、可选副标题与右侧操作。
class AppSubpageHeader extends StatelessWidget {
const AppSubpageHeader({
super.key,
required this.title,
required this.backKey,
this.subtitle,
this.actions,
this.onBack,
this.dark = false,
});
final String title;
final Key backKey;
final String? subtitle;
final Widget? actions;
final VoidCallback? onBack;
final bool dark;
@override
Widget build(BuildContext context) {
final foreground = dark ? Colors.white : AppColors.onSurface;
final secondary = dark ? Colors.white70 : AppColors.muted;
return SizedBox(
key: const Key('subpage-header'),
height: subtitle == null ? _height : _heightWithSubtitle,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: _horizontal),
child: Row(
children: [
AppSubpageBackButton(backKey: backKey, dark: dark, onBack: onBack),
const SizedBox(width: _backGap),
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
title,
key: const Key('subpage-title'),
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(
color: foreground,
fontSize: _titleFontSize,
fontWeight: FontWeight.w800,
),
),
if (subtitle != null) ...[
const SizedBox(height: 2),
Text(
subtitle!,
key: const Key('subpage-subtitle'),
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(
color: secondary,
fontSize: _subtitleFontSize,
fontWeight: FontWeight.w500,
),
),
],
],
),
),
if (actions != null) ...[
const SizedBox(width: _actionGap),
actions!,
],
],
),
),
);
}
}