How to specify drag target for a certain widget Flutter (Single Draggable Being Dropped Into 3 Drag Targets Instead Of 1)

1,746

This is happening because on each DragTarget you are building the same widget.caughtAnimation that you set on any onAccept callback.

Consider structuring your widget state model in a way that you can individually modify each DragTarget, this can be done with a List/array or a map.

List<LottieBuilder> caughtAnimations;

then

                mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
                  DragTarget(
                    onAccept: (LottieBuilder animation) {
                      setState(() {
                        caughtAnimations[0] = animation;
                      });
                    },
                    builder: (BuildContext context, List<dynamic> candidateData, List<dynamic> rejectedData) {
                      return Center(
                        child: Container(
                          height: 60,
                          width: 60,
                          decoration: BoxDecoration(
                              color: Colors.grey.shade400.withOpacity(0.5), borderRadius: BorderRadius.circular(20.0)),
                          child: caughtAnimations[0],
                        ),
                      );
                    },
                  ),
                  Padding(
                    padding: const EdgeInsets.all(8.0),
                    child: DragTarget(
                      onAccept: (LottieBuilder animation) {
                        setState(() {
                          caughtAnimations[1] = animation;
                        });
                      },
                      builder: (BuildContext context, List<dynamic> candidateData, List<dynamic> rejectedData) {
                        return Center(
                          child: Container(
                            height: 60,
                            width: 60,
                            decoration: BoxDecoration(
                                color: Colors.grey.shade400.withOpacity(0.5),
                                borderRadius: BorderRadius.circular(20.0)),
                            child: caughtAnimations[1],
                          ),
                        );
                      },
                    ),
                  ),
                  DragTarget(
                    onAccept: (LottieBuilder animation) {
                      setState(() {
                        caughtAnimations[2] = animation;
                      });
                    },
                    builder: (BuildContext context, List<dynamic> candidateData, List<dynamic> rejectedData) {
                      return Center(
                        child: Container(
                          height: 60,
                          width: 60,
                          decoration: BoxDecoration(
                              color: Colors.grey.shade400.withOpacity(0.5), borderRadius: BorderRadius.circular(20.0)),
                          child: caughtAnimations[2],
                        ),
                      );
                    },
                  ),
                ],
              ),
Share:
1,746
XtremeDevX
Author by

XtremeDevX

I'm XtremeDevX, professional app developer, and I code Dart, Swift, And Python. I am currently learning Tensorflow and Keras for advanced Machine Learning.

Updated on November 18, 2022

Comments

  • XtremeDevX
    XtremeDevX over 1 year

    Here is the problem that I am facing:

    I start off with a list of emoji's which I want to drop into these 3 Drop Targets

    (I want to be able to select each emoji which goes into each of these drop targets) enter image description here

    When I drag one of these emojis (only one, which is in this case, the first one, it automatically drops into all the drag targets instead of only the first one).

    This results in the same emoji populating all the drag targets unintentionally like this which is unexpected behavior:

    enter image description here

    My question is, how can I change my code so that I can make sure that, when I drag on emoji into the first, second, or third Drag target, only that respective drag target gets filled instead of all of them? Thanks a lot and I really appreciate your help!

    Code For DragBox:

    class DragBox extends StatefulWidget {
      DragBox({this.animatedAsset, this.width});
      final LottieBuilder animatedAsset;
      final double width;
      @override
      _DragBoxState createState() => _DragBoxState();
    }
    
    class _DragBoxState extends State<DragBox> {
      @override
      Widget build(BuildContext context) {
        return Draggable(
          feedback: Container(
            width: 50,
            height: 50,
            child: widget.animatedAsset,
          ),
          child: Container(
            child: widget.animatedAsset,
            width: widget.width,
            height: 50,
          ),
          childWhenDragging: Container(),
          data: widget.animatedAsset,
        );
      }
    }
    

    Code For Emoji Picker :

    class AnimatedEmojiPicker extends StatefulWidget {
      @override
      _AnimatedEmojiPickerState createState() => _AnimatedEmojiPickerState();
    }
    
    class _AnimatedEmojiPickerState extends State<AnimatedEmojiPicker> {
      @override
      Widget build(BuildContext context) {
        return Padding(
          padding: const EdgeInsets.only(left: 10.0, right: 10.0),
          child: Container(
            width: MediaQuery.of(context).size.width,
            height: 60,
            decoration:
                BoxDecoration(color: Colors.grey.shade400.withOpacity(0.5), borderRadius: BorderRadius.circular(20.0)),
            child: ListView(
              scrollDirection: Axis.horizontal,
              children: <Widget>[
                Container(
                  width: 15,
                ),
                DragBox(
                  animatedAsset: Lottie.asset('Assets/blushing.json'),
                ),
                Container(
                  width: 15,
                ),
                DragBox(
                  animatedAsset: Lottie.asset('Assets/cooldude.json'),
                ),
                Container(
                  width: 15,
                ),
                DragBox(
                  animatedAsset: Lottie.asset('Assets/zipmouth.json'),
                ),
                //More drag boxes like this one
              ],
            ),
          ),
        );
      }
    }
    

    My Drag targets:

                    mainAxisAlignment: MainAxisAlignment.center,
                    children: <Widget>[
                      DragTarget(
                        onAccept: (LottieBuilder animation) {
                          setState(() {
                            widget.caughtAnimation = animation;
                          });
                        },
                        builder: (BuildContext context, List<dynamic> candidateData, List<dynamic> rejectedData) {
                          return Center(
                            child: Container(
                              height: 60,
                              width: 60,
                              decoration: BoxDecoration(
                                  color: Colors.grey.shade400.withOpacity(0.5), borderRadius: BorderRadius.circular(20.0)),
                              child: widget.caughtAnimation,
                            ),
                          );
                        },
                      ),
                      Padding(
                        padding: const EdgeInsets.all(8.0),
                        child: DragTarget(
                          onAccept: (LottieBuilder animation) {
                            setState(() {
                              widget.caughtAnimation = animation;
                            });
                          },
                          builder: (BuildContext context, List<dynamic> candidateData, List<dynamic> rejectedData) {
                            return Center(
                              child: Container(
                                height: 60,
                                width: 60,
                                decoration: BoxDecoration(
                                    color: Colors.grey.shade400.withOpacity(0.5),
                                    borderRadius: BorderRadius.circular(20.0)),
                                child: widget.caughtAnimation,
                              ),
                            );
                          },
                        ),
                      ),
                      DragTarget(
                        onAccept: (LottieBuilder animation) {
                          setState(() {
                            widget.caughtAnimation = animation;
                          });
                        },
                        builder: (BuildContext context, List<dynamic> candidateData, List<dynamic> rejectedData) {
                          return Center(
                            child: Container(
                              height: 60,
                              width: 60,
                              decoration: BoxDecoration(
                                  color: Colors.grey.shade400.withOpacity(0.5), borderRadius: BorderRadius.circular(20.0)),
                              child: widget.caughtAnimation,
                            ),
                          );
                        },
                      ),
                    ],
                  ),
    

    Again, thanks for any help!

  • XtremeDevX
    XtremeDevX almost 4 years
    thanks @MDemetrio for the answer, though could you explain how to change my draggable objects according to this list of caught animations, thanks a lot and i will mark your answer as accepted once i completely understand how to change my code!
  • MDemetrio
    MDemetrio almost 4 years
    On your DragTarget's containing widget State class declare the List<LottieBuilder> caughtAnimations; on each DragTarget's onAccept, set the caughtAnimations on a specified index ``` setState(() { caughtAnimations[1] = animation; }); ``` then on the builder of the same DragTarget, build the caughtAnimations of the specified index
  • XtremeDevX
    XtremeDevX almost 4 years
    Ok, though how do I change my draggable object?
  • MDemetrio
    MDemetrio almost 4 years
    I don't think your Draggable object requires any change
  • XtremeDevX
    XtremeDevX almost 4 years
    Ok thanks a lot! I really appreciate your help! Keep posting great answers like this on stackoverflow!!