Search code examples
fluttergridviewdraggable

Draggable element inside a GridView in flutter has wrong position


Hi everyone I'm trying to use a GridView of icons and I want to drag those elements outsite the GridView in another widget. Once I start dragging an icon there is a gap between the starting drag point and the feedback widget. I tried also to set feedbackOffset but it didn't work.

I prepared an example code as POC

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        // This is the theme of your application.
        //
        // Try running your application with "flutter run". You'll see the
        // application has a blue toolbar. Then, without quitting the app, try
        // changing the primarySwatch below to Colors.green and then invoke
        // "hot reload" (press "r" in the console where you ran "flutter run",
        // or simply save your changes to "hot reload" in a Flutter IDE).
        // Notice that the counter didn't reset back to zero; the application
        // is not restarted.
        primarySwatch: Colors.blue,
      ),
      home: IconsCollector(),
    );
  }
}

// import 'package:flutter_svg_provider/flutter_svg_provider.dart';

class IconsCollector extends StatefulWidget {
  const IconsCollector({
    Key? key,
  }) : super(key: key);

  @override
  _IconsCollectorState createState() => _IconsCollectorState();
}

class _IconsCollectorState extends State<IconsCollector> {
  List<Widget> out = [];

  List iconlist = [
    Icon(Icons.ac_unit),
    Icon(Icons.ac_unit),
    Icon(Icons.ac_unit),
    Icon(Icons.ac_unit),
    Icon(Icons.ac_unit),
  ];

  @override
  void initState() {
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    var screensize = MediaQuery.of(context).size;

    return 
    GridView.builder(
                scrollDirection: Axis.vertical,
                itemCount: iconlist.length,
                gridDelegate: new SliverGridDelegateWithFixedCrossAxisCount(
                  crossAxisCount: 7,
                ),
                itemBuilder: (BuildContext context, int index) {
                  return Draggable(
                      hitTestBehavior: HitTestBehavior.translucent,
                      feedback:  Container(
                          width: screensize.width * 0.1,
                          height: screensize.height * 0.55,
                          margin: EdgeInsets.all(12),
                          decoration: new BoxDecoration(
                            boxShadow: <BoxShadow>[
                              BoxShadow(
                                color: Colors.grey,
                                offset: Offset(1.1, 1.1),
                                blurRadius: 10.0,
                              ),
                            ],
                            color: Colors.white,
                            border: Border.all(width: 5),
                            // borderRadius: new BorderRadius.all(Radius.circular(30.0)),
                            shape: BoxShape.circle,
                          ),

                          child: ClipRRect(
                              borderRadius: BorderRadius.circular(30.0),
                              child: iconlist[index])),
                      data: index,
                      child: Container(
                          width: screensize.width * 0.1,
                          height: screensize.height * 0.55,
                          margin: EdgeInsets.all(12),
                          decoration: new BoxDecoration(
                            boxShadow: <BoxShadow>[
                              BoxShadow(
                                color: Colors.grey,
                                offset: Offset(1.1, 1.1),
                                blurRadius: 10.0,
                              ),
                            ],
                            color: Colors.white,
                            border: Border.all(width: 5),
                            // borderRadius: new BorderRadius.all(Radius.circular(30.0)),
                            shape: BoxShape.circle,
                          ),

                          child: ClipRRect(
                              borderRadius: BorderRadius.circular(30.0),
                              child: iconlist[index])));
                });
          

    
  }
}

Anybody has any idea how to solve this issue? I cannot use drag_and_drop_gridview because I want to drag the icon outside the GridView.

My flutter doctor output:

[✓] Flutter (Channel stable, 2.2.3, on Linux, locale en_US.utf8)
[✓] Android toolchain - develop for Android devices (Android SDK version 30.0.3)
[✓] Chrome - develop for the web
[✓] Linux toolchain - develop for Linux desktop
[✓] Android Studio (version 4.1)
[✓] VS Code (version 1.58.2)
[✓] Connected device (3 available)

• No issues found!

I attach a screenshot of the emulator. The same thing happens on a real device too. Note the gap between the mouse pointer and the dragged icon Thank you all for any suggestions!


Solution

  • It happening because in feed back your container size is big and you are clippling with transparent background here i fixed it,

    import 'package:flutter/material.dart';
    
    void main() {
      runApp(MyApp());
    }
    
    class MyApp extends StatelessWidget {
      // This widget is the root of your application.
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Flutter Demo',
          theme: ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: IconsCollector(),
        );
      }
    }
    
    // import 'package:flutter_svg_provider/flutter_svg_provider.dart';
    
    class IconsCollector extends StatefulWidget {
      const IconsCollector({
        Key? key,
      }) : super(key: key);
    
      @override
      _IconsCollectorState createState() => _IconsCollectorState();
    }
    
    class _IconsCollectorState extends State<IconsCollector> {
      List<Widget> out = [];
    
      List iconlist = [
        Icon(Icons.ac_unit),
        Icon(Icons.ac_unit),
        Icon(Icons.ac_unit),
        Icon(Icons.ac_unit),
        Icon(Icons.ac_unit),
      ];
    
      @override
      void initState() {
        super.initState();
      }
    
      @override
      Widget build(BuildContext context) {
        var screensize = MediaQuery.of(context).size;
    
        return GridView.builder(
            scrollDirection: Axis.vertical,
            itemCount: iconlist.length,
            gridDelegate: new SliverGridDelegateWithFixedCrossAxisCount(
              crossAxisCount: 7,
            ),
            itemBuilder: (BuildContext context, int index) {
              return Draggable(
                hitTestBehavior: HitTestBehavior.translucent,
                feedback: Container(
                  height:120,
                  width:120,
                  decoration: new BoxDecoration(
                    boxShadow: <BoxShadow>[
                      BoxShadow(
                        color: Colors.grey,
                        offset: Offset(1.1, 1.1),
                        blurRadius: 10.0,
                      ),
                    ],
                    color: Colors.white,
                    border: Border.all(width: 5),
                    shape: BoxShape.circle,
                  ),
                  child: ClipRRect(
                    borderRadius: BorderRadius.circular(30.0),
                    child: iconlist[index],
                  ),
                ),
                data: index,
                child: Container(
                  width: screensize.width * 0.1,
                  height: screensize.height * 0.55,
                  margin: EdgeInsets.all(12),
                  decoration: new BoxDecoration(
                    boxShadow: <BoxShadow>[
                      BoxShadow(
                        color: Colors.grey,
                        offset: Offset(1.1, 1.1),
                        blurRadius: 10.0,
                      ),
                    ],
                    color: Colors.white,
                    border: Border.all(width: 5),
                    shape: BoxShape.circle,
                  ),
                  child: ClipRRect(
                    borderRadius: BorderRadius.circular(30.0),
                    child: iconlist[index],
                  ),
                ),
              );
            });
      }
    }