karvulf / flutter-reorderable-grid-view

BSD 3-Clause "New" or "Revised" License
156 stars 23 forks source link

When wrap in PageView.builder, drag not work #121

Closed FanYuanBo888 closed 1 month ago

FanYuanBo888 commented 1 month ago
class RecorderablePage extends StatefulWidget {
  const RecorderablePage({super.key});

  @override
  State<RecorderablePage> createState() => _RecorderablePageState();
}

class _RecorderablePageState extends State<RecorderablePage> {
  final PageController _pageController =
      PageController(initialPage: 0, viewportFraction: 0.8);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: PageView.builder(
        controller: _pageController,
        itemBuilder: (c, i) => RecorderableItem(
          color: Colors.primaries[i],
        ),
        itemCount: 3,
      ),
    );
  }
}

class RecorderableItem extends StatefulWidget {
  final Color color;

  const RecorderableItem({super.key, required this.color});

  @override
  State<RecorderableItem> createState() => _RecorderableItemState();
}

class _RecorderableItemState extends State<RecorderableItem> {
  static const _startCounter = 200;
  List<int> children = List.generate(_startCounter, (index) => index);
  final lockedIndices = <int>[0, 4];
  final nonDraggableIndices = [0, 2, 3];

  var _scrollController = ScrollController();
  var _gridViewKey = GlobalKey();

  @override
  Widget build(BuildContext context) {
    return Container(
      color: widget.color,
      padding: const EdgeInsets.symmetric(vertical: 100),
      child: ReorderableBuilder.builder(
        key: Key(_gridViewKey.toString()),
        positionDuration: const Duration(seconds: 1),
        onReorder: _handleReorder,
        // lockedIndices: lockedIndices,
        // nonDraggableIndices: nonDraggableIndices,
        onDragStarted: _handleDragStarted,
        onUpdatedDraggedChild: _handleUpdatedDraggedChild,
        onDragEnd: _handleDragEnd,
        scrollController: _scrollController,
        childBuilder: (itemBuilder) {
          return GridView.builder(
            key: _gridViewKey,
            scrollDirection: Axis.vertical,
            controller: _scrollController,
            padding: EdgeInsets.all(8),
            itemCount: children.length,
            itemBuilder: (context, index) {
              return itemBuilder(
                _getChild(index: index),
                index,
              );
            },
            gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
              crossAxisCount: 4,
              mainAxisSpacing: 10,
              crossAxisSpacing: 10,
            ),
          );
        },
      ),
    );
  }

  Widget _getChild({required int index}) {
    return CustomDraggable(
      key: Key(children[index].toString()),
      data: index,
      child: Container(
        decoration: BoxDecoration(
          color: lockedIndices.contains(index)
              ? Theme.of(context).disabledColor
              : Theme.of(context).colorScheme.primary,
        ),
        height: 100.0,
        width: 100.0,
        child: Center(
          child: Text(
            '${children[index]}',
            style: const TextStyle(
              color: Colors.black,
              fontWeight: FontWeight.bold,
            ),
          ),
        ),
      ),
    );
  }

  void _handleDragStarted(int index) {
    _showSnackbar(text: 'Dragging at index $index has started!');
  }

  void _handleUpdatedDraggedChild(int index) {
    _showSnackbar(text: 'Dragged child updated position to $index');
  }

  void _handleReorder(ReorderedListFunction reorderedListFunction) {
    setState(() {
      children = reorderedListFunction(children) as List<int>;
    });
  }

  void _handleDragEnd(int index) {
    _showSnackbar(text: 'Dragging was finished at $index!');
  }

  void _showSnackbar({required String text}) {
    ScaffoldMessenger.of(context).clearSnackBars();
    final snackBar = SnackBar(
      content: Text(
        text,
        style: const TextStyle(color: Colors.white),
      ),
      backgroundColor: Theme.of(context).colorScheme.surface,
      duration: const Duration(milliseconds: 1000),
    );
    ScaffoldMessenger.of(context).showSnackBar(snackBar);
  }
}

Scroll to the bottom and drag item again, and the order will be out of order

karvulf commented 1 month ago

Hello @FanYuanBo888 This issue seems to be related to #67 and #113. I will try to find some time later or this weekend and will look for a soluation that also this package is also working for PageView.builder.

karvulf commented 1 month ago

I fixed the issue and will do a release soon. I also want to fix some other issues and will release it with version 5.3.1 @FanYuanBo888