snap_wish/lib/pages/add_photo_page.dart
2025-08-30 18:11:40 +08:00

282 lines
7.7 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'package:flutter/material.dart';
/// 添加照片页面 - 照片上传和元数据管理
/// 提供照片选择、分类选择、标签添加等功能
/// 使用StatefulWidget管理复杂的表单状态
class AddPhotoPage extends StatefulWidget {
const AddPhotoPage({super.key});
@override
State<AddPhotoPage> createState() => _AddPhotoPageState();
}
/// 添加照片页面状态管理
/// 技巧使用多个Controller管理不同输入字段
class _AddPhotoPageState extends State<AddPhotoPage> {
// 表单状态管理
String? _selectedCategory;
final TextEditingController _tagsController = TextEditingController();
final List<String> _tags = [];
// TODO: 替换为真实文件夹数据
final List<String> _categories = ['默认分类', '人像', '风景', '建筑'];
@override
void dispose() {
_tagsController.dispose();
super.dispose();
}
/// 选择照片
/// TODO: 集成图片选择器(image_picker)实现真实功能
void _selectPhoto() {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('选择照片功能待实现')),
);
}
/// 添加标签
/// 技巧:自动去除空格和重复标签,保持数据整洁
void _addTag(String text) {
final tag = text.trim();
if (tag.isNotEmpty && !_tags.contains(tag)) {
setState(() {
_tags.add(tag);
});
_tagsController.clear();
}
}
/// 移除标签
void _removeTag(String tag) {
setState(() {
_tags.remove(tag);
});
}
/// 保存照片
/// 技巧:表单验证确保必要字段已填写
void _savePhoto() {
if (_selectedCategory == null) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('请选择文件夹')),
);
return;
}
// TODO: 实现真实保存逻辑
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('照片已保存到 $_selectedCategory')),
);
Navigator.pop(context);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: _buildAppBar(),
body: _buildBody(),
);
}
/// 构建应用栏
/// 技巧使用actions添加保存按钮保持界面简洁
AppBar _buildAppBar() {
return AppBar(
title: const Text('添加照片'),
actions: [
TextButton(
onPressed: _savePhoto,
child: const Text(
'保存',
style: TextStyle(color: Colors.white, fontSize: 16),
),
),
],
);
}
/// 构建页面主体
/// 技巧使用SingleChildScrollView确保键盘弹出时内容可滚动
Widget _buildBody() {
return SingleChildScrollView(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_buildPhotoSelector(),
const SizedBox(height: 24),
_buildCategorySelector(),
const SizedBox(height: 24),
_buildTagsSection(),
],
),
);
}
/// 构建照片选择器
/// 技巧使用GestureDetector实现点击区域提升用户体验
Widget _buildPhotoSelector() {
return GestureDetector(
onTap: _selectPhoto,
child: Container(
height: 200,
decoration: BoxDecoration(
color: const Color(0xFF1A1D1F),
borderRadius: BorderRadius.circular(16),
border: Border.all(color: const Color(0xFF374151)),
),
child: const Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
Icons.add_photo_alternate,
size: 48,
color: Color(0xFF9CA3AF),
),
SizedBox(height: 8),
Text(
'点击选择照片',
style: TextStyle(
color: Color(0xFF9CA3AF),
fontSize: 16,
),
),
],
),
),
),
);
}
/// 构建分类选择器
/// 技巧使用DropdownButtonFormField提供下拉选择体验
Widget _buildCategorySelector() {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'选择文件夹',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
const SizedBox(height: 8),
DropdownButtonFormField<String>(
value: _selectedCategory,
decoration: InputDecoration(
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
),
hintText: '请选择文件夹',
filled: true,
fillColor: const Color(0xFF1A1D1F),
),
dropdownColor: const Color(0xFF1A1D1F),
items: _categories.map((category) {
return DropdownMenuItem(
value: category,
child: Text(category, style: const TextStyle(color: Colors.white)),
);
}).toList(),
onChanged: (value) {
setState(() {
_selectedCategory = value;
});
},
),
],
);
}
/// 构建标签区域
/// 技巧使用Wrap实现标签的流式布局
Widget _buildTagsSection() {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'添加标签',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
const SizedBox(height: 8),
_buildTagInput(),
const SizedBox(height: 12),
_buildTagList(),
],
);
}
/// 构建标签输入框
/// 技巧使用TextField的多种事件处理实现智能标签输入
Widget _buildTagInput() {
return TextField(
controller: _tagsController,
decoration: InputDecoration(
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
),
hintText: '输入标签(支持 #标签 格式)',
filled: true,
fillColor: const Color(0xFF1A1D1F),
suffixIcon: IconButton(
icon: const Icon(Icons.add, color: Color(0xFFFF8A1F)),
onPressed: () => _addTag(_tagsController.text),
),
),
style: const TextStyle(color: Colors.white),
onSubmitted: _addTag,
onChanged: _handleTagInputChange,
);
}
/// 处理标签输入变化
/// 技巧:智能识别#符号,支持多种输入格式
void _handleTagInputChange(String value) {
// 支持空格或回车分隔标签
if (value.endsWith(' ') || value.endsWith('\n')) {
final tag = value.trim();
if (tag.isNotEmpty) {
_addTag(tag.replaceAll('#', ''));
}
}
}
/// 构建标签列表
/// 技巧使用Chip组件实现可删除的标签
Widget _buildTagList() {
if (_tags.isEmpty) {
return const Text(
'暂无标签,可添加多个标签方便搜索',
style: TextStyle(color: Color(0xFF9CA3AF), fontSize: 14),
);
}
return Wrap(
spacing: 8,
runSpacing: 8,
children: _tags.map((tag) => _buildTagChip(tag)).toList(),
);
}
/// 构建单个标签Chip
/// 技巧自定义Chip样式提升视觉体验
Widget _buildTagChip(String tag) {
return Chip(
label: Text(
'#$tag',
style: const TextStyle(color: Colors.white, fontSize: 12),
),
backgroundColor: const Color(0xFF374151),
deleteIcon: const Icon(Icons.close, size: 16, color: Colors.white),
onDeleted: () => _removeTag(tag),
);
}
}