feat: 完成顶部导航组件开发和系统UI适配
- 创建可复用的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>
This commit is contained in:
parent
8b5fdaa36d
commit
f62a43823c
380
learning_docs/09_Flutter布局系统详解.md
Normal file
380
learning_docs/09_Flutter布局系统详解.md
Normal file
@ -0,0 +1,380 @@
|
|||||||
|
# Flutter布局系统详解
|
||||||
|
|
||||||
|
## 📚 学习目标
|
||||||
|
|
||||||
|
深入理解Flutter的布局系统,掌握常用的布局组件和设计原则,能够创建响应式的、可复用的UI组件。
|
||||||
|
|
||||||
|
## 🎯 核心概念
|
||||||
|
|
||||||
|
### 1. Widget树结构
|
||||||
|
Flutter应用由一棵Widget树构成,每个Widget都有父Widget和子Widget的关系:
|
||||||
|
|
||||||
|
```
|
||||||
|
MaterialApp (根节点)
|
||||||
|
└── Scaffold (页面骨架)
|
||||||
|
└── AppHeader (自定义组件)
|
||||||
|
├── Container (搜索栏容器)
|
||||||
|
│ ├── Material (Material容器)
|
||||||
|
│ └── InkWell (点击响应)
|
||||||
|
└── Container (按钮容器)
|
||||||
|
├── Material (Material容器)
|
||||||
|
└── InkWell (点击响应)
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📦 基础布局组件详解
|
||||||
|
|
||||||
|
### Container - 万能容器
|
||||||
|
Container是最常用的布局组件,可以设置尺寸、内边距、装饰等。
|
||||||
|
|
||||||
|
```dart
|
||||||
|
Container({
|
||||||
|
height: 60, // 固定高度
|
||||||
|
width: 100, // 固定宽度
|
||||||
|
padding: EdgeInsets.all(16), // 内边距
|
||||||
|
margin: EdgeInsets.symmetric( // 外边距
|
||||||
|
horizontal: 16,
|
||||||
|
vertical: 8,
|
||||||
|
),
|
||||||
|
decoration: BoxDecoration( // 装饰属性
|
||||||
|
color: Colors.blue,
|
||||||
|
borderRadius: BorderRadius.circular(8),
|
||||||
|
border: Border.all(color: Colors.grey),
|
||||||
|
),
|
||||||
|
child: Text('内容'), // 子组件
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
**关键知识点:**
|
||||||
|
- **尺寸控制**:width、height控制容器大小
|
||||||
|
- **间距管理**:padding(内边距)、margin(外边距)
|
||||||
|
- **装饰属性**:通过BoxDecoration设置背景色、边框、圆角等
|
||||||
|
- **布局影响**:Container会尽可能小,除非有父容器约束
|
||||||
|
|
||||||
|
### Row - 水平布局
|
||||||
|
Row将其子组件沿水平轴排列。
|
||||||
|
|
||||||
|
```dart
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Text('左侧'), // 固定宽度
|
||||||
|
Expanded( // 占据剩余空间
|
||||||
|
child: Text('中间'),
|
||||||
|
),
|
||||||
|
Container(width: 50), // 固定宽度
|
||||||
|
Text('右侧'), // 固定宽度
|
||||||
|
],
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
**关键知识点:**
|
||||||
|
- **Expanded**:占据剩余可用空间
|
||||||
|
- **Flexible**:按比例分配空间
|
||||||
|
- **MainAxisAlignment**:主轴(水平)对齐方式
|
||||||
|
- **CrossAxisAlignment**:交叉轴(垂直)对齐方式
|
||||||
|
|
||||||
|
### Column - 垂直布局
|
||||||
|
Column将其子组件沿垂直轴排列,与Row功能相同但方向相反。
|
||||||
|
|
||||||
|
```dart
|
||||||
|
Column(
|
||||||
|
children: [
|
||||||
|
Text('顶部'), // 固定高度
|
||||||
|
Expanded( // 占据剩余垂直空间
|
||||||
|
child: Text('中间内容'),
|
||||||
|
),
|
||||||
|
Container(height: 50), // 固定高度
|
||||||
|
Text('底部'), // 固定高度
|
||||||
|
],
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
### SizedBox - 空白间距
|
||||||
|
用于创建固定大小的空白区域,常用于组件间距。
|
||||||
|
|
||||||
|
```dart
|
||||||
|
SizedBox(width: 16), // 水平间距
|
||||||
|
SizedBox(height: 8), // 垂直间距
|
||||||
|
SizedBox.square(20), // 正方形空白
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🎨 Material Design组件
|
||||||
|
|
||||||
|
### Material - Material容器
|
||||||
|
提供Material Design的基础功能,如墨水纹效果、颜色系统支持。
|
||||||
|
|
||||||
|
```dart
|
||||||
|
Material(
|
||||||
|
color: Colors.blue, // 背景色
|
||||||
|
child: InkWell( // 点击响应
|
||||||
|
onTap: () {},
|
||||||
|
child: Text('按钮'),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
### InkWell - 点击响应
|
||||||
|
提供水波纹点击效果,是Material Design的推荐交互组件。
|
||||||
|
|
||||||
|
```dart
|
||||||
|
InkWell(
|
||||||
|
onTap: () { // 点击事件
|
||||||
|
print('被点击了');
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
width: 100,
|
||||||
|
height: 50,
|
||||||
|
color: Colors.red,
|
||||||
|
child: Text('可点击区域'),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Text - 文本显示
|
||||||
|
用于显示文本,支持丰富的样式定制。
|
||||||
|
|
||||||
|
```dart
|
||||||
|
Text(
|
||||||
|
'Hello World',
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 24,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
color: Colors.black,
|
||||||
|
decoration: TextDecoration.underline,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🎯 AppHeader组件布局分析
|
||||||
|
|
||||||
|
### 整体布局结构
|
||||||
|
|
||||||
|
```dart
|
||||||
|
return Scaffold(
|
||||||
|
body: Column(
|
||||||
|
children: [
|
||||||
|
// 1. 固定高度的顶部导航
|
||||||
|
AppHeader(...),
|
||||||
|
|
||||||
|
// 2. 占据剩余空间的内容区域
|
||||||
|
Expanded(
|
||||||
|
child: 页面内容,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
### AppHeader内部布局
|
||||||
|
|
||||||
|
```dart
|
||||||
|
return Container(
|
||||||
|
height: 60, // 固定高度
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
// 1. 可选标题(条件渲染)
|
||||||
|
if (title != null) ...[
|
||||||
|
Text(title),
|
||||||
|
SizedBox(width: 16),
|
||||||
|
],
|
||||||
|
|
||||||
|
// 2. 搜索栏(占据主要空间)
|
||||||
|
if (showSearchBar) ...[
|
||||||
|
Expanded(child: 搜索栏),
|
||||||
|
SizedBox(width: 12),
|
||||||
|
],
|
||||||
|
|
||||||
|
// 3. 导入按钮(固定大小)
|
||||||
|
导入按钮,
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
**布局设计要点:**
|
||||||
|
1. **Row水平布局**:标题、搜索栏、按钮水平排列
|
||||||
|
2. **Expanded搜索栏**:使用Expanded让搜索栏自适应宽度
|
||||||
|
3. **条件渲染**:通过`if (condition) ...[...]`控制组件显示
|
||||||
|
4. **固定间距**:使用SizedBox创建统一的组件间距
|
||||||
|
|
||||||
|
## 🎨 装饰与样式
|
||||||
|
|
||||||
|
### BoxDecoration详解
|
||||||
|
BoxDecoration提供了丰富的装饰选项:
|
||||||
|
|
||||||
|
```dart
|
||||||
|
BoxDecoration(
|
||||||
|
// 背景色
|
||||||
|
color: Colors.white,
|
||||||
|
|
||||||
|
// 渐变色
|
||||||
|
gradient: LinearGradient(
|
||||||
|
colors: [Colors.blue, Colors.purple],
|
||||||
|
begin: Alignment.topLeft,
|
||||||
|
end: Alignment.bottomRight,
|
||||||
|
),
|
||||||
|
|
||||||
|
// 边框
|
||||||
|
border: Border(
|
||||||
|
top: BorderSide(color: Colors.grey),
|
||||||
|
bottom: BorderSide(color: Colors.grey),
|
||||||
|
),
|
||||||
|
|
||||||
|
// 圆角
|
||||||
|
borderRadius: BorderRadius.circular(12),
|
||||||
|
|
||||||
|
// 阴影
|
||||||
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
color: Colors.black.withOpacity(0.1),
|
||||||
|
blurRadius: 8,
|
||||||
|
offset: Offset(0, 2),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
|
||||||
|
// 背景图片
|
||||||
|
image: DecorationImage(
|
||||||
|
image: AssetImage('assets/image.png'),
|
||||||
|
fit: BoxFit.cover,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Theme.of(context) 主题系统
|
||||||
|
|
||||||
|
Flutter提供了完整的主题系统,支持亮色和暗色模式:
|
||||||
|
|
||||||
|
```dart
|
||||||
|
// 获取当前主题配置
|
||||||
|
ThemeData theme = Theme.of(context);
|
||||||
|
|
||||||
|
// 使用主题颜色
|
||||||
|
Color primaryColor = theme.colorScheme.primary;
|
||||||
|
Color surfaceColor = theme.colorScheme.surface;
|
||||||
|
|
||||||
|
// 使用文本样式
|
||||||
|
TextStyle headlineStyle = theme.textTheme.headlineLarge;
|
||||||
|
TextStyle bodyStyle = theme.textTheme.bodyLarge;
|
||||||
|
|
||||||
|
// 获取主题图标配色
|
||||||
|
Color iconColor = theme.iconTheme.color;
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🎓 响应式设计原则
|
||||||
|
|
||||||
|
### 尺寸适配
|
||||||
|
```dart
|
||||||
|
// 使用MediaQuery获取屏幕信息
|
||||||
|
double screenWidth = MediaQuery.of(context).size.width;
|
||||||
|
|
||||||
|
// 根据屏幕尺寸调整布局
|
||||||
|
double padding = screenWidth > 600 ? 24.0 : 16.0;
|
||||||
|
|
||||||
|
// 使用LayoutBuilder根据父容器约束调整
|
||||||
|
LayoutBuilder(
|
||||||
|
builder: (context, constraints) {
|
||||||
|
if (constraints.maxWidth > 600) {
|
||||||
|
return Row(...); // 平板布局
|
||||||
|
} else {
|
||||||
|
return Column(...); // 手机布局
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Flex布局
|
||||||
|
```dart
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Flexible(
|
||||||
|
flex: 2, // 占据2份空间
|
||||||
|
child: Container(color: Colors.red),
|
||||||
|
),
|
||||||
|
Flexible(
|
||||||
|
flex: 1, // 占据1份空间
|
||||||
|
child: Container(color: Colors.blue),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
## 💡 最佳实践
|
||||||
|
|
||||||
|
### 1. 组件化设计
|
||||||
|
- 将重复的UI抽取为可复用组件
|
||||||
|
- 通过参数配置组件的行为
|
||||||
|
- 保持组件的单一职责原则
|
||||||
|
|
||||||
|
### 2. 布局优化
|
||||||
|
- 合理使用Expanded和Flexible
|
||||||
|
- 避免不必要的嵌套
|
||||||
|
- 使用约束而不是硬编码尺寸
|
||||||
|
|
||||||
|
### 3. 主题适配
|
||||||
|
- 始终使用Theme.of(context)获取主题配置
|
||||||
|
- 避免硬编码颜色值
|
||||||
|
- 支持亮色/暗色模式自动切换
|
||||||
|
|
||||||
|
### 4. 交互设计
|
||||||
|
- 使用InkWell提供Material Design交互
|
||||||
|
- 设置合适的最小触摸目标(44x44dp)
|
||||||
|
- 提供视觉反馈(颜色变化、动画等)
|
||||||
|
|
||||||
|
## 🔧 常见问题解决
|
||||||
|
|
||||||
|
### 问题1:Container大小不符合预期
|
||||||
|
```dart
|
||||||
|
// 错误:Container没有约束时会尽可能小
|
||||||
|
Container(child: Text('文本')) // 可能显示不完整
|
||||||
|
|
||||||
|
// 正确:给Container设置明确的约束或让父容器约束
|
||||||
|
Container(
|
||||||
|
width: 200,
|
||||||
|
height: 100,
|
||||||
|
child: Text('文本'),
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 问题2:Row/Column中的布局异常
|
||||||
|
```dart
|
||||||
|
// 错误:Row中的子组件过大导致溢出
|
||||||
|
Row(children: [Container(width: 500)]) // 可能溢出屏幕
|
||||||
|
|
||||||
|
// 正确:使用Expanded或Flexible自适应空间
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Expanded(child: Container()), // 自适应宽度
|
||||||
|
Container(width: 100), // 固定宽度
|
||||||
|
],
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 问题3:文本样式不生效
|
||||||
|
```dart
|
||||||
|
// 错误:在父Widget上设置文本样式不会被子组件继承
|
||||||
|
Container(
|
||||||
|
child: Text('文本'),
|
||||||
|
style: TextStyle(fontSize: 16), // ❌ 这不会生效
|
||||||
|
)
|
||||||
|
|
||||||
|
// 正确:直接在Text组件上设置样式
|
||||||
|
Container(
|
||||||
|
child: Text(
|
||||||
|
'文本',
|
||||||
|
style: TextStyle(fontSize: 16), // ✅ 这会生效
|
||||||
|
),
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**学习要点总结:**
|
||||||
|
1. **理解Widget树结构**:掌握父子组件关系和约束传递
|
||||||
|
2. **掌握基础布局组件**:Container、Row、Column、SizedBox
|
||||||
|
3. **学会响应式设计**:使用Expanded、Flexible、MediaQuery
|
||||||
|
4. **遵循Material Design**:使用Material、InkWell、Theme
|
||||||
|
5. **组件化思维**:创建可复用的UI组件
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*文档创建时间:2025年1月*
|
||||||
|
*Flutter版本:>=3.0.0*
|
||||||
156
lib/components/app_header.dart
Normal file
156
lib/components/app_header.dart
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
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,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,5 +1,5 @@
|
|||||||
import "package:flutter/material.dart";
|
import 'package:flutter/material.dart';
|
||||||
import "package:hive_flutter/hive_flutter.dart";
|
// import 'package:hive_flutter/hive_flutter.dart';
|
||||||
|
|
||||||
// 数据层服务
|
// 数据层服务
|
||||||
import 'services/database_service.dart';
|
import 'services/database_service.dart';
|
||||||
@ -247,7 +247,7 @@ class MyApp extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return MaterialApp(
|
return MaterialApp(
|
||||||
title: "Readful",
|
title: 'Readful',
|
||||||
theme: ThemeData(primarySwatch: Colors.blue),
|
theme: ThemeData(primarySwatch: Colors.blue),
|
||||||
home: Scaffold(
|
home: Scaffold(
|
||||||
appBar: AppBar(title: const Text('readful 电子书阅读器')),
|
appBar: AppBar(title: const Text('readful 电子书阅读器')),
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import '../components/app_header.dart';
|
||||||
|
|
||||||
/// 首页页面
|
/// 首页页面
|
||||||
///
|
///
|
||||||
@ -14,12 +15,34 @@ class HomePage extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
body: Center(
|
body: Column(
|
||||||
|
children: [
|
||||||
|
// 顶部导航组件
|
||||||
|
SafeArea(
|
||||||
|
bottom: false, // 只处理顶部安全区域
|
||||||
|
child: AppHeader(
|
||||||
|
onSearchPressed: () {
|
||||||
|
// TODO: 实现搜索功能
|
||||||
|
print('搜索按钮被点击');
|
||||||
|
},
|
||||||
|
onImportPressed: () {
|
||||||
|
// TODO: 实现导入功能
|
||||||
|
print('导入按钮被点击');
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
// 页面内容区域
|
||||||
|
Expanded(
|
||||||
|
child: Center(
|
||||||
child: Text(
|
child: Text(
|
||||||
'首页',
|
'首页内容区域',
|
||||||
style: Theme.of(context).textTheme.headlineMedium,
|
style: Theme.of(context).textTheme.headlineMedium,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,13 +1,47 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import '../components/app_header.dart';
|
||||||
|
|
||||||
|
/// 书库页面
|
||||||
|
///
|
||||||
|
/// 用户管理和浏览所有导入的电子书
|
||||||
|
/// 功能规划:
|
||||||
|
/// - 书籍列表展示
|
||||||
|
/// - 分类筛选功能
|
||||||
|
/// - 排序选项
|
||||||
|
/// - 批量操作功能
|
||||||
class LibraryPage extends StatelessWidget {
|
class LibraryPage extends StatelessWidget {
|
||||||
const LibraryPage({Key? key}) : super(key: key);
|
const LibraryPage({Key? key}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
body: Center(
|
body: Column(
|
||||||
child: Text('书库', style: Theme.of(context).textTheme.headlineMedium),
|
children: [
|
||||||
|
// 顶部导航组件
|
||||||
|
SafeArea(
|
||||||
|
bottom: false,
|
||||||
|
child: AppHeader(
|
||||||
|
title: '书库',
|
||||||
|
showSearchBar: true,
|
||||||
|
onSearchPressed: () {
|
||||||
|
print('书库搜索按钮被点击');
|
||||||
|
},
|
||||||
|
onImportPressed: () {
|
||||||
|
print('书库导入按钮被点击');
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
// 书籍列表内容区域
|
||||||
|
Expanded(
|
||||||
|
child: Center(
|
||||||
|
child: Text(
|
||||||
|
'书库列表区域',
|
||||||
|
style: Theme.of(context).textTheme.headlineMedium,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user