drag_select_grid_view icon indicating copy to clipboard operation
drag_select_grid_view copied to clipboard

set limitation to select

Open pishguy opened this issue 4 years ago • 11 comments

in this library how can i set limited selected items? for example user can't select more than 10 items?

pishguy avatar Apr 19 '20 13:04 pishguy

Such feature is not supported yet, but we can work around that by undoing any changes that lead to selecting above the limit. Please take this example:

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  static const selectionLimit = 10;

  final controller = DragSelectGridViewController();
  Selection currentSelection;

  @override
  void initState() {
    super.initState();
    controller.addListener(handleSelectionChange);
  }

  @override
  void dispose() {
    controller.removeListener(handleSelectionChange);
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: SelectionAppBar(
        selection: controller.selection,
        title: const Text('Grid Example'),
      ),
      body: DragSelectGridView(
        gridController: controller,
        padding: const EdgeInsets.all(8),
        itemCount: 90,
        itemBuilder: (context, index, selected) {
          return SelectableItem(
            index: index,
            color: Colors.blue,
            selected: selected,
          );
        },
        gridDelegate: const SliverGridDelegateWithMaxCrossAxisExtent(
          maxCrossAxisExtent: 150,
          crossAxisSpacing: 8,
          mainAxisSpacing: 8,
        ),
      ),
    );
  }

  void handleSelectionChange() {
    if (controller.selection.amount > selectionLimit) {
      setState(() => controller.selection = currentSelection);
    } else {
      setState(() {
        currentSelection = Selection(
          Set.of(controller.selection.selectedIndexes),
        );
      });
    }
  }
}

hcbpassos avatar Apr 19 '20 20:04 hcbpassos

You can set a maximum parameter to your Grid Widget like that : GridWidget( maximum: 15, ). By creating the selected item Widget ( which you can find in the example ) , you can
then add a bool named parameter , which checks if your selection list reached the maximum like that :

 SelectableItem(
            isMaximum: _selectedList.length == widget.maximum,
            whenSelcted: () { },
            whenUnselected: ()  { },
)

Then in the SelectableItem Widget you can check this condition in the didUpdateWidget method like that :

@override
void didUpdateWidget(SelectableItem oldWidget) {
 super.didUpdateWidget(oldWidget);
 if (oldWidget.selected != widget.selected) {
   if (widget.selected) {
     if (widget.isMaximum == false) {
       _controller.forward();
       widget.whenSelcted();
     } else {
       Fluttertoast.showToast(msg: 'You\'ve reached the maximum');
     }
   } else {
     _controller.reverse();
     widget.whenUnselected();
   }
 }
}

Loopex2019 avatar Apr 21 '20 08:04 Loopex2019

@Loopex2019 could you reformat your code?

and GridWidget in library source? i should change that handly?

pishguy avatar Apr 21 '20 09:04 pishguy

No gridview is just an example. I mean it is the widget you created , which its build method return the DragSelectGridView widget

Loopex2019 avatar Apr 21 '20 09:04 Loopex2019

@Loopex2019 I appreciate your suggestion, but it is not correct. Not calling _controller.forward(); only avoids the selection animation, it doesn't make the item in fact unselected.

The only way to unselect an item is through DragSelectGridViewController.selection, as I suggested above :)

@MahdiPishguy Have you tried that?

ghost avatar Apr 21 '20 14:04 ghost

@hugocbpassos thanks for explaining to me . This actually worked for me. Because in the whenSelected() Method it adds the selected item into a list . So by checking the maximum it doesn't only prevent the controller from animating but also prevents the whenSelected() Method from being fired . But of course you are right since the selection itself doesn't change .

Loopex2019 avatar Apr 21 '20 14:04 Loopex2019

So by checking the maximum it doesn't only prevent the controller from animating but also prevents the whenSelected() Method from being fired .

The thing is, the item is already selected when State.didUpdateWidget() is called, so not firing whenSelected() won't actually help :)

By the way, those callbacks (whenSelected() and whenUnselected()) made me worry. DragSelectGridViewController should be able to handle selection by itself. There's no need to duplicate such logic.

Furthermore, for semantic purposes, the only information SelectableItem should receive is selected.

ghost avatar Apr 21 '20 15:04 ghost

@hugocbpassos don't worry it's just a callback when the item gets selected to add my custom logic for adding the selected items inside a List variable.

Loopex2019 avatar Apr 21 '20 15:04 Loopex2019

@Loopex2019 You should be doing that with DragSelectGridViewController.addListener().

ghost avatar Apr 21 '20 15:04 ghost

Ah okay thanks for clarifying

Loopex2019 avatar Apr 21 '20 15:04 Loopex2019

@Loopex2019 I appreciate your suggestion, but it is not correct. Not calling _controller.forward(); only avoids the selection animation, it doesn't make the item in fact unselected.

The only way to unselect an item is through DragSelectGridViewController.selection, as I suggested above :)

@MahdiPishguy Have you tried that?

i test this source code which that is here https://github.com/hugocbpassos/drag_select_grid_view/issues/9#issuecomment-616216177

its work fine :)

pishguy avatar Apr 21 '20 15:04 pishguy