Flutter - Multiselection ListView











up vote
1
down vote

favorite












In my app, I do have a list, on which I have implemented the long press selection of this post of Raouf Rahiche. When the selection is enabled I do have a different appbar, that has an IconButton on it, that should disable the selection. But I do not know how to do that.



Till now it is not working the way it should. The behaviour is displayed in the video below.
enter image description here



The longpress-selection is a StatefulWidget:



class _SelectableItems extends State<SelectableItems> {
bool isSelected = false;
GoogleMaterialColors googleMaterialColors = new GoogleMaterialColors();

@override
void initState() {
super.initState();
}

@override
Widget build(BuildContext context) {
return new GestureDetector(
onLongPress: () {
setState(() {
isSelected = !isSelected;
});
widget.callback();
},
onTap: () {
setState(() {
isSelected = !isSelected;
});
if (widget.longPressEnabled) {
widget.callback();
} else {
Navigator.push(
context,
MaterialPageRoute(builder: (context)=>RecipeDetails(widget.name))
);
}
},
child: ListTile(
leading: CircleAvatar(
child: (isSelected
? Icon(
Icons.check,
color: Colors.white,
)
: (widget.image != "no image"
? Container(
width: 40.0,
height: 40.0,
decoration: new BoxDecoration(
image: new DecorationImage(
colorFilter: ColorFilter.mode(Colors.black.withOpacity(0.2), BlendMode.darken),
image: AssetImage(widget.image),
fit: BoxFit.cover,
),
borderRadius: new BorderRadius.all(new Radius.circular(50.0)),
),
)
: Text(
widget.name[0].toUpperCase(),
style: TextStyle(
color: Colors.white,
fontSize: 21.0,
fontWeight: FontWeight.w400
),
)
)
),
backgroundColor: (isSelected
? googleMaterialColors.primaryColor()
: widget.color.withOpacity(1.00)
)
),
title: Padding(
padding: EdgeInsets.only(top: 25.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
widget.title
],
),
),
),
);
}
}


I am calling this widget inside a SideHeaderListView like this:



bool longPressFlag = false;
List<String> indexList = new List();
//other code

return SideHeaderListView(
hasSameHeader: (int a, int b){
return snapshot.data[a].name[0] == snapshot.data[b].name[0];
},
itemCount: snapshot.data.length,
headerBuilder: (BuildContext context, int index){
return new Padding(
padding: EdgeInsets.only(top: 30.0, left: 20.0, right: 25.0),
child: Container(
width: 10.0,
child: Text(
snapshot.data[index].name[0].toUpperCase(),
style: TextStyle(
color: googleMaterialColors.primaryColor().withGreen(120),
fontFamily: "Google-Sans",
fontSize: 15.0,
fontWeight: FontWeight.w600
),
),
),
);
},
itemExtend: 70.0,
itemBuilder: (BuildContext context, int index){

Color usedColor = convertColor.convertToColor(snapshot.data[index].backgroundColor);
String image = snapshot.data[index].image;


return SelectableItems(
color: usedColor,
name: snapshot.data[index].name,
title: (searchController.text.isEmpty
? Text(snapshot.data[index].name)
: recipeName(searchCondition, snapshot.data[index].name)
),
index: index,
image: image,
longPressEnabled: longPressFlag,
//isSelected: selectedFlag,
callback: () {
if (indexList.contains(snapshot.data[index].name)) {
indexList.remove(snapshot.data[index].name);
} else {
indexList.add(snapshot.data[index].name);
}
longPress();
},
);
},
);

void longPress() {
setState(() {
if (indexList.length == 0) {
longPressFlag = false;
} else {
longPressFlag = true;
}
});
}


I hope somebody would be able to solve my problem. Thanks in advance.










share|improve this question
























  • You want the "X" IconButton to deselect all selections and close the contextual app bar?
    – Jacob Phillips
    Nov 11 at 6:06










  • That's exactly what it should do.
    – Stnieder
    Nov 11 at 9:59










  • And for now when you press "X" - it hides appbar, but selected items stay without changes - am I correct?
    – Andrey Turkovsky
    Nov 11 at 11:27










  • You are right with that
    – Stnieder
    Nov 11 at 12:59















up vote
1
down vote

favorite












In my app, I do have a list, on which I have implemented the long press selection of this post of Raouf Rahiche. When the selection is enabled I do have a different appbar, that has an IconButton on it, that should disable the selection. But I do not know how to do that.



Till now it is not working the way it should. The behaviour is displayed in the video below.
enter image description here



The longpress-selection is a StatefulWidget:



class _SelectableItems extends State<SelectableItems> {
bool isSelected = false;
GoogleMaterialColors googleMaterialColors = new GoogleMaterialColors();

@override
void initState() {
super.initState();
}

@override
Widget build(BuildContext context) {
return new GestureDetector(
onLongPress: () {
setState(() {
isSelected = !isSelected;
});
widget.callback();
},
onTap: () {
setState(() {
isSelected = !isSelected;
});
if (widget.longPressEnabled) {
widget.callback();
} else {
Navigator.push(
context,
MaterialPageRoute(builder: (context)=>RecipeDetails(widget.name))
);
}
},
child: ListTile(
leading: CircleAvatar(
child: (isSelected
? Icon(
Icons.check,
color: Colors.white,
)
: (widget.image != "no image"
? Container(
width: 40.0,
height: 40.0,
decoration: new BoxDecoration(
image: new DecorationImage(
colorFilter: ColorFilter.mode(Colors.black.withOpacity(0.2), BlendMode.darken),
image: AssetImage(widget.image),
fit: BoxFit.cover,
),
borderRadius: new BorderRadius.all(new Radius.circular(50.0)),
),
)
: Text(
widget.name[0].toUpperCase(),
style: TextStyle(
color: Colors.white,
fontSize: 21.0,
fontWeight: FontWeight.w400
),
)
)
),
backgroundColor: (isSelected
? googleMaterialColors.primaryColor()
: widget.color.withOpacity(1.00)
)
),
title: Padding(
padding: EdgeInsets.only(top: 25.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
widget.title
],
),
),
),
);
}
}


I am calling this widget inside a SideHeaderListView like this:



bool longPressFlag = false;
List<String> indexList = new List();
//other code

return SideHeaderListView(
hasSameHeader: (int a, int b){
return snapshot.data[a].name[0] == snapshot.data[b].name[0];
},
itemCount: snapshot.data.length,
headerBuilder: (BuildContext context, int index){
return new Padding(
padding: EdgeInsets.only(top: 30.0, left: 20.0, right: 25.0),
child: Container(
width: 10.0,
child: Text(
snapshot.data[index].name[0].toUpperCase(),
style: TextStyle(
color: googleMaterialColors.primaryColor().withGreen(120),
fontFamily: "Google-Sans",
fontSize: 15.0,
fontWeight: FontWeight.w600
),
),
),
);
},
itemExtend: 70.0,
itemBuilder: (BuildContext context, int index){

Color usedColor = convertColor.convertToColor(snapshot.data[index].backgroundColor);
String image = snapshot.data[index].image;


return SelectableItems(
color: usedColor,
name: snapshot.data[index].name,
title: (searchController.text.isEmpty
? Text(snapshot.data[index].name)
: recipeName(searchCondition, snapshot.data[index].name)
),
index: index,
image: image,
longPressEnabled: longPressFlag,
//isSelected: selectedFlag,
callback: () {
if (indexList.contains(snapshot.data[index].name)) {
indexList.remove(snapshot.data[index].name);
} else {
indexList.add(snapshot.data[index].name);
}
longPress();
},
);
},
);

void longPress() {
setState(() {
if (indexList.length == 0) {
longPressFlag = false;
} else {
longPressFlag = true;
}
});
}


I hope somebody would be able to solve my problem. Thanks in advance.










share|improve this question
























  • You want the "X" IconButton to deselect all selections and close the contextual app bar?
    – Jacob Phillips
    Nov 11 at 6:06










  • That's exactly what it should do.
    – Stnieder
    Nov 11 at 9:59










  • And for now when you press "X" - it hides appbar, but selected items stay without changes - am I correct?
    – Andrey Turkovsky
    Nov 11 at 11:27










  • You are right with that
    – Stnieder
    Nov 11 at 12:59













up vote
1
down vote

favorite









up vote
1
down vote

favorite











In my app, I do have a list, on which I have implemented the long press selection of this post of Raouf Rahiche. When the selection is enabled I do have a different appbar, that has an IconButton on it, that should disable the selection. But I do not know how to do that.



Till now it is not working the way it should. The behaviour is displayed in the video below.
enter image description here



The longpress-selection is a StatefulWidget:



class _SelectableItems extends State<SelectableItems> {
bool isSelected = false;
GoogleMaterialColors googleMaterialColors = new GoogleMaterialColors();

@override
void initState() {
super.initState();
}

@override
Widget build(BuildContext context) {
return new GestureDetector(
onLongPress: () {
setState(() {
isSelected = !isSelected;
});
widget.callback();
},
onTap: () {
setState(() {
isSelected = !isSelected;
});
if (widget.longPressEnabled) {
widget.callback();
} else {
Navigator.push(
context,
MaterialPageRoute(builder: (context)=>RecipeDetails(widget.name))
);
}
},
child: ListTile(
leading: CircleAvatar(
child: (isSelected
? Icon(
Icons.check,
color: Colors.white,
)
: (widget.image != "no image"
? Container(
width: 40.0,
height: 40.0,
decoration: new BoxDecoration(
image: new DecorationImage(
colorFilter: ColorFilter.mode(Colors.black.withOpacity(0.2), BlendMode.darken),
image: AssetImage(widget.image),
fit: BoxFit.cover,
),
borderRadius: new BorderRadius.all(new Radius.circular(50.0)),
),
)
: Text(
widget.name[0].toUpperCase(),
style: TextStyle(
color: Colors.white,
fontSize: 21.0,
fontWeight: FontWeight.w400
),
)
)
),
backgroundColor: (isSelected
? googleMaterialColors.primaryColor()
: widget.color.withOpacity(1.00)
)
),
title: Padding(
padding: EdgeInsets.only(top: 25.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
widget.title
],
),
),
),
);
}
}


I am calling this widget inside a SideHeaderListView like this:



bool longPressFlag = false;
List<String> indexList = new List();
//other code

return SideHeaderListView(
hasSameHeader: (int a, int b){
return snapshot.data[a].name[0] == snapshot.data[b].name[0];
},
itemCount: snapshot.data.length,
headerBuilder: (BuildContext context, int index){
return new Padding(
padding: EdgeInsets.only(top: 30.0, left: 20.0, right: 25.0),
child: Container(
width: 10.0,
child: Text(
snapshot.data[index].name[0].toUpperCase(),
style: TextStyle(
color: googleMaterialColors.primaryColor().withGreen(120),
fontFamily: "Google-Sans",
fontSize: 15.0,
fontWeight: FontWeight.w600
),
),
),
);
},
itemExtend: 70.0,
itemBuilder: (BuildContext context, int index){

Color usedColor = convertColor.convertToColor(snapshot.data[index].backgroundColor);
String image = snapshot.data[index].image;


return SelectableItems(
color: usedColor,
name: snapshot.data[index].name,
title: (searchController.text.isEmpty
? Text(snapshot.data[index].name)
: recipeName(searchCondition, snapshot.data[index].name)
),
index: index,
image: image,
longPressEnabled: longPressFlag,
//isSelected: selectedFlag,
callback: () {
if (indexList.contains(snapshot.data[index].name)) {
indexList.remove(snapshot.data[index].name);
} else {
indexList.add(snapshot.data[index].name);
}
longPress();
},
);
},
);

void longPress() {
setState(() {
if (indexList.length == 0) {
longPressFlag = false;
} else {
longPressFlag = true;
}
});
}


I hope somebody would be able to solve my problem. Thanks in advance.










share|improve this question















In my app, I do have a list, on which I have implemented the long press selection of this post of Raouf Rahiche. When the selection is enabled I do have a different appbar, that has an IconButton on it, that should disable the selection. But I do not know how to do that.



Till now it is not working the way it should. The behaviour is displayed in the video below.
enter image description here



The longpress-selection is a StatefulWidget:



class _SelectableItems extends State<SelectableItems> {
bool isSelected = false;
GoogleMaterialColors googleMaterialColors = new GoogleMaterialColors();

@override
void initState() {
super.initState();
}

@override
Widget build(BuildContext context) {
return new GestureDetector(
onLongPress: () {
setState(() {
isSelected = !isSelected;
});
widget.callback();
},
onTap: () {
setState(() {
isSelected = !isSelected;
});
if (widget.longPressEnabled) {
widget.callback();
} else {
Navigator.push(
context,
MaterialPageRoute(builder: (context)=>RecipeDetails(widget.name))
);
}
},
child: ListTile(
leading: CircleAvatar(
child: (isSelected
? Icon(
Icons.check,
color: Colors.white,
)
: (widget.image != "no image"
? Container(
width: 40.0,
height: 40.0,
decoration: new BoxDecoration(
image: new DecorationImage(
colorFilter: ColorFilter.mode(Colors.black.withOpacity(0.2), BlendMode.darken),
image: AssetImage(widget.image),
fit: BoxFit.cover,
),
borderRadius: new BorderRadius.all(new Radius.circular(50.0)),
),
)
: Text(
widget.name[0].toUpperCase(),
style: TextStyle(
color: Colors.white,
fontSize: 21.0,
fontWeight: FontWeight.w400
),
)
)
),
backgroundColor: (isSelected
? googleMaterialColors.primaryColor()
: widget.color.withOpacity(1.00)
)
),
title: Padding(
padding: EdgeInsets.only(top: 25.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
widget.title
],
),
),
),
);
}
}


I am calling this widget inside a SideHeaderListView like this:



bool longPressFlag = false;
List<String> indexList = new List();
//other code

return SideHeaderListView(
hasSameHeader: (int a, int b){
return snapshot.data[a].name[0] == snapshot.data[b].name[0];
},
itemCount: snapshot.data.length,
headerBuilder: (BuildContext context, int index){
return new Padding(
padding: EdgeInsets.only(top: 30.0, left: 20.0, right: 25.0),
child: Container(
width: 10.0,
child: Text(
snapshot.data[index].name[0].toUpperCase(),
style: TextStyle(
color: googleMaterialColors.primaryColor().withGreen(120),
fontFamily: "Google-Sans",
fontSize: 15.0,
fontWeight: FontWeight.w600
),
),
),
);
},
itemExtend: 70.0,
itemBuilder: (BuildContext context, int index){

Color usedColor = convertColor.convertToColor(snapshot.data[index].backgroundColor);
String image = snapshot.data[index].image;


return SelectableItems(
color: usedColor,
name: snapshot.data[index].name,
title: (searchController.text.isEmpty
? Text(snapshot.data[index].name)
: recipeName(searchCondition, snapshot.data[index].name)
),
index: index,
image: image,
longPressEnabled: longPressFlag,
//isSelected: selectedFlag,
callback: () {
if (indexList.contains(snapshot.data[index].name)) {
indexList.remove(snapshot.data[index].name);
} else {
indexList.add(snapshot.data[index].name);
}
longPress();
},
);
},
);

void longPress() {
setState(() {
if (indexList.length == 0) {
longPressFlag = false;
} else {
longPressFlag = true;
}
});
}


I hope somebody would be able to solve my problem. Thanks in advance.







android ios dart flutter






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 8 at 15:47









André Sousa

1,1271818




1,1271818










asked Nov 8 at 15:25









Stnieder

6212




6212












  • You want the "X" IconButton to deselect all selections and close the contextual app bar?
    – Jacob Phillips
    Nov 11 at 6:06










  • That's exactly what it should do.
    – Stnieder
    Nov 11 at 9:59










  • And for now when you press "X" - it hides appbar, but selected items stay without changes - am I correct?
    – Andrey Turkovsky
    Nov 11 at 11:27










  • You are right with that
    – Stnieder
    Nov 11 at 12:59


















  • You want the "X" IconButton to deselect all selections and close the contextual app bar?
    – Jacob Phillips
    Nov 11 at 6:06










  • That's exactly what it should do.
    – Stnieder
    Nov 11 at 9:59










  • And for now when you press "X" - it hides appbar, but selected items stay without changes - am I correct?
    – Andrey Turkovsky
    Nov 11 at 11:27










  • You are right with that
    – Stnieder
    Nov 11 at 12:59
















You want the "X" IconButton to deselect all selections and close the contextual app bar?
– Jacob Phillips
Nov 11 at 6:06




You want the "X" IconButton to deselect all selections and close the contextual app bar?
– Jacob Phillips
Nov 11 at 6:06












That's exactly what it should do.
– Stnieder
Nov 11 at 9:59




That's exactly what it should do.
– Stnieder
Nov 11 at 9:59












And for now when you press "X" - it hides appbar, but selected items stay without changes - am I correct?
– Andrey Turkovsky
Nov 11 at 11:27




And for now when you press "X" - it hides appbar, but selected items stay without changes - am I correct?
– Andrey Turkovsky
Nov 11 at 11:27












You are right with that
– Stnieder
Nov 11 at 12:59




You are right with that
– Stnieder
Nov 11 at 12:59












2 Answers
2






active

oldest

votes

















up vote
1
down vote



accepted
+50










The first thing is that you should add each item a key in constructor like this :



MyItem({Key key}): super(key: key);


Why a key ?
A key allow you to identify your widget correctly.
See in doc :




A new widget will only be used to update an existing element if its
key is the same as the key of the current widget associated with the
element.




Create a GlobalKey (a GLobal key extends Key)
For each item to access the widget from, create a global key.
From the doc :




A key that is unique across the entire app. Global keys uniquely
identify elements. Global keys provide access to other objects that
are associated with elements, such as the a [BuildContext] and, for
[StatefulWidget]s, a [State].




Add in the code the creation of a global key for each item (in your SelectableItem for you) :



...
var key = new GlobalKey<SelectableItem >();
this.items.put(position, key);
return new SelectableItem(key: key,...);


Items is a map where you can save position and Global Key.
Now when you want to select a View from the parent just access the globalKey from the map of items and access the widget to do what you want.(update, uncheck, etc...)



Edit : exemple :



class SideHeaderListView  {

Map<int, GlobalKey<_SelectableItems>> map = new Map();

create() {
for (int i = 0; i< 10; i++) {
var key = new GlobalKey<_SelectableItems>();
var item = new SelectableItems(key: key);
map.putIfAbsent(i, () => key);
}
}

redrawItem(int i) {
var widget = this.map[i].currentState;
widget.redraw();
}
}

class SelectableItems extends StatefulWidget {

SelectableItems({key: Key}) : super(key: key);

@override
State<StatefulWidget> createState() {
return new _SelectableItems();
}
}

class _SelectableItems extends State<SelectableItems> {

@override
Widget build(BuildContext context) {
return new Text("test");
}

redraw() {
setState(() {

});
}

}





share|improve this answer























  • Do I have to create a map, that is named items like this: Map<int,GlobalKey> items = new Map(); ?
    – Stnieder
    Nov 11 at 14:29










  • yes, that's it exactly.
    – mcfly
    Nov 11 at 14:43










  • Do I have to create that inside the SelectableItems class?
    – Stnieder
    Nov 11 at 14:47










  • No, create it in SideHeaderListView where you create your items. This is where you want to be able to call each items to reset them or else.
    – mcfly
    Nov 11 at 14:50










  • When I try to create that map, it throws always an error: SelectableItems doesn't extend 'State<StatefulWidget>'
    – Stnieder
    Nov 11 at 14:50


















up vote
1
down vote













You have commented part of code - //isSelected: selectedFlag,
I think, you have to add this field to your widget



class SelectableItems extands StatefulWidget {
SelectableItems({this.isSelected = false});
final bool isSelected;
...

class _SelectableItems extends State<SelectableItems> {
bool isSelected;

@override
void initState() {
isSelected = widget.isSelected ?? false;
super.initState();
}
....


And when you're creating list of items:



return SelectableItems(
...
isSelected: indexList.contains(snapshot.data[index].name)


I think this could work






share|improve this answer





















    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53210904%2fflutter-multiselection-listview%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes








    up vote
    1
    down vote



    accepted
    +50










    The first thing is that you should add each item a key in constructor like this :



    MyItem({Key key}): super(key: key);


    Why a key ?
    A key allow you to identify your widget correctly.
    See in doc :




    A new widget will only be used to update an existing element if its
    key is the same as the key of the current widget associated with the
    element.




    Create a GlobalKey (a GLobal key extends Key)
    For each item to access the widget from, create a global key.
    From the doc :




    A key that is unique across the entire app. Global keys uniquely
    identify elements. Global keys provide access to other objects that
    are associated with elements, such as the a [BuildContext] and, for
    [StatefulWidget]s, a [State].




    Add in the code the creation of a global key for each item (in your SelectableItem for you) :



    ...
    var key = new GlobalKey<SelectableItem >();
    this.items.put(position, key);
    return new SelectableItem(key: key,...);


    Items is a map where you can save position and Global Key.
    Now when you want to select a View from the parent just access the globalKey from the map of items and access the widget to do what you want.(update, uncheck, etc...)



    Edit : exemple :



    class SideHeaderListView  {

    Map<int, GlobalKey<_SelectableItems>> map = new Map();

    create() {
    for (int i = 0; i< 10; i++) {
    var key = new GlobalKey<_SelectableItems>();
    var item = new SelectableItems(key: key);
    map.putIfAbsent(i, () => key);
    }
    }

    redrawItem(int i) {
    var widget = this.map[i].currentState;
    widget.redraw();
    }
    }

    class SelectableItems extends StatefulWidget {

    SelectableItems({key: Key}) : super(key: key);

    @override
    State<StatefulWidget> createState() {
    return new _SelectableItems();
    }
    }

    class _SelectableItems extends State<SelectableItems> {

    @override
    Widget build(BuildContext context) {
    return new Text("test");
    }

    redraw() {
    setState(() {

    });
    }

    }





    share|improve this answer























    • Do I have to create a map, that is named items like this: Map<int,GlobalKey> items = new Map(); ?
      – Stnieder
      Nov 11 at 14:29










    • yes, that's it exactly.
      – mcfly
      Nov 11 at 14:43










    • Do I have to create that inside the SelectableItems class?
      – Stnieder
      Nov 11 at 14:47










    • No, create it in SideHeaderListView where you create your items. This is where you want to be able to call each items to reset them or else.
      – mcfly
      Nov 11 at 14:50










    • When I try to create that map, it throws always an error: SelectableItems doesn't extend 'State<StatefulWidget>'
      – Stnieder
      Nov 11 at 14:50















    up vote
    1
    down vote



    accepted
    +50










    The first thing is that you should add each item a key in constructor like this :



    MyItem({Key key}): super(key: key);


    Why a key ?
    A key allow you to identify your widget correctly.
    See in doc :




    A new widget will only be used to update an existing element if its
    key is the same as the key of the current widget associated with the
    element.




    Create a GlobalKey (a GLobal key extends Key)
    For each item to access the widget from, create a global key.
    From the doc :




    A key that is unique across the entire app. Global keys uniquely
    identify elements. Global keys provide access to other objects that
    are associated with elements, such as the a [BuildContext] and, for
    [StatefulWidget]s, a [State].




    Add in the code the creation of a global key for each item (in your SelectableItem for you) :



    ...
    var key = new GlobalKey<SelectableItem >();
    this.items.put(position, key);
    return new SelectableItem(key: key,...);


    Items is a map where you can save position and Global Key.
    Now when you want to select a View from the parent just access the globalKey from the map of items and access the widget to do what you want.(update, uncheck, etc...)



    Edit : exemple :



    class SideHeaderListView  {

    Map<int, GlobalKey<_SelectableItems>> map = new Map();

    create() {
    for (int i = 0; i< 10; i++) {
    var key = new GlobalKey<_SelectableItems>();
    var item = new SelectableItems(key: key);
    map.putIfAbsent(i, () => key);
    }
    }

    redrawItem(int i) {
    var widget = this.map[i].currentState;
    widget.redraw();
    }
    }

    class SelectableItems extends StatefulWidget {

    SelectableItems({key: Key}) : super(key: key);

    @override
    State<StatefulWidget> createState() {
    return new _SelectableItems();
    }
    }

    class _SelectableItems extends State<SelectableItems> {

    @override
    Widget build(BuildContext context) {
    return new Text("test");
    }

    redraw() {
    setState(() {

    });
    }

    }





    share|improve this answer























    • Do I have to create a map, that is named items like this: Map<int,GlobalKey> items = new Map(); ?
      – Stnieder
      Nov 11 at 14:29










    • yes, that's it exactly.
      – mcfly
      Nov 11 at 14:43










    • Do I have to create that inside the SelectableItems class?
      – Stnieder
      Nov 11 at 14:47










    • No, create it in SideHeaderListView where you create your items. This is where you want to be able to call each items to reset them or else.
      – mcfly
      Nov 11 at 14:50










    • When I try to create that map, it throws always an error: SelectableItems doesn't extend 'State<StatefulWidget>'
      – Stnieder
      Nov 11 at 14:50













    up vote
    1
    down vote



    accepted
    +50







    up vote
    1
    down vote



    accepted
    +50




    +50




    The first thing is that you should add each item a key in constructor like this :



    MyItem({Key key}): super(key: key);


    Why a key ?
    A key allow you to identify your widget correctly.
    See in doc :




    A new widget will only be used to update an existing element if its
    key is the same as the key of the current widget associated with the
    element.




    Create a GlobalKey (a GLobal key extends Key)
    For each item to access the widget from, create a global key.
    From the doc :




    A key that is unique across the entire app. Global keys uniquely
    identify elements. Global keys provide access to other objects that
    are associated with elements, such as the a [BuildContext] and, for
    [StatefulWidget]s, a [State].




    Add in the code the creation of a global key for each item (in your SelectableItem for you) :



    ...
    var key = new GlobalKey<SelectableItem >();
    this.items.put(position, key);
    return new SelectableItem(key: key,...);


    Items is a map where you can save position and Global Key.
    Now when you want to select a View from the parent just access the globalKey from the map of items and access the widget to do what you want.(update, uncheck, etc...)



    Edit : exemple :



    class SideHeaderListView  {

    Map<int, GlobalKey<_SelectableItems>> map = new Map();

    create() {
    for (int i = 0; i< 10; i++) {
    var key = new GlobalKey<_SelectableItems>();
    var item = new SelectableItems(key: key);
    map.putIfAbsent(i, () => key);
    }
    }

    redrawItem(int i) {
    var widget = this.map[i].currentState;
    widget.redraw();
    }
    }

    class SelectableItems extends StatefulWidget {

    SelectableItems({key: Key}) : super(key: key);

    @override
    State<StatefulWidget> createState() {
    return new _SelectableItems();
    }
    }

    class _SelectableItems extends State<SelectableItems> {

    @override
    Widget build(BuildContext context) {
    return new Text("test");
    }

    redraw() {
    setState(() {

    });
    }

    }





    share|improve this answer














    The first thing is that you should add each item a key in constructor like this :



    MyItem({Key key}): super(key: key);


    Why a key ?
    A key allow you to identify your widget correctly.
    See in doc :




    A new widget will only be used to update an existing element if its
    key is the same as the key of the current widget associated with the
    element.




    Create a GlobalKey (a GLobal key extends Key)
    For each item to access the widget from, create a global key.
    From the doc :




    A key that is unique across the entire app. Global keys uniquely
    identify elements. Global keys provide access to other objects that
    are associated with elements, such as the a [BuildContext] and, for
    [StatefulWidget]s, a [State].




    Add in the code the creation of a global key for each item (in your SelectableItem for you) :



    ...
    var key = new GlobalKey<SelectableItem >();
    this.items.put(position, key);
    return new SelectableItem(key: key,...);


    Items is a map where you can save position and Global Key.
    Now when you want to select a View from the parent just access the globalKey from the map of items and access the widget to do what you want.(update, uncheck, etc...)



    Edit : exemple :



    class SideHeaderListView  {

    Map<int, GlobalKey<_SelectableItems>> map = new Map();

    create() {
    for (int i = 0; i< 10; i++) {
    var key = new GlobalKey<_SelectableItems>();
    var item = new SelectableItems(key: key);
    map.putIfAbsent(i, () => key);
    }
    }

    redrawItem(int i) {
    var widget = this.map[i].currentState;
    widget.redraw();
    }
    }

    class SelectableItems extends StatefulWidget {

    SelectableItems({key: Key}) : super(key: key);

    @override
    State<StatefulWidget> createState() {
    return new _SelectableItems();
    }
    }

    class _SelectableItems extends State<SelectableItems> {

    @override
    Widget build(BuildContext context) {
    return new Text("test");
    }

    redraw() {
    setState(() {

    });
    }

    }






    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Nov 11 at 15:08

























    answered Nov 11 at 13:29









    mcfly

    298211




    298211












    • Do I have to create a map, that is named items like this: Map<int,GlobalKey> items = new Map(); ?
      – Stnieder
      Nov 11 at 14:29










    • yes, that's it exactly.
      – mcfly
      Nov 11 at 14:43










    • Do I have to create that inside the SelectableItems class?
      – Stnieder
      Nov 11 at 14:47










    • No, create it in SideHeaderListView where you create your items. This is where you want to be able to call each items to reset them or else.
      – mcfly
      Nov 11 at 14:50










    • When I try to create that map, it throws always an error: SelectableItems doesn't extend 'State<StatefulWidget>'
      – Stnieder
      Nov 11 at 14:50


















    • Do I have to create a map, that is named items like this: Map<int,GlobalKey> items = new Map(); ?
      – Stnieder
      Nov 11 at 14:29










    • yes, that's it exactly.
      – mcfly
      Nov 11 at 14:43










    • Do I have to create that inside the SelectableItems class?
      – Stnieder
      Nov 11 at 14:47










    • No, create it in SideHeaderListView where you create your items. This is where you want to be able to call each items to reset them or else.
      – mcfly
      Nov 11 at 14:50










    • When I try to create that map, it throws always an error: SelectableItems doesn't extend 'State<StatefulWidget>'
      – Stnieder
      Nov 11 at 14:50
















    Do I have to create a map, that is named items like this: Map<int,GlobalKey> items = new Map(); ?
    – Stnieder
    Nov 11 at 14:29




    Do I have to create a map, that is named items like this: Map<int,GlobalKey> items = new Map(); ?
    – Stnieder
    Nov 11 at 14:29












    yes, that's it exactly.
    – mcfly
    Nov 11 at 14:43




    yes, that's it exactly.
    – mcfly
    Nov 11 at 14:43












    Do I have to create that inside the SelectableItems class?
    – Stnieder
    Nov 11 at 14:47




    Do I have to create that inside the SelectableItems class?
    – Stnieder
    Nov 11 at 14:47












    No, create it in SideHeaderListView where you create your items. This is where you want to be able to call each items to reset them or else.
    – mcfly
    Nov 11 at 14:50




    No, create it in SideHeaderListView where you create your items. This is where you want to be able to call each items to reset them or else.
    – mcfly
    Nov 11 at 14:50












    When I try to create that map, it throws always an error: SelectableItems doesn't extend 'State<StatefulWidget>'
    – Stnieder
    Nov 11 at 14:50




    When I try to create that map, it throws always an error: SelectableItems doesn't extend 'State<StatefulWidget>'
    – Stnieder
    Nov 11 at 14:50












    up vote
    1
    down vote













    You have commented part of code - //isSelected: selectedFlag,
    I think, you have to add this field to your widget



    class SelectableItems extands StatefulWidget {
    SelectableItems({this.isSelected = false});
    final bool isSelected;
    ...

    class _SelectableItems extends State<SelectableItems> {
    bool isSelected;

    @override
    void initState() {
    isSelected = widget.isSelected ?? false;
    super.initState();
    }
    ....


    And when you're creating list of items:



    return SelectableItems(
    ...
    isSelected: indexList.contains(snapshot.data[index].name)


    I think this could work






    share|improve this answer

























      up vote
      1
      down vote













      You have commented part of code - //isSelected: selectedFlag,
      I think, you have to add this field to your widget



      class SelectableItems extands StatefulWidget {
      SelectableItems({this.isSelected = false});
      final bool isSelected;
      ...

      class _SelectableItems extends State<SelectableItems> {
      bool isSelected;

      @override
      void initState() {
      isSelected = widget.isSelected ?? false;
      super.initState();
      }
      ....


      And when you're creating list of items:



      return SelectableItems(
      ...
      isSelected: indexList.contains(snapshot.data[index].name)


      I think this could work






      share|improve this answer























        up vote
        1
        down vote










        up vote
        1
        down vote









        You have commented part of code - //isSelected: selectedFlag,
        I think, you have to add this field to your widget



        class SelectableItems extands StatefulWidget {
        SelectableItems({this.isSelected = false});
        final bool isSelected;
        ...

        class _SelectableItems extends State<SelectableItems> {
        bool isSelected;

        @override
        void initState() {
        isSelected = widget.isSelected ?? false;
        super.initState();
        }
        ....


        And when you're creating list of items:



        return SelectableItems(
        ...
        isSelected: indexList.contains(snapshot.data[index].name)


        I think this could work






        share|improve this answer












        You have commented part of code - //isSelected: selectedFlag,
        I think, you have to add this field to your widget



        class SelectableItems extands StatefulWidget {
        SelectableItems({this.isSelected = false});
        final bool isSelected;
        ...

        class _SelectableItems extends State<SelectableItems> {
        bool isSelected;

        @override
        void initState() {
        isSelected = widget.isSelected ?? false;
        super.initState();
        }
        ....


        And when you're creating list of items:



        return SelectableItems(
        ...
        isSelected: indexList.contains(snapshot.data[index].name)


        I think this could work







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Nov 11 at 13:54









        Andrey Turkovsky

        1,6011617




        1,6011617






























            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.





            Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


            Please pay close attention to the following guidance:


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53210904%2fflutter-multiselection-listview%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            The Sandy Post

            Danny Elfman

            Pages that link to "Head v. Amoskeag Manufacturing Co."