如何访问带有覆盖可拖动的拖动目标



我正在尝试在 Flutter 中创建一个游戏,将物品拖放到目标中。一旦物品掉落在目标上,它就会被重新定位在目标上。

这一直有效,直到下一个项目被放在原始目标上。onAccept 不再触发,因为第一项位于目标的"顶部"。

解决此问题的最佳方法是什么?

我基本上重写了这个问题/答案:在颤振中输入拖动目标时如何更新可拖动的孩子?

部分主:

child: Stack(
              children: <Widget>[
                MyDragTarget(Offset(50, 500), draggableController, 'target 1'),
                MyDragTarget(Offset(250, 500), draggableController, 'target 2'),
                MyDraggable(
                  Offset(50, 100),
                  draggableController,
                  'ball 1',
                ),
                MyDraggable(
                  Offset(150, 100),
                  draggableController,
                  'ball 2',
                ),
                MyDraggable(
                  Offset(250, 100),
                  draggableController,
                  'ball 3',
                ),
              ],
            ),

可拖动

class MyDraggable<T> extends StatefulWidget {
  final Offset initPos;
  final MyDraggableController<T> controller;
  final T data;
  MyDraggable(this.initPos, this.controller, this.data, {Key key})
      : super(key: key);
  @override
  _MyDraggableState createState() =>
      _MyDraggableState<T>(this.initPos, this.controller, this.data);
}
class _MyDraggableState<T> extends State<MyDraggable> {
  MyDraggableController<T> controller;
  T data;
  Offset position = Offset(0.0, 0.0);
  _MyDraggableState(this.position, this.controller, this.data);

  @override
  void initState() {
    this.controller.subscribeToOnTargetCallback(onTargetCallbackHandler);
    super.initState();
    position = widget.initPos;
  }
  void onTargetCallbackHandler(T data, Offset targetPosition) {
    debugPrint("dropped inside target: " + data.toString());
    if (this.data == data) {
      debugPrint("DRAGGABLE is ACCEPTED " +
          this.data.toString() +
          " " +
          this.isOnTarget.toString());
      setState(() {
        this.position = targetPosition;
      });
    } else {
      debugPrint("DRAGGABLE is NOT ACCEPTED " +
          this.data.toString() +
          " " +
          this.isOnTarget.toString());
      if (this.position == targetPosition) {
        debugPrint(this.data.toString() + " is occupying this spot!");
      }
      setState(() {});
    }
  }
  @override
  void dispose() {
    this.controller.unSubscribeFromOnTargetCallback(onTargetCallbackHandler);
    super.dispose();
  }
  @override
  Widget build(BuildContext context) {
    return Positioned(
        left: position.dx,
        top: position.dy,
        child: Draggable<T>(
          data: this.data,
          child: CirkleWidget(this.data,0.5),
          feedback: CirkleWidget(this.data,1.2),
          childWhenDragging: new Container(),
          onDraggableCanceled: (v, f) => setState(
                () {
                  this.isOnTarget = false;
                  this.position = widget.initPos;

                },
              ),
        ));
  }
}

拖动目标

class MyDragTarget<T> extends StatefulWidget {
  final Offset inPos;
  final MyDraggableController<T> controller;
  final T data;
  MyDragTarget(this.inPos, this.controller, this.data, {Key key})
      : super(key: key);
  @override
  _MyDragTargetState createState() =>
      _MyDragTargetState(this.inPos, this.controller, this.data);
}
class _MyDragTargetState<T> extends State<MyDragTarget> {
  Offset position = Offset(0.0, 0.0);
  MyDraggableController<T> controller;
  T data;
  T currentBall;


  _MyDragTargetState(this.position, this.controller, this.data);
  @override
  void initState() {
    position = widget.inPos;
    data = widget.data;
    //this.controller.subscribeToOnTargetCallback(onTargetCallbackHandler);
    super.initState();
  }
  @override
  Widget build(BuildContext context) {
    debugPrint(position.toString());
    return Positioned(
      left: position.dx-10,
      top: position.dy-10,
      child: DragTarget<T>(
        builder: (context, list, list2) {
          return Container(
            decoration: BoxDecoration(
                color: Colors.blueGrey,
                borderRadius: BorderRadius.circular(50.0)),
            height: 120,
            width: 120,
            child: Center(
              child: Text(data.toString().toUpperCase()),
            ),
          );
        },
        onWillAccept: (item){
          debugPrint("will accept");
          return true;
        },
        onAccept: (item) {
          debugPrint('TARGET accepted $item');
          //this.draggableController.onTarget(true, item);
          //debugPrint("set currentball from "+ currentBall.toString() + " to" + item.toString());
          //currentBall = item;
          this.controller.onDropped(item,this.position);
          return true;
        },
      ),
    );
  }
}

控制器

class MyDraggableController<T> {
  List<Function(T,Offset)> _targetUpdateCallbacks = new List<Function(T,Offset)>();
  //List<Function( )> _targetMoveCallbacks =  new List<Function( )>();
  MyDraggableController();
  void onDropped(T draggableData,Offset targetPosition) {
    debugPrint("dropped" + draggableData.toString());
    _targetUpdateCallbacks.forEach((f) {
      f(draggableData,targetPosition);
    });
  }
  void subscribeToOnTargetCallback(Function(T,Offset) f) {
    _targetUpdateCallbacks.add(f);
  }
  void unSubscribeFromOnTargetCallback(Function(T,Offset) f) {
    _targetUpdateCallbacks.remove(f);
  }
}

使覆盖的可拖动小部件成为 DragTarget 的子项。

class _MyDragTargetState<T> extends State<MyDragTarget> {
  ...
  @override
  Widget build(BuildContext context) {
    debugPrint(position.toString());
    return Positioned(
      left: position.dx-10,
      top: position.dy-10,
      child: DragTarget<T>(
        builder: (context, list, list2) {
          return Stack(
            children: [
              Container(
                decoration: BoxDecoration(
                    color: Colors.blueGrey,
                    borderRadius: BorderRadius.circular(50.0)
                ),
                height: 120,
                width: 120,
                child: Center(
                  child: Text(data.toString().toUpperCase()
                ),
              ),
              MyDraggable(...) // Put your Draggable widgets here onwards
            ]
          );
        },
  ...
}

使用提供程序体系结构。

Constants.HOME_SCREEN: (BuildContext context) => ChangeNotifierProvider(
            builder: (context) => Data(), child: HomePage())

初始化变量的 getter 和 setter,内部 setter 函数 notifyListeners(( 将被调用,以便侦听这些变量的小部件可以重建。

创建 removeLastItem(( 方法,该方法将从可拖动列表中删除最后一项。

removeLastItem() {
    items.removeLast();
    notifyListeners();
  }

最好的例子是Manik Gupta。点击此链接。https://medium.com/flutterdevs/draggable-and-drag-target-in-flutter-2513ea7c09f2

class DragTargetWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return DragTarget(onWillAccept: (data) {
      return true;
    }, onAccept: (CardItem data) {
      if (Provider.of<Data>(context).itemsList.length >= 1) {
        Provider.of<Data>(context).removeLastItem();
        Provider.of<Data>(context).changeSuccessDrop(true);
        Provider.of<Data>(context).changeAcceptedData(data);
      }

最新更新