You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何避免Stack中Matrix4 Transform可拖拽组件新增子部件时位置重置

问题根源
  1. 拖拽状态没有持久化存储:你将控制位置缩放的Matrix4存在Drag组件内部的局部ValueNotifier中,每次点击新增按钮触发DummyProvider的notifyListeners后,上层MyApp组件重绘,所有Drag组件都会被重建,内部的ValueNotifier会重置为单位矩阵,自然就回到了屏幕初始位置。
  2. 状态没有和数据绑定:你在DraggableText类中已经预留了position字段用于存储位置变换,但实际开发中没有用到,既没有在初始化Drag组件时读取这个字段的取值,也没有在拖拽过程中将最新的变换矩阵同步到这个字段中。
  3. 列表子组件缺少唯一标识:Stack的子组件列表动态更新时,没有给每个Drag组件绑定唯一Key,会导致Flutter框架复用组件时出现状态错位。
修复步骤

1. 扩展DummyProvider增加更新位置的方法

class DummyProvider extends ChangeNotifier {
  List<DraggableText> list = [];
  String currentText = '';

  void addToList(DraggableText text) {
    list.add(text);
    notifyListeners();
  }

  // 新增更新指定拖拽组件位置的方法
  void updatePosition(String id, Matrix4 newPosition) {
    final index = list.indexWhere((element) => element.id == id);
    if (index != -1) {
      list[index].position = newPosition;
      // 如果不需要拖拽时实时触发其他组件更新,可以去掉这里的notifyListeners,降低重绘开销
      // notifyListeners();
    }
  }
}

2. 改造Drag组件,绑定数据状态

// 组件参数增加对应DraggableText实例和provider实例
class Drag extends StatelessWidget {
  final DraggableText draggableText;
  final DummyProvider provider;
  const Drag({super.key, required this.draggableText, required this.provider});

  @override
  Widget build(BuildContext context) {
    // 初始化时读取已存储的位置,不再默认用单位矩阵
    final ValueNotifier<Matrix4> notifier = ValueNotifier(draggableText.position);
    return MatrixGestureDetector(
      onMatrixUpdate: (m, tm, sm, rm) {
        notifier.value = m;
        // 拖拽时同步更新provider中存储的位置
        provider.updatePosition(draggableText.id, m);
      },
      child: AnimatedBuilder(
        animation: notifier,
        builder: (ctx, child) {
          return Transform(
            transform: notifier.value,
            child: Center(
              child: Stack(
                children: <Widget>[
                  Transform.scale(
                    scale: 1,
                    origin: const Offset(0.0, 0.0),
                    child: GestureDetector(
                        child: Container(
                            color: Colors.blueAccent,
                            child: Text(draggableText.text, style: const TextStyle(fontSize: 40))
                        )
                    ),
                  ),
                ],
              ),
            ),
          );
        },
      ),
    );
  }
}

3. 修改MyApp中Stack子组件生成逻辑,增加唯一Key

child: Stack(
  children: List.generate(
    dummyProvider.list.length,
    (index) => Drag(
      // 绑定唯一Key避免组件复用错位
      key: Key(dummyProvider.list[index].id),
      draggableText: dummyProvider.list[index],
      provider: dummyProvider,
    )
  ),
),

内容的提问来源于stack exchange,提问作者lucifer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 21:45:09