feat(app): 集成文字输入到编辑器 — TextInputOverlay + 工具栏选项行

This commit is contained in:
iven
2026-06-01 21:27:15 +08:00
parent d392515f4a
commit fef2d629e5
2 changed files with 92 additions and 4 deletions

View File

@@ -22,6 +22,7 @@ import '../widgets/handwriting_canvas.dart';
import '../widgets/stroke_model.dart';
import '../widgets/draggable_element.dart';
import '../widgets/editor_toolbar.dart';
import '../widgets/text_input_overlay.dart';
/// 手账编辑器页面
class EditorPage extends StatelessWidget {
@@ -171,7 +172,7 @@ class _EditorView extends StatelessWidget {
Expanded(
child: BlocBuilder<EditorBloc, EditorState>(
builder: (context, state) {
return _EditorStack(state: state);
return _EditorStack(state: state, journalId: journalId);
},
),
),
@@ -258,8 +259,9 @@ class _EditorView extends StatelessWidget {
/// Layer 3 (顶层): 由 _EditorView 中的工具栏处理
class _EditorStack extends StatelessWidget {
final EditorState state;
final String? journalId;
const _EditorStack({required this.state});
const _EditorStack({required this.state, this.journalId});
@override
Widget build(BuildContext context) {
@@ -285,6 +287,30 @@ class _EditorStack extends StatelessWidget {
if (state.elements.isNotEmpty)
_buildElementLayer(context),
// 文字输入覆盖层(文字工具激活时显示)
if (state.activeTool == EditorTool.text)
TextInputOverlay(
onConfirmed: (text, fontSize, fontColor) {
final center = Offset(
MediaQuery.of(context).size.width / 2 - 80,
MediaQuery.of(context).size.height / 3,
);
context.read<EditorBloc>().add(ElementAdded(
JournalElement.createText(
journalId: journalId ?? '',
text: text,
position: center,
fontSize: fontSize,
fontColor: fontColor,
),
));
context.read<EditorBloc>().add(ToolChanged(EditorTool.select));
},
onCancelled: () {
context.read<EditorBloc>().add(ToolChanged(EditorTool.select));
},
),
// 空状态提示
if (state.strokes.isEmpty && state.elements.isEmpty)
_buildEmptyHint(context),

View File

@@ -129,10 +129,72 @@ class EditorToolbar extends StatelessWidget {
static const _widths = [1.5, 3.0, 5.0, 8.0, 12.0];
Widget _buildOptionsRow(BuildContext context, ColorScheme colorScheme) {
if (!state.isDrawingMode) {
return const SizedBox(height: 44, child: Center(child: Text('选择元素或添加内容')));
// 画笔模式:颜色 + 粗细
if (state.isDrawingMode) {
return _buildBrushOptions(context, colorScheme);
}
// 文字工具提示
if (state.activeTool == EditorTool.text) {
return const SizedBox(
height: 44,
child: Center(
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(Icons.text_fields, size: 16),
SizedBox(width: 8),
Text('点击画布输入文字', style: TextStyle(fontSize: 13)),
],
),
),
);
}
// 贴纸工具提示
if (state.activeTool == EditorTool.sticker) {
return const SizedBox(
height: 44,
child: Center(
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(Icons.emoji_emotions_outlined, size: 16),
SizedBox(width: 8),
Text('选择一个贴纸放到日记上', style: TextStyle(fontSize: 13)),
],
),
),
);
}
// 图片工具提示
if (state.activeTool == EditorTool.image) {
return const SizedBox(
height: 44,
child: Center(
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(Icons.add_photo_alternate_outlined, size: 16),
SizedBox(width: 8),
Text('选择照片添加到日记', style: TextStyle(fontSize: 13)),
],
),
),
);
}
// 选择工具
return const SizedBox(
height: 44,
child: Center(child: Text('选择元素或添加内容')),
);
}
/// 画笔模式选项 — 颜色 + 粗细
Widget _buildBrushOptions(BuildContext context, ColorScheme colorScheme) {
return SizedBox(
height: 44,
child: Row(