gpt4 book ai didi

Flutter Draggable - 如何将 Draggable 重置为起始位置?

转载 作者:行者123 更新时间:2023-12-04 10:07:35 26 4
gpt4 key购买 nike

更新:

See latest updates at the bottom.



原装

我有 flutter Draggable 和 DragTarget 小部件,它们正在工作,但在放置 DragTarget 后,我​​遇到了一个特定的情况,我想重建 DragTarget 并将 Draggable 移回其原始位置。

当我检查 Flutter 检查器时,它会显示我的小部件,但当我调用我的 Provider 以获取下一组信息时,Draggables 保持在它们的放置位置而不是返回到它们的起始位置。

如图像的最后一帧所示,三个目标帧仍然包含对可拖动小部件的引用,但每次单击红色 IconButton 时,我都会重建 Draggable 和 DragTarget 小部件。

观察
  • 即使我在包裹
    具有消费者的父小部件中的平铺。
  • 消费者正在传递更改后的数据值。
  • 使用 Flutter 在我的小部件树中可以看到 DragTargets
    检查员。
  • 当我到达一个有超过三个 Draggables 的事件时,
    放置的可拖动对象放错了位置,而 Tiles 和 DropTargets 则用于
    其他小部件按预期显示。

  • 期望:

    当我重置我的消费者数据时,我希望使用新数据在原始位置重新绘制 Tiles 和 Targets。

    draggable_behavior

    拖动目标
    @override
    Widget build(BuildContext context) {
    return DragTarget(
    builder:
    (context, List<String> candidateData, List<dynamic> rejectedData) {
    return (isSuccessful) //&& !widget.isPuzzleComplete
    ? Tile(
    title: widget.data,
    )
    : TargetPlaceholder(
    widget: widget,
    );
    },
    onWillAccept: (data) {
    return widget.data == data;
    },
    onAccept: (data) {
    setState(() {
    Provider.of<GameController>(
    context,
    listen: false,
    ).checkPuzzleSolved();
    //activate the animation, may not require setState
    isSuccessful = !widget.isPuzzleComplete;
    });
    },
    onLeave: (data) {
    print('Draggable object left the target area containing data of $data');
    },
    );
    }
    }

    可拖动
    @override
    Widget build(BuildContext context) {
    return Draggable(
    data: widget.title,
    // dragAnchor: DragAnchor.pointer,
    child: isSuccessful ? Container() : TileContent(widget: widget),
    childWhenDragging: Container(),
    feedback: Opacity(
    opacity: 0.7,
    child: TileContent(
    widget: widget,
    ),
    ),
    onDragCompleted: () {
    setState(() {
    Transform(
    transform: Matrix4.translation(_shake()),
    child: TileContent(widget: widget));
    });
    },
    onDragEnd: (details) {
    setState(() {
    isSuccessful = details.wasAccepted;
    });
    },
    );
    }
    }

    父小部件
     Row(
    mainAxisAlignment: MainAxisAlignment.spaceEvenly,
    children: <Widget>[
    for (var item in targetPattern)
    Consumer<GameController>(builder: (context, gc, _) {
    return Target(
    data: item,
    isPuzzleComplete: gc.isPuzzleComplete,
    );
    })
    ],
    ),
    SizedBox(
    height: 36,
    ),
    Row(
    mainAxisAlignment: MainAxisAlignment.spaceEvenly,
    children: <Widget>[
    for (var data in scrambledPattern)
    Consumer<GameController>(builder: (context, gc, _) {
    return Tile(
    title: data,
    isPuzzleComplete: gc.isPuzzleComplete,
    );
    })
    ],
    ),

    更新的行为

    请参阅下面的注释和第二个动画 gif,将代码更改和新行为与上面的原始行为进行比较和对比。

    After adding a UniqueKey to both the Targets and Tiles - The Tiles are incorrectly shown in their original location, The Targets are correctly shown.

    What I am seeking to do is:


  • 将瓷砖显示在目标上的放置位置
  • 在不同的点击事件后,将瓷砖和目标重新绘制在其原始位置。

  • 注 - 将以下代码应用于 Tile 和 Target 小部件。
    key: (gc.isPuzzleComplete == true) ? UniqueKey() : null,

    uniquekey-update

    解决方案

    感谢@LoVe 关于使用 UniqueKey 的提醒以及对 Flutter 团队关于 Keys 的视频的回顾;我能够通过有条件地将 UniqueKey 添加到包含 Tiles 和 Target 的封闭行来解决该问题。

    在这些小部件中的每一个中,我都能够使用 (isSuccessful || widget.isPuzzleComplete) 更新小部件的外观。 .我还能够删除与从 Tile/Target 小部件和 setState 调用中获取 isPuzzleComplete 逻辑相关的消费者逻辑。

    目前,该行为是 100% 正确的。
    //mod to parent row of Tiles
    Row(
    key: widget.isPuzzleComplete ? UniqueKey() : null,
    mainAxisAlignment: MainAxisAlignment.spaceEvenly,
    children: <Widget>[
    for (var data in scrambledPattern)
    Tile( title: data,
    isPuzzleComplete: widget.isPuzzleComplete,
    ),
    ],
    ),

    //mod to draggable Tile
    Draggable(
    key: (widget.isPuzzleComplete == true) ? UniqueKey() : null,
    data: widget.title,
    child: (isSuccessful || widget.isPuzzleComplete)
    ? Container()
    : TileContent(widget: widget),

    //mod to drag target
    return DragTarget(
    key: UniqueKey(),
    builder:
    (context, List<String> candidateData, List<dynamic> rejectedData) {
    return (widget.isPuzzleComplete || isSuccessful)
    ? Tile(
    title: widget.data,

    引用

    Flutter 团队使用 Keys 的视频 ( link )

    最佳答案

    您将不得不使用 key ,如下所示:

    Tile( key:UniqueKey(), title: data, isPuzzleComplete: gc.isPuzzleComplete, ); }

    每当您使用 RowColumnList相同类型的小部件并且您经常更新它们,那么您必须使用 Key s 所以框架知道什么时候该更新相同类型的小部件,什么时候不更新,

    更多关于使用 key 的信息 here

    关于Flutter Draggable - 如何将 Draggable 重置为起始位置?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61495216/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com