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

Viewed 2196

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(),
  ),
);
}}
1 Answers

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;
}
Related