1

I'm working with draggables and dragtargets in Flutter. I currently have two dragtargets in my project, both respond correctly once I drop a draggable over them. However, once the first drag from draggable1 to dragtarget1 is complete, the second drag brings up an issue: whilst hovering (not dropped) over dragtarget2 with draggable2, the onaccept property is triggered and dragtarget2 is built with the contents of dragtarget1. I don't understand why. I'd be grateful for any help/tips!

I have made a short video with a visual representation of the issue: https://youtu.be/IJa3oZ_7fw0

Here's my code for the dragtarget:

 Widget build(BuildContext context) {
bool isSuccessful = false;
int caughtData;
return SafeArea(
  child: Column(
    children: <Widget>[
      Row(
        children: <Widget>[
          Expanded(
            child: Container(
              height: 70,
              width: 200,
              color: Colors.grey.shade600,
              child: DragTarget<int>(
                builder: (context, List<int> candidateData, rejectedData) {
                  return isSuccessful
                      ? FlatButton(
                          color:
                              chordBrain.chordBank[caughtData].buttoncolor,
                          child:
                              Text(chordBrain.chordBank[caughtData].chord),
                          onPressed: () {
                            playSound(noteBrain.noteBank[caughtData].note1);
                            playSound(noteBrain.noteBank[caughtData].note2);
                            playSound(noteBrain.noteBank[caughtData].note3);
                            playSound(noteBrain.noteBank[caughtData].note4);
                          },
                        )
                      : Container();
                },
                onWillAccept: (int data) {
                  print('$data');
                  return true;
                },
                onAccept: (int data) {
                  print('$data');
                  isSuccessful = true;
                  caughtData = data;
                },
              ),
            ),
          ),
          SizedBox(
            width: 8,
          ),
          Expanded(
            child: Container(
              height: 70,
              width: 200,
              color: Colors.grey.shade600,
              child: DragTarget<int>(
                builder: (context, List<int> candidateData, rejectedData) {
                  return isSuccessful
                      ? FlatButton(
                          color:
                              chordBrain.chordBank[caughtData].buttoncolor,
                          child:
                              Text(chordBrain.chordBank[caughtData].chord),
                          onPressed: () {
                            playSound(noteBrain.noteBank[caughtData].note1);
                            playSound(noteBrain.noteBank[caughtData].note2);
                            playSound(noteBrain.noteBank[caughtData].note3);
                            playSound(noteBrain.noteBank[caughtData].note4);
                          },
                        )
                      : Container();
                },
                onWillAccept: (int data) {
                  print('$data');
                  return true;
                },
                onAccept: (int data) {
                  print('$data');
                  isSuccessful = true;
                  caughtData = data;
                },
              ),
            ),
          ),
        ],
      ),

1 Answers1

0

It seems I've found a solution, it's not very elegant but it works. Although I still don't understand why my draggables trigger a build when hovering (not dropped) over the dragtargets, the problem was resolved by making the dragtargets more dissimilar to each other. Instead of assigning both my dragtargets the same bool and int variables to trigger the build widget, I gave them unique variables:

Widget build(BuildContext context) {
bool isSuccessful = false;
bool isWorking = false;
int caughtData1;
int caughtData2;

The boolean isSuccessful and integer caughtData1 was assigned to the first dragtarget, isWorking and caughtData2 assigned to the second dragtarget. I also deleted the onWillAccept code - not sure if this was necessary though. The full code as follows:

Widget build(BuildContext context) {
bool isSuccessful = false;
bool isWorking = false;
int caughtData1;
int caughtData2;

return SafeArea(
  child: Column(
    children: <Widget>[
      Row(
        children: <Widget>[
          Expanded(
            child: Container(
              height: 70,
              color: Colors.grey.shade600,
              child: DragTarget<int>(
                builder: (context, List<int> candidateData, rejectedData) {
                  return isWorking
                      ? FlatButton(
                          color:
                              chordBrain.chordBank[caughtData1].buttoncolor,
                          child:
                              Text(chordBrain.chordBank[caughtData1].chord),
                          onPressed: () {
                            playSound(
                                noteBrain.noteBank[caughtData1].note1);
                            playSound(
                                noteBrain.noteBank[caughtData1].note2);
                            playSound(
                                noteBrain.noteBank[caughtData1].note3);
                            playSound(
                                noteBrain.noteBank[caughtData1].note4);
                          },
                        )
                      : Container();
                },
                onAccept: (int data) {
                  print('$data');
                  caughtData1 = data;
                  isWorking = true;
                },
              ),
            ),
          ),
          SizedBox(
            width: 8,
          ),
          Expanded(
            child: Container(
              height: 70,
              color: Colors.grey.shade600,
              child: DragTarget<int>(
                builder: (context, List<int> candidateData, rejectedData) {
                  return isSuccessful
                      ? FlatButton(
                          color:
                              chordBrain.chordBank[caughtData2].buttoncolor,
                          child:
                              Text(chordBrain.chordBank[caughtData2].chord),
                          onPressed: () {
                            playSound(
                                noteBrain.noteBank[caughtData2].note1);
                            playSound(
                                noteBrain.noteBank[caughtData2].note2);
                            playSound(
                                noteBrain.noteBank[caughtData2].note3);
                            playSound(
                                noteBrain.noteBank[caughtData2].note4);
                          },
                        )
                      : Container();
                },
                onAccept: (int data) {
                  print('$data');
                  caughtData2 = data;
                  isSuccessful = true;
                },
              ),
            ),
          ),
        ],
      ),