// 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!, ], ], ), ), ); } }