- 创建可复用的AppHeader组件,集成搜索栏和导入按钮 - 实现SafeArea系统UI避让,解决状态栏重叠问题 - 优化代码注释,采用简洁专业的文档风格 - 完善Flutter布局系统学习文档,涵盖Container、Row、InkWell等组件 - 更新项目状态和开发进度文档 技术要点: - Material Design主题系统集成 - 条件渲染和组件参数化设计 - InkWell水波纹点击效果 - Flutter代码质量优化(零警告) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
157 lines
4.5 KiB
Dart
157 lines
4.5 KiB
Dart
import 'package:flutter/material.dart';
|
||
|
||
/// 应用顶部导航组件
|
||
///
|
||
/// 可复用的顶部导航栏组件,集成在搜索栏内的导入按钮。
|
||
/// 提供统一的搜索和文件导入功能,支持主题自适应。
|
||
class AppHeader extends StatelessWidget {
|
||
/// 标题文本(可选),某些页面可以显示标题而非搜索栏
|
||
final String? title;
|
||
|
||
/// 搜索按钮点击回调函数
|
||
final VoidCallback? onSearchPressed;
|
||
|
||
/// 导入按钮点击回调函数
|
||
final VoidCallback? onImportPressed;
|
||
|
||
/// 是否显示搜索栏(默认值为true)
|
||
final bool showSearchBar;
|
||
|
||
/// 搜索栏占位符文本
|
||
final String searchHint;
|
||
|
||
const AppHeader({
|
||
super.key,
|
||
this.title,
|
||
this.onSearchPressed,
|
||
this.onImportPressed,
|
||
this.showSearchBar = true,
|
||
this.searchHint = '搜索书名或内容...',
|
||
});
|
||
|
||
/// 构建组件的UI结构
|
||
@override
|
||
Widget build(BuildContext context) {
|
||
return Container(
|
||
height: 60,
|
||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
||
decoration: BoxDecoration(
|
||
color: Theme.of(context).colorScheme.surface,
|
||
border: Border(
|
||
bottom: BorderSide(
|
||
color: Theme.of(context).colorScheme.outline.withOpacity(0.2),
|
||
width: 1,
|
||
),
|
||
),
|
||
),
|
||
child: Row(
|
||
children: [
|
||
// 标题区域(条件渲染)
|
||
if (title != null) ...[
|
||
Text(
|
||
title!,
|
||
style: Theme.of(context).textTheme.headlineSmall?.copyWith(
|
||
fontWeight: FontWeight.w600,
|
||
),
|
||
),
|
||
const SizedBox(width: 16),
|
||
],
|
||
|
||
// 搜索栏区域(占据剩余空间)
|
||
if (showSearchBar) ...[
|
||
Expanded(
|
||
child: _buildSearchBar(context),
|
||
),
|
||
]
|
||
],
|
||
),
|
||
);
|
||
}
|
||
|
||
/// 构建搜索栏组件,包含搜索图标、占位符文本和导入按钮
|
||
Widget _buildSearchBar(BuildContext context) {
|
||
return Container(
|
||
height: 44,
|
||
decoration: BoxDecoration(
|
||
color: Theme.of(context).colorScheme.surfaceVariant,
|
||
borderRadius: BorderRadius.circular(22),
|
||
border: Border.all(
|
||
color: Theme.of(context).colorScheme.outline.withOpacity(0.3),
|
||
),
|
||
),
|
||
child: Material(
|
||
color: Colors.transparent,
|
||
child: InkWell(
|
||
borderRadius: BorderRadius.circular(22),
|
||
onTap: onSearchPressed,
|
||
child: Padding(
|
||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||
child: Row(
|
||
children: [
|
||
Icon(
|
||
Icons.search,
|
||
size: 24,
|
||
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
||
),
|
||
const SizedBox(width: 8),
|
||
Expanded(
|
||
child: Text(
|
||
searchHint,
|
||
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
|
||
color: Theme.of(context)
|
||
.colorScheme
|
||
.onSurfaceVariant
|
||
.withOpacity(0.6),
|
||
),
|
||
),
|
||
),
|
||
const SizedBox(width: 8),
|
||
_buildImportButton(context),
|
||
],
|
||
),
|
||
),
|
||
),
|
||
),
|
||
);
|
||
}
|
||
|
||
/// 构建导入按钮组件
|
||
Widget _buildImportButton(BuildContext context) {
|
||
return Container(
|
||
width: 40,
|
||
height: 32,
|
||
decoration: BoxDecoration(
|
||
color: Theme.of(context).colorScheme.primaryContainer,
|
||
borderRadius: BorderRadius.circular(16),
|
||
),
|
||
child: Material(
|
||
color: Colors.transparent,
|
||
child: InkWell(
|
||
borderRadius: BorderRadius.circular(16),
|
||
onTap: onImportPressed,
|
||
child: Padding(
|
||
padding: const EdgeInsets.symmetric(horizontal: 12),
|
||
child: Row(
|
||
mainAxisSize: MainAxisSize.min,
|
||
children: [
|
||
Icon(
|
||
Icons.add,
|
||
size: 18,
|
||
color: Theme.of(context).colorScheme.onPrimaryContainer,
|
||
),
|
||
const SizedBox(width: 4),
|
||
Text(
|
||
'导入',
|
||
style: Theme.of(context).textTheme.bodySmall?.copyWith(
|
||
color: Theme.of(context).colorScheme.onPrimaryContainer,
|
||
),
|
||
),
|
||
],
|
||
),
|
||
),
|
||
),
|
||
),
|
||
);
|
||
}
|
||
}
|