- 添加导航条目和分类数据模型 - 实现导航卡片网格展示 - 支持点击卡片打开链接 - 添加主题样式(渐变色、卡片阴影) - 区分系统默认和自定义条目 - 添加分类统计信息"
117 lines
3.4 KiB
Dart
117 lines
3.4 KiB
Dart
import 'package:flutter/material.dart';
|
||
|
||
import '../../../../core/constants/app_sizes.dart';
|
||
import '../../../../core/theme/app_colors.dart';
|
||
import 'link_search_field.dart';
|
||
|
||
/// 顶部控制栏:折叠按钮 + 搜索框。
|
||
///
|
||
/// 对应 `index3.html` 的 `.top-bar`:整体宽 750px 并且**水平居中**
|
||
/// (`margin: 0 auto 36px auto`),下方与第一组卡片留 36px。
|
||
class TopBar extends StatelessWidget {
|
||
const TopBar({
|
||
super.key,
|
||
required this.searchController,
|
||
required this.searchHint,
|
||
required this.sidebarCollapsed,
|
||
required this.onToggleSidebar,
|
||
});
|
||
|
||
/// 搜索框控制器。
|
||
final TextEditingController searchController;
|
||
|
||
/// 搜索框占位文案。
|
||
final String searchHint;
|
||
|
||
/// 侧栏当前是否折叠,用于按钮的提示文案。
|
||
final bool sidebarCollapsed;
|
||
|
||
/// 折叠 / 展开侧栏。
|
||
final VoidCallback onToggleSidebar;
|
||
|
||
@override
|
||
Widget build(BuildContext context) {
|
||
return Padding(
|
||
padding: const EdgeInsets.only(bottom: AppSizes.topBarMarginBottom),
|
||
child: Center(
|
||
child: ConstrainedBox(
|
||
constraints: const BoxConstraints(
|
||
maxWidth: AppSizes.topBarMaxWidth,
|
||
),
|
||
child: Row(
|
||
children: <Widget>[
|
||
_ToggleButton(
|
||
collapsed: sidebarCollapsed,
|
||
onTap: onToggleSidebar,
|
||
),
|
||
const SizedBox(width: AppSizes.topBarGap),
|
||
Expanded(
|
||
child: LinkSearchField(
|
||
controller: searchController,
|
||
hintText: searchHint,
|
||
),
|
||
),
|
||
],
|
||
),
|
||
),
|
||
),
|
||
);
|
||
}
|
||
}
|
||
|
||
/// 折叠按钮(`.toggle-btn`)。
|
||
class _ToggleButton extends StatefulWidget {
|
||
const _ToggleButton({required this.collapsed, required this.onTap});
|
||
|
||
final bool collapsed;
|
||
final VoidCallback onTap;
|
||
|
||
@override
|
||
State<_ToggleButton> createState() => _ToggleButtonState();
|
||
}
|
||
|
||
class _ToggleButtonState extends State<_ToggleButton> {
|
||
bool _hovered = false;
|
||
|
||
@override
|
||
Widget build(BuildContext context) {
|
||
final Color foreground = _hovered
|
||
? AppColors.primary
|
||
: AppColors.textSecondary;
|
||
|
||
return Tooltip(
|
||
// 原型写的是 title="展开/折叠侧边栏",文案固定。
|
||
message: '展开/折叠侧边栏',
|
||
child: MouseRegion(
|
||
cursor: SystemMouseCursors.click,
|
||
onEnter: (_) => setState(() => _hovered = true),
|
||
onExit: (_) => setState(() => _hovered = false),
|
||
child: GestureDetector(
|
||
onTap: widget.onTap,
|
||
child: AnimatedContainer(
|
||
duration: AppSizes.transition,
|
||
// `.toggle-btn { transition: all 0.2s }`。
|
||
curve: Curves.ease,
|
||
width: AppSizes.toggleButtonSize,
|
||
height: AppSizes.toggleButtonSize,
|
||
alignment: Alignment.center,
|
||
decoration: BoxDecoration(
|
||
color: AppColors.surface,
|
||
border: Border.all(
|
||
color: _hovered ? AppColors.primary : AppColors.border,
|
||
),
|
||
borderRadius: BorderRadius.circular(AppSizes.toggleButtonRadius),
|
||
boxShadow: AppColors.cardShadow,
|
||
),
|
||
// 原型这里就是一个 ☰ 字符(font-size: 18px)。
|
||
child: Text(
|
||
'☰',
|
||
style: TextStyle(fontSize: 18, color: foreground),
|
||
),
|
||
),
|
||
),
|
||
),
|
||
);
|
||
}
|
||
}
|