Search code examples
androidrowflutterlong-press

Flutter longPress event functionality for selection of row(s) and/or elements


I need to implement a long press selection on a row element of Flutter for Android and iOS. Any help please?

My code so far:

class ListElement extends StatelessWidget {
  ListElement({this.text, this.name, this.mId, this.animationController});

  final String text;
  final String name;
  final String mId;
  final AnimationController animationController; 

  @override
  Widget build(BuildContext context) {
    return new GestureDetector(
      onTap: () {
         Navigator.of(context).push(
                  new MaterialPageRoute(builder: (BuildContext context) => new DrugProfile(drugmId))
                );
      }, 
      onLongPress: () {
       //HERE I NEED TO SELECT MULTIPLE ROWS IF IT FIRES
      }, 

      child: new SizeTransition(
        sizeFactor: new CurvedAnimation(
            parent: animationController, curve: Curves.easeOut),
        axisAlignment: 0.0,
        child: new Container(
          margin: const EdgeInsets.symmetric(vertical: 10.0),
          child: new Row(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: <Widget>[
              new Container(
                margin: const EdgeInsets.only(right: 16.0),
                child: new CircleAvatar(child: new Text(name[0].toUpperCase())),
              ),
              new Expanded(
                child: new Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: <Widget>[
                    new Text(name, style: Theme.of(context).textTheme.subhead),
                    new Container(
                      margin: const EdgeInsets.only(top: 5.0),
                      child: new Text(
                        text,
                        textAlign: TextAlign.left,
                        style: new TextStyle(
                        fontSize: 13.0,),
                      ),
                    ),
                  ],
                ),
              ),
            ],
          ),
        )
      )
    );
  }
}

Maybe I am wrong starting from the onLongPress event, but I need to do the following: If longPress on a row element then provide the ability to select many rows. And after selection then perform custom operation on the rows (this is not part of the question :) ) After selection I imagine a array of indexes that I can pass into a function for further processes. I only need help with multiple selection of elements.


Solution

  • You can use a HashMap to track the selected items in the List and update its values depending on the gesture that you'd like.

    Here's a sample that you can try. In this sample, multi-select mode will start on long press of an item. Multi-select mode will stop when there's no selected items left.

    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,
            visualDensity: VisualDensity.adaptivePlatformDensity,
          ),
          home: MyHomePage(title: 'Flutter Demo Home Page'),
        );
      }
    }
    
    class MyHomePage extends StatefulWidget {
      MyHomePage({Key key, this.title}) : super(key: key);
    
      final String title;
    
      @override
      _MyHomePageState createState() => _MyHomePageState();
    }
    
    class _MyHomePageState extends State<MyHomePage> {
      var selectMode = false;
    
      Map<String, bool> listItemSelected = {
        'List 1': false,
        'List 2': false,
        'List 3': false,
        'List 4': false,
        'List 5': false,
        'List 6': false,
        'List 7': false,
        'List 8': false,
        'List 9': false,
      };
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text(widget.title),
          ),
          body: Center(
            child: ListView(
              children: listItemSelected.keys.map((key) {
                return Card(
                  child: GestureDetector(
                    onTap: () {
                      // if multi-select mode is true, tap should select List item
                      if (selectMode && listItemSelected.containsValue(true)) {
                        debugPrint('onTap on $key');
                        setState(() {
                          listItemSelected[key] = !listItemSelected[key];
                        });
                      } else {
                        // Stop multi-select mode when there's no more selected List item
                        debugPrint('selectMode STOP');
                        selectMode = false;
                      }
                    },
                    // Start List multi-select mode on long press
                    onLongPress: () {
                      debugPrint('onLongPress on $key');
                      if (!selectMode) {
                        debugPrint('selectMode START');
                        selectMode = true;
                      }
                      setState(() {
                        listItemSelected[key] = !listItemSelected[key];
                      });
                    },
                    child: Container(
                      // Change List item color if selected
                      color: (listItemSelected[key])
                          ? Colors.lightBlueAccent
                          : Colors.white,
                      padding: EdgeInsets.all(16.0),
                      child: Text(key),
                    ),
                  ),
                );
              }).toList(),
            ),
          ),
        );
      }
    }
    
    

    Demo

    demo