// 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 = 40; const double _backGap = 12; const double _titleFontSize = 18; const double _subtitleFontSize = 12; const double _actionGap = 8; const double _iconSize = 22; const double _iconWeight = 600; const double _shadowBlur = 8; /// 二级页面统一圆形操作按钮,返回、分享和更多共用同一尺寸与表面样式。 class AppSubpageCircleButton extends StatelessWidget { const AppSubpageCircleButton({ super.key, required this.buttonKey, required this.tooltip, required this.icon, required this.onPressed, this.dark = false, }); final Key buttonKey; final String tooltip; final IconData icon; final VoidCallback onPressed; final bool dark; @override Widget build(BuildContext context) { return SizedBox( key: buttonKey, width: _backSize, height: _backSize, child: Tooltip( message: tooltip, child: DecoratedBox( key: const Key('subpage-back-shadow'), decoration: BoxDecoration( shape: BoxShape.circle, boxShadow: dark ? const [ BoxShadow( color: AppColors.shadowSoft, blurRadius: _shadowBlur, ), ] : const [], ), child: Material( color: dark ? AppColors.headerScrim : AppColors.transparent, shape: const CircleBorder(), clipBehavior: Clip.antiAlias, child: InkWell( customBorder: const CircleBorder(), onTap: onPressed, child: Center( child: Icon( icon, color: dark ? AppColors.onSurface : AppColors.textPrimary, size: _iconSize, weight: _iconWeight, ), ), ), ), ), ), ); } } /// 二级页面统一返回按钮,普通页透明,沉浸页使用半透明黑底。 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 AppSubpageCircleButton( buttonKey: backKey, tooltip: MaterialLocalizations.of(context).backButtonTooltip, icon: Icons.chevron_left_rounded, dark: dark, onPressed: onBack ?? () => Navigator.of(context).maybePop(), ); } } /// 二级页面统一页头:返回按钮、左对齐标题、可选副标题与右侧操作。 class AppSubpageHeader extends StatelessWidget { const AppSubpageHeader({ super.key, required this.title, required this.backKey, this.subtitle, this.actions, this.onBack, this.dark = false, this.showBack = true, }); final String title; final Key backKey; final String? subtitle; final Widget? actions; final VoidCallback? onBack; final bool dark; final bool showBack; @override Widget build(BuildContext context) { final foreground = AppColors.textPrimary; final secondary = AppColors.textSecondary; return SizedBox( key: const Key('subpage-header'), height: subtitle == null ? _height : _heightWithSubtitle, child: Padding( padding: const EdgeInsets.symmetric(horizontal: _horizontal), child: Row( children: [ if (showBack) ...[ 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!, ], ], ), ), ); } }