Mindinventory / flutter_draggable_gridview

This package supports drag & drop widgets inside the GridView.builder for multiplatform. It provides all the properties which are available in Gridview. builder and easy to implement with the few lines of code.
https://www.mindinventory.com/flutter-app-development.php
MIT License
98 stars 19 forks source link

After updating from 0.0.8 to 0.0.9 the dragging completion stopped working? #24

Closed Jamey-7 closed 6 months ago

Jamey-7 commented 7 months ago

This is my current setup that I had working on 0.0.8 but after I upgraded to .0.0.9 when I drag an item to a different position the other items do not move out of the way and allow me to place it. Have I implemented this wrong is that why it stopped working on version .0.0.9?

Here is a simplified version of my code with the DraggableGridViewBuilder to display a list of items:

class RoutesWellsScreen extends StatefulWidget {
  final String routeId;
  final String routeName;

  RoutesWellsScreen({required this.routeId, required this.routeName});

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

class _RoutesWellsScreenState extends State<RoutesWellsScreen>
    with SingleTickerProviderStateMixin {
  TextEditingController _routeNameController = TextEditingController();

  bool _wellsLoaded = false; // Add a flag to indicate if wells have been loaded

  @override
  void initState() {
    super.initState();
    _routeNameController.text = widget.routeName;

    // Use Future.microtask to ensure that we are not in the middle of a build when calling setCurrentRoute
    Future.microtask(() async {
      final routesWellsModel =
          Provider.of<RoutesWellsModel>(context, listen: false);
      await routesWellsModel.setCurrentRoute(widget.routeId, widget.routeName);
      // Check if wells have already been loaded to prevent reloading
      if (!_wellsLoaded) {
        _loadWells();
        _wellsLoaded = true; // Set the flag to true after wells are loaded
      }
    });
  }

  @override
  void deactivate() {
    // Clear the wells data and other related state
    Provider.of<RoutesWellsModel>(context, listen: false).clearWellsData();

    super.deactivate();
  }

  @override
  void dispose() {
    // Dispose the text controller
    _routeNameController.dispose();
    // Dispose the controller only if it hasn't been disposed yet

    super.dispose();
  }

  Future<void> _loadWells() async {
    final routesWellsModel =
        Provider.of<RoutesWellsModel>(context, listen: false);

    final userDataProvider =
        Provider.of<UserDataProvider>(context, listen: false);

    // Set the current route before loading the wells
    await routesWellsModel.setCurrentRoute(widget.routeId, widget.routeName);

    // Now load the wells data
    String userId = userDataProvider.userId;
    await routesWellsModel.getSpecificRoute(
      userId,
      widget.routeId,
    );

    // Finally, set the loading state to false
    routesWellsModel.setLoadingState(false);
  }

  @override
  Widget build(BuildContext context) {
    ScreenUtil.init(context, designSize: Size(428, 926));

    return Consumer<RoutesWellsModel>(
      builder: (context, routesWellsModel, child) {

        int crossAxisCount =
            ResponsiveBreakpoints.of(context).largerThan('desktop')
                ? 4 // 4 columns for screen sizes larger than 'large-tablet'
                : ResponsiveBreakpoints.of(context).largerThan('large-tablet')
                    ? 3 // 3 columns for 'large-tablet' screen sizes
                    : ResponsiveBreakpoints.of(context).largerThan('tablet')
                        ? 2 // 2 columns for 'large-tablet' screen sizes
                        : 1;

        return Scaffold(
          backgroundColor: Color.fromARGB(255, 245, 245, 245),
          body: Column(
            children: [
              Expanded(
                child: Padding(
                  padding: EdgeInsets.fromLTRB(12, 5, 12, 15),
                  child: Consumer<RoutesWellsModel>(
                    builder: (context, model, child) {
                      if (model.wells.isEmpty) {
                        return Center(child: Text('No items to display'));
                      }
                      return DraggableGridViewBuilder(
                        gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
                          crossAxisCount: crossAxisCount,
                          mainAxisSpacing: 0.0,
                          crossAxisSpacing: 0.0,
                          childAspectRatio: (MediaQuery.of(context).size.width /
                                  crossAxisCount) /
                              160,
                        ),
                        children: model.wells.asMap().entries.map((entry) {
                          WellData well = entry.value;
                          return DraggableGridItem(
                            child: GestureDetector(
                              child: WellCard(wellData: well),
                            ),
                            isDraggable: true,
                          );
                        }).toList(),
                        dragCompletion: (List<DraggableGridItem> list,
                            int beforeIndex, int afterIndex) {
                          if (beforeIndex != afterIndex) {
                            Provider.of<RoutesWellsModel>(context,
                                    listen: false)
                                .reorderWellsInRoute(beforeIndex, afterIndex);
                          }
                        },
                        dragFeedback:
                            (List<DraggableGridItem> list, int index) {
                          print('Drag feedback called with index: $index');
                          if (index >= 0 && index < model.wells.length) {
                            WellData well = model.wells[index];
                            print(
                                'Creating drag feedback for Well with API No: ${well.apiNo}');
                            return Container(
                              width: MediaQuery.of(context).size.width /
                                  crossAxisCount,
                              height: 153,
                              child: Stack(
                                children: [
                                  Padding(
                                    padding:
                                        const EdgeInsets.fromLTRB(18, 3, 18, 0),
                                    child: WellCard(wellData: well),
                                  ),
                                ],
                              ),
                            );
                          } else {
                            print('Index out of range. Returning placeholder.');
                            return Container(
                              width: MediaQuery.of(context).size.width /
                                  crossAxisCount,
                              height: 153,
                              child: Center(child: Text('Loading...')),
                            );
                          }
                        },
                        dragPlaceHolder:
                            (List<DraggableGridItem> list, int index) {
                          print('Drag placeholder called with index: $index');
                          return PlaceHolderWidget(
                            child: Container(
                              color: const Color.fromARGB(255, 245, 245, 245),
                            ),
                          );
                        },
                        dragChildWhenDragging:
                            (List<DraggableGridItem> list, int index) {
                          print(
                              'Drag child when dragging called with index: $index');
                          return Container(); // Empty container represents the space left by the dragged item.
                        },
                      );
                    },
                  ),
                ),
              ),
            ],
          ),
        );
      },
    );
  }
}

For drag completion it is supposed to call this in my route_wells_model.dart to update the order but it never reaches this because drag completion is never called.

class RoutesWellsModel extends ChangeNotifier {
List<WellData> _wells = [];

Future<void> reorderWellsInRoute(int oldIndex, int newIndex) async {
  // Log initial state
  logMessage('Attempting to reorder well from oldIndex: $oldIndex to newIndex: $newIndex');
  logMessage('List before reordering: ${_wells.map((e) => e.apiNo)}');

  if (_currentRouteId.isEmpty) {
    logMessage('Error: Current route ID is empty, cannot reorder wells.');
    return;
  }

  // Adjust newIndex in case of dragging towards the end of the list
  if (newIndex > oldIndex) {
    newIndex -= 1; // This adjustment is necessary because the item is removed before inserting
  }

  // Log state right before reordering
  logMessage('Reordering well. oldIndex: $oldIndex, newIndex: $newIndex (after adjustment)');

  final WellData well = _wells.removeAt(oldIndex);
  _wells.insert(newIndex, well);

  // Log the result of the reorder operation
  logMessage('Well with API No. ${well.apiNo} moved to newIndex: $newIndex');
  logMessage('List after reordering: ${_wells.map((e) => e.apiNo)}');

  // Now, sync the new order locally
  for (int i = 0; i < _wells.length; i++) {
    _wells[i].order = i + 1; // Setting the new order based on the list index incremented by 1
    logMessage('Well with API No. ${_wells[i].apiNo} set to new order ${_wells[i].order}');
  }

  // Log the final state of the list
  logMessage('Final ordered list: ${_wells.map((e) => '${e.apiNo}: ${e.order}')}');

  // Immediately update the UI
  notifyListeners();
}
}

Here are my printouts on first load of the screen.

flutter: Listeners notified of changes
flutter: Drag feedback called with index: 0
flutter: Creating drag feedback for Well with API No: 84375934
flutter: Drag child when dragging called with index: 0
flutter: Drag placeholder called with index: 0
flutter: Drag feedback called with index: 1
flutter: Creating drag feedback for Well with API No: 67438562
flutter: Drag child when dragging called with index: 1
flutter: Drag placeholder called with index: 1
flutter: Drag feedback called with index: 2
flutter: Creating drag feedback for Well with API No: 46578454
flutter: Drag child when dragging called with index: 2
flutter: Drag placeholder called with index: 2
flutter: Drag feedback called with index: 3
flutter: Creating drag feedback for Well with API No: 578937492
flutter: Drag child when dragging called with index: 3
flutter: Drag placeholder called with index: 3

Then as soon as I hold an item and drag it around it just goes in a loop of this nonstop and no other items will move out of the way to allow me to drop the item in a different location so it never reaches drag completion.

flutter: Drag feedback called with index: 0
flutter: Creating drag feedback for Well with API No: 84375934
flutter: Drag child when dragging called with index: 0
flutter: Drag placeholder called with index: 0
flutter: Drag feedback called with index: 1
flutter: Creating drag feedback for Well with API No: 67438562
flutter: Drag child when dragging called with index: 1
flutter: Drag placeholder called with index: 1
flutter: Drag feedback called with index: 2
flutter: Creating drag feedback for Well with API No: 46578454
flutter: Drag child when dragging called with index: 2
flutter: Drag placeholder called with index: 2
flutter: Drag feedback called with index: 3
flutter: Creating drag feedback for Well with API No: 578937492
flutter: Drag child when dragging called with index: 3
flutter: Drag placeholder called with index: 3

Am I just doing this wrong i am not sure why the other items will not move in version .0.0.9

Anders3byg commented 6 months ago

https://github.com/Mindinventory/flutter_draggable_gridview/assets/92431441/66c5faa5-afec-4736-adf9-a76863177237

Only tried 0.0.9, but is it the same issue? It works functionality wise, but it hides one image instead of moving it over to the empty slot.

kingsglade commented 6 months ago

Similar issues, if you colour the placeholder its clearer what's happening

https://github.com/Mindinventory/flutter_draggable_gridview/assets/60739910/9068fcea-e50c-40fa-bc33-c74f4e49cf9a

Mine is moving the tiles around, but one of the tiles (the tile I moved) doesn't get updated with its replacement as the rest of the tiles are re-arranged until I drop the one I'm moving

Also using ^0.0.9 but I see exactly the same with ^0.08 down to ^0.06

xshiwei commented 6 months ago

Version 0.0.10 also has this problem, dragCompletion has no callback

xshiwei commented 6 months ago

flutter版本 3.19.1

abrarmalekji345 commented 6 months ago

This has been fixed in 0.0.11