Does flutter have a contextual action bar for selecting multiple item from a list view

2,057

You should keep the "selected" state in your list data not in your widget.

Something like that:

import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:playground/feature_discovery.dart';

void main() {
  timeDilation = 1.0;
  runApp(MaterialApp(home: MyHomePage()));
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => new _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  bool longPressFlag = false;
  List<Element> indexList = new List();
  int selectedCount = 0;
  void longPress() {
    setState(() {
      if (indexList.isEmpty) {
        longPressFlag = false;
      } else {
        longPressFlag = true;
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    for (var i = 0; i < 50; i++) {
      indexList.add(Element(isSelected: false));
    }

return new Scaffold(
  appBar: AppBar(
    title: Text("Title"),
    actions: <Widget>[
      Padding(
        padding: const EdgeInsets.only( right: 15.0),
        child: Center(child: Text("$selectedCount")),
      ),
    ],
  ),
  body: new ListView.builder(
    itemCount: 50,
    itemBuilder: (context, index) {
      return new CustomWidget(
        isSelected: indexList[index].isSelected,
        index: index,
        longPressEnabled: longPressFlag,
        callback: () {
          onElementSelected(index);
          if (indexList.contains(index)) {
            indexList.remove(index);
          } else {
            indexList.add(Element());
          }
          longPress();
        },
      );
    },
  ),
);

}

onElementSelected(int index) {
    setState(() {
      if(indexList[index].isSelected)
        selectedCount--;
      else
        selectedCount++;
      indexList[index].isSelected = !indexList[index].isSelected;
    });
  }
}

class CustomWidget extends StatefulWidget {
  final int index;
  final bool longPressEnabled;
  final VoidCallback callback;
  final bool isSelected;
  const CustomWidget(
      {Key key,
      this.index,
      this.longPressEnabled,
      this.callback,
      this.isSelected})
      : super(key: key);
  @override
  _CustomWidgetState createState() => new _CustomWidgetState();
}

class _CustomWidgetState extends State<CustomWidget> {
  @override
  Widget build(BuildContext context) {
    return new GestureDetector(
      onLongPress: () {
        widget.callback();
      },
      onTap: () {
        if (widget.longPressEnabled) {
          widget.callback();
        }
      },
      child: new Container(
        margin: new EdgeInsets.all(5.0),
        child: new ListTile(
          title: new Text("Title ${widget.index}"),
          subtitle: new Text("Description ${widget.index}"),
        ),
        decoration: widget.isSelected
            ? new BoxDecoration(
                color: Colors.black38,
                border: new Border.all(color: Colors.black))
            : new BoxDecoration(),
      ),
    );
  }
}

class Element {
  Element({this.isSelected});
  bool isSelected;
}
Share:
2,057
Sourav Das
Author by

Sourav Das

Hello I am a mobile application developer. In the recent past I have made some apps for play store.I also have some experience in developing cross platform apps.

Updated on November 24, 2022

Comments

  • Sourav Das
    Sourav Das over 1 year

    Hello I am working on a project where I need to select multiple item from a listview .I tried the code below but the problem is , If I select an item then I scroll up and scroll down to that item color should be changed into white color.If there be a package that solves these issue then please help me.Any help or code will be welcomed.

    class MyHomePage extends StatefulWidget {
    @override
    _MyHomePageState createState() => new _MyHomePageState();}
    class _MyHomePageState extends State<MyHomePage> {
    bool longPressFlag = false;
    List<int> indexList = new List();
    void longPress() {
    setState(() {
      if (indexList.isEmpty) {
        longPressFlag = false;
      } else {
        longPressFlag = true;
      }
    });}
    @override
    Widget build(BuildContext context) {
    return new Scaffold(
      body: new ListView.builder(
        itemCount: 3,
        itemBuilder: (context, index) {
          return new CustomWidget(
            index: index,
            longPressEnabled: longPressFlag,
            callback: () {
              if (indexList.contains(index)) {
                indexList.remove(index);
              } else {
                indexList.add(index);
              }
        longPress();
            },
          );
          },),
    );}}
    class CustomWidget extends StatefulWidget {
    final int index;
    final bool longPressEnabled;
    final VoidCallback callback;
    const CustomWidget({Key key, this.index, this.longPressEnabled,    this.callback}) : super(key: key);
    @override
    _CustomWidgetState createState() => new _CustomWidgetState();
    }
    class _CustomWidgetState extends State<CustomWidget> {
    bool selected = false;
    @override
    Widget build(BuildContext context) {
    return new GestureDetector(
      onLongPress: () {
        setState(() {
          selected = !selected;
        });
        widget.callback();
      },
      onTap: () {
        if (widget.longPressEnabled) {
          setState(() {
            selected = !selected;
          });
          widget.callback();
        }
      },
      child: new Container(
        margin: new EdgeInsets.all(5.0),
        child: new ListTile(
          title: new Text("Title ${widget.index}"),
          subtitle: new Text("Description ${widget.index}"),
        ),
        decoration: selected? new BoxDecoration(color: Colors.black38, border: new Border.all(color: Colors.black)): new BoxDecoration(),
      ),
    );
    }}