Is it possible to disable reordering a single item in a reorderable listview in flutter?
Asked Answered
B

7

13

I am trying to create a ListView that meets the following criteria:

  1. The items in the ListView are categorized into sections with headers for each section
  2. The items can be dragged from one section to another
  3. The section headers are not draggable

This would easy to accomplish if ReorderableListView allowed you to disable a ListTile from being dragged & dropped (in other words, I would be able to create the headers as ListTile items in the ListView and disable dragging and dropping on only them while still allowing everything else to be dragged & dropped), but I can't figure out how. Any tips?

Bouzoun answered 24/5, 2021 at 1:2 Comment(2)
pub.dev/packages/drag_and_drop_lists This plugin will help youSwanner
I have the same requirements as you did. Did you manage to get anywhere with that?Coleman
C
8

This is another workaround.

Wrap the widget you don't want to be moved in a GestureDetector, then override the onLongPress.

 return GestureDetector(
                                  onLongPress: () {},
                                  key: ValueKey(index),
                                  child: Column(
                                      children: List.generate(
                                          3,
                                          (index) => ListTile(
                                              title: Text("TItle test")))),
                                );

Check this https://github.com/hanshengchiu/reorderables/issues/89#:~:text=movable%20widgets%20in%3A-,GestureDetector(%0A%20%20%20%20%20%20onLongPress%3A%20()%20%7B%7D%2C%20//%20Override%20onLongPress%20to%20make%20item%20unmovable.%0A%20%20%20%20%20%20child%3A%20...%0A),-6 for the full discussion

Costumier answered 4/5, 2022 at 10:11 Comment(0)
B
4

Just discovered the AbsorbPointer and IgnorePointer classes.

Bouzoun answered 24/5, 2021 at 2:7 Comment(2)
This will still allow items to be reordered around it. So if you were trying to keep an item at the top, they could drag another above it.Grous
That's a valid observation. With this implementation, I think the the simplest solution to this edge case is to ignore the invalid reordering in the onReorder callback But I agree that an ideal implementation would prevent the top header from moving when reordering an item above itBouzoun
H
1

You can prevent moving the headers with AbsortPointer etc. as you mentioned, but if the other items are moved into a place that you don't want to allow, you can simply check for this in the onReorder callback and not update the underlying model, so when the user drops the item it will get back to its original place. E.g. if the user tries moving any movable item to be placed before the first header, you detect this (newIndex == 0) and return early.

Holp answered 12/8, 2021 at 8:27 Comment(0)
W
1

You can use ReorderableDragStartListener.

Wrap the sections that need to be non-reorderable with it and pass enabled: false like so:

class HeaderSection extends StatelessWidget {
  const HeaderSection({
    Key? key,
    required this.index,
  }) : super(key: key);

  final int index;

  @override
  Widget build(BuildContext context) {
    return ReorderableDragStartListener(
      index: index,
      enabled: false,
      child: const Text('This header can not be dragged'),
    );
  }
} 

There is also ReorderableDelayedDragStartListener for cases where you want to use long-press to begin reordering.

Wismar answered 22/9, 2022 at 15:9 Comment(1)
This did not work for me on flutter 3.3.5.Hansel
C
1

Check out this example
You can set buildDefaultDragHandles to false, then build the drag handler using ReorderableDragStartListener only for non-header items

Curarize answered 30/7, 2024 at 6:52 Comment(0)
A
0

You can add a some type of nonreorderable bool field to tiles , and check it when onReorder is called, and just skip the index change, or do same extra logic for that particular case.

Ats answered 4/2, 2022 at 6:44 Comment(0)
J
-1

The reorderable list wrap with AbsorbPointer widget

Use AbsorbPointer to disable widgets

 AbsorbPointer(
            absorbing: countList.length <= 1 ? true : false,
            child: ReorderableListView(
                shrinkWrap: true,
                buildDefaultDragHandles: false,
                dragStartBehavior: DragStartBehavior.down,
                physics: const NeverScrollableScrollPhysics(),
                children: <Widget>[
                  for (var i = 0; i < countList.length; i++)
                    Card(
                      elevation: 0,
                      color: customColors().backgroundPrimary,
                      key: ValueKey(
                          countList[i].Name),
                      child: Container(
                        child:Text("Demo")
                      ),
                    ),
                ],
                onReorder:onReoder),
          ),
Jubbulpore answered 29/7, 2022 at 10:16 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.