fix(app): 修复 4 个 Flutter 交互问题
Some checks failed
Main Merge / backend (push) Has been cancelled
Main Merge / frontend (push) Has been cancelled

1. 首页数据不刷新 — JournalRepository 添加 onJournalChanged
   Stream 变更通知,HomeBloc 订阅后自动刷新
2. 画笔再次点击不弹出面板 — 添加 ToolReactivated 事件,
   工具栏检测已激活工具时发出重新激活信号
3. 钢笔铅笔效果一样 — 调整 perfect_freehand 参数
   (pen: size 10/smooth 0.65, pencil: size 3/smooth 0.35)
4. 橡皮擦不生效 — ActiveStrokePainter 橡皮擦模式绘制
   半透明灰色反馈,笔画完成后 setState 触发 Layer 1 重绘
5. 贴纸文字无法缩放 — DraggableElement 用 Scale 手势
   替换 Pan 手势,支持双指缩放和旋转
This commit is contained in:
iven
2026-06-04 00:05:22 +08:00
parent 988ee7335a
commit 9fce34f4ef
14 changed files with 164 additions and 15 deletions

View File

@@ -53,6 +53,16 @@ class ActiveStrokePainter extends CustomPainter {
final path = buildStrokePath(outlinePoints);
// 橡皮擦实时反馈:绘制半透明灰色,让用户看到擦除范围
// 实际擦除在笔画完成后的合成图中通过 BlendMode.dstOut 执行
if (brushType == BrushType.eraser) {
canvas.drawPath(path, Paint()
..color = const Color(0x40808080) // 25% 灰色
..style = PaintingStyle.fill
..isAntiAlias = true);
return;
}
// 构造临时 Stroke 用于获取 Paint
final stroke = Stroke(
id: '__active__',

View File

@@ -19,6 +19,8 @@ class DraggableElement extends StatefulWidget {
final bool isSelected;
final ValueChanged<String> onTap;
final void Function(String id, double x, double y) onMoved;
final void Function(String id, double w, double h)? onResized;
final void Function(String id, double rotation)? onRotated;
final ValueChanged<String> onDeleted;
const DraggableElement({
@@ -27,6 +29,8 @@ class DraggableElement extends StatefulWidget {
this.isSelected = false,
required this.onTap,
required this.onMoved,
this.onResized,
this.onRotated,
required this.onDeleted,
});
@@ -41,6 +45,11 @@ class _DraggableElementState extends State<DraggableElement> {
late double _height;
late double _rotation;
// Scale 手势状态
double _baseWidth = 0;
double _baseHeight = 0;
double _baseRotation = 0;
@override
void initState() {
super.initState();
@@ -76,15 +85,35 @@ class _DraggableElementState extends State<DraggableElement> {
child: Transform.rotate(
angle: _rotation,
child: GestureDetector(
// 拖拽移动
onPanUpdate: (details) {
// 缩放开始 — 记录基准值
onScaleStart: (details) {
_baseWidth = _width;
_baseHeight = _height;
_baseRotation = _rotation;
},
// 缩放更新 — 支持单指拖拽 + 双指缩放/旋转
onScaleUpdate: (details) {
setState(() {
_x += details.delta.dx;
_y += details.delta.dy;
// 拖拽(单指和双指都支持)
_x += details.focalPointDelta.dx;
_y += details.focalPointDelta.dy;
// 双指缩放 + 旋转
if (details.pointerCount >= 2) {
final newW = (_baseWidth * details.scale).clamp(40.0, 400.0);
final newH = (_baseHeight * details.scale).clamp(40.0, 400.0);
_width = newW;
_height = newH;
_rotation = _baseRotation + details.rotation;
}
});
widget.onMoved(widget.element.id, _x, _y);
if (details.pointerCount >= 2) {
widget.onResized?.call(widget.element.id, _width, _height);
widget.onRotated?.call(widget.element.id, _rotation);
}
},
onPanEnd: (_) {
onScaleEnd: (_) {
// 确保最终位置已通知
widget.onMoved(widget.element.id, _x, _y);
},

View File

@@ -68,7 +68,7 @@ class EditorToolbar extends StatelessWidget {
final colorScheme = Theme.of(context).colorScheme;
return GestureDetector(
onTap: () => onEvent(ToolChanged(tool)),
onTap: () => onEvent(isActive ? ToolReactivated(tool) : ToolChanged(tool)),
behavior: HitTestBehavior.opaque,
child: Container(
constraints: const BoxConstraints(minWidth: 36, minHeight: 36),

View File

@@ -235,7 +235,10 @@ class _HandwritingCanvasState extends State<HandwritingCanvas> {
widget.onStrokeCompleted?.call(stroke);
// 光栅化新笔画到缓存(异步,不阻塞 UI
_cache.addStroke(stroke);
// 完成后 setState 确保 Layer 1 (CachedStrokesPainter) 用新合成图重绘
_cache.addStroke(stroke).then((_) {
if (mounted) setState(() {});
});
}
/// 指针取消(如来电打断):丢弃当前笔画。

View File

@@ -39,19 +39,21 @@ class _BrushConfig {
/// 各画笔的渲染参数。
const Map<BrushType, _BrushConfig> _brushConfigs = {
/// 钢笔:中等粗细,强压感变化,模拟笔效果
/// 钢笔:粗壮平滑,模拟签字笔效果
BrushType.pen: _BrushConfig(
size: 8,
thinning: 0.7,
smoothing: 0.5,
size: 10,
thinning: 0.65,
smoothing: 0.65,
streamline: 0.6,
simulatePressure: true,
),
/// 铅笔:细线,轻微压感,高平滑度产生自然线条
/// 铅笔:纤细有质感,保留书写抖动
BrushType.pencil: _BrushConfig(
size: 4,
thinning: 0.3,
smoothing: 0.7,
size: 3,
thinning: 0.4,
smoothing: 0.35,
streamline: 0.3,
simulatePressure: true,
),