How store list of String with sharedPreferences in Flutter? - list

How can I store the list with sharedPreferences and use it in the ListView?
this is my shared preferences codeand this is my list view
this is my code:
late SharedPreferences _prefs;
#override
void initState() {
super.initState();
SharedPreferences.getInstance().then((prefs) {
setState(() => _prefs = prefs);
});
}
_saveList(List<String> list) {
_prefs.setStringList('key', list);
print('$_prefs');
}
List _fetchList() {
print('$_prefs');
return _prefs.getStringList('key') ?? [];
}
Widget build(BuildContext context) {
_saveList(list);
return MaterialApp(
title: 'Errori',
home: Scaffold(
appBar: AppBar(
title: const Text('Report Errori'),
),
body: Container(
child: Column(
children: <Widget>[
Expanded(
child: ListView.builder(
shrinkWrap: true,
itemCount: _fetchList().length,
itemBuilder: (context, index) => Container(
child: Material(
borderRadius: BorderRadius.circular(5.0),
child: Center(
child: Text(_fetchList()[index]),
),
))))
],
),
),
),
);
I don't think what I did is correct. I keep having the problem that when I restart the app, the items disappear

To store list of string you can use the following:
List<String> stringsList= ['Alex', 'Mob', 'Flutter'];
final SharedPreferences prefs = await SharedPreferences.getInstance();
// store your string list in shared prefs
prefs.setStringList("stringList", stringsList);
To retrieve list of string you can use the following:
final SharedPreferences prefs = await SharedPreferences.getInstance();
List<String> myStringList = (prefs.getStringList('stringList') ?? List<String>());

The answer to your question is here to save a list of objects to sharedpreferences and you can recall them in the commented place below:
itemBuilder(_,_){
//Recall the listview method
return yourWidget;}

Related

_TypeError (type 'Null' is not a subtype of type 'List<String>' of 'function result')

I'm trying to generate a 300 list like this:
import 'package:flutter/material.dart';
void main() {
runApp(new MaterialApp(
title: "Zulfa Application",
home: new Home(data: new List<String>.generate(300,(i)=>"Ini data ke $i"),),
));
}
class Home extends StatelessWidget {
final List<String> data;
Home({required this.data});
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar : new AppBar(
backgroundColor: Colors.purpleAccent,
title: new Text("Zulfalogy Content"),
),
body: new Container(
child: new ListView.builder(
itemCount: data.length,
itemBuilder: (context, index){
return new ListTile(
leading: new Icon(Icons.widgets),
title: new Text("${data[index]}"),
);
}
),
),
);
}
}
And it thrown an error like this:
_TypeError (type 'Null' is not a subtype of type 'List<String>' of 'function result')
I didnt know how its going. i just following some tutorial and it still error. Hope u guys can help me to solve this:)
I have been copying your code as you post it and it worked fine for me
could you share your flutter version. or try to upgrade your flutter sdk.
or try to copy this >>
import 'package:flutter/material.dart';
void main() {
runApp(new MaterialApp(
title: "Zulfa Application",
home: Home(data: List.generate(300,(i)=>"Ini data ke $i"),),
));
}
class Home extends StatelessWidget {
final List? data;
Home({ this.data});
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar : new AppBar(
backgroundColor: Colors.purpleAccent,
title: new Text("Zulfalogy Content"),
),
body: new Container(
child: new ListView.builder(
itemCount: data!.length,
itemBuilder: (context, index){
return new ListTile(
leading: new Icon(Icons.widgets),
title: new Text("${data![index]}"),
);
}
),
),
);
}
}

How to avoid overwriting a List Item when using the same name?

In my project the user can add and edit List Items. The Problem is, that if the user add a List item with an already existing List name, the old one gets overwritten, with the error 'Multiple widgets used the same GlobalKey'. How can I avoid that, so that the user can add multiple items with the same name?
import 'package:flutter/material.dart';
class PlanOverview extends StatefulWidget {
const PlanOverview({Key key}) : super(key: key);
#override
_PlanOverviewState createState() => _PlanOverviewState();
}
class _PlanOverviewState extends State<PlanOverview> {
List<String> plans = ['Plan A', 'Plan B'];
void addPlan(String newPlan) {
setState(() {
plans.add(newPlan);
});
Navigator.of(context).pop();
}
void newEntry() {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
content: TextField(
onSubmitted: addPlan,
decoration: InputDecoration(
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10)),
icon: Icon(Icons.text_snippet_outlined),
labelText: 'Name des Plans'),
),
);
});
}
void edit(int i) => showDialog(
context: context,
builder: (context) {
final plan = plans[i];
return AlertDialog(
content: TextFormField(
decoration: InputDecoration(
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10)),
icon: Icon(Icons.text_snippet_outlined)),
initialValue: plan,
onFieldSubmitted: (_) => Navigator.of(context).pop(),
onChanged: (name) => setState(
() {
plans[i] = name;
},
)));
});
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Trainingspläne'),
shape: RoundedRectangleBorder(
borderRadius:
BorderRadius.only(bottomLeft: Radius.circular(10.0), bottomRight: Radius.circular(10.0)),
),
actions: [
IconButton(
onPressed: newEntry,
icon: Icon(Icons.add),
),
],
),
body: ReorderableListView.builder(
itemCount: plans.length,
onReorder: (oldi, newi) => setState(() {
final i = newi > oldi ? newi - 1 : newi;
final plan = plans.removeAt(oldi);
plans.insert(i, plan);
}),
itemBuilder: (context, i) {
final plan = plans[i];
return ListTile(
tileColor: Color.fromARGB(255, 34, 34, 34),
key: ValueKey(plan),
contentPadding: EdgeInsets.symmetric(horizontal: 20, vertical: 5),
title: Text(plans[i]),
onTap: () {
Navigator.push<Widget>(
context,
MaterialPageRoute(
builder: (context) =>
ExerciseTable(key: GlobalKey(), title: plans[i])));
},
trailing: IconButton(
icon: Icon(Icons.edit),
onPressed: () {
edit(i);
}),
);
}),
);
}
}
When the user creates an element and adds it to the list, you can check the list for an element with the same name and if it exists, add its index to its name this way there cant be two elements with the same name.
You dont need to show the index part of the name to the user if you dont want to, its just for control purposes.
If you have a search bar where the user types the name of the element he wants to access you can use auto complete to show the elements tht contains what the user is typing.

Flutter ListView delete Items not working

I have a ListView.builder with widgets and I would like to remove items from it but when I execute the Lines below nothing happens.
if (mounted) {
setState(() {
verlustContentList.removeLast();
});
}
This is how I generate the List:
generateList() async {
return verlustContentList = List.generate(
15,
(index) => VerlustContent(
key: Key(
index.toString(),
),
),
);
}
This is how I display the List:
StreamBuilder(
stream: generateList().asStream(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
return ListView.builder(
itemCount: verlustContentList.length,
itemBuilder: (context, index) {
return verlustContentList[index];
},
);
},
);
The Class VerlustContent is a Statefulwidget.
StreamBuilder listens to a stream you defined but you never push new data to that stream.
If you would print the list after the .removeLast(), it would really print the list without the last one.
I think you should remove the StreamBuilder because you can't even access that stream this way. Generate the list on initState() and show it in ListView. If generation does take some time, you can return a CircularProgressIndicator() if list is empty.
class MyStateful extends StatefulWidget {
#override
_MyStatefulState createState() => _MyStatefulState();
}
class _MyStatefulState extends State<MyStateful> {
List<Text> list= [];
#override
void initState() {
super.initState();
generateList();
}
void generateList() {
list = List.generate(
15,
(index) => Text(
index.toString()
),
);
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Center(
child: Column(
children: [
Container(
height: 300,
child: ListView.builder(
itemCount: list.length,
itemBuilder: (context, index) {
return list[index];
},
),
),
ElevatedButton(
onPressed: () {
if (mounted) {
setState(() {
list.removeLast();
print(list);
});
}
},
child: Text('deleteLast'),
),
],
),
),
),
);
}
}

When adding item to list in flutter, the item does not save in that list

I have a list of users which show in a dropdown in a form which is then submitted, the list is empty, I have made a function which allows users to type a "name" into a TextFormField and it then adds that name to the list, it then appears on the dropdown, but when the page is reloaded the list item has gone.
example:
void savePerson() {
String newperson = _newPersonController.text;
_persons.add(newperson);
}
The function to save string to list
List<String> _persons = [
];
The List
TextFormField(
controller: _newPersonController,
decoration: InputDecoration(
hintText: 'Add New Person',
prefixIcon: Icon(
Icons.local_hospital,
size: 30,
),
fillColor: Colors.white,
filled: true,
contentPadding: EdgeInsets.all(15),
)),
The TextFormField where the user inserts the name to be added
FlatButton(
onPressed: () {
savePerson();
setState(() {
_newPersonController.clear();
});
},
child: Text('Add Person'))
Button code
Just to be clear, it ADDS it to the list/dropdown - that works, but my list doesn't seem to be able to save info to it.
I'm fairly new to flutter - sorry for anything obvious.
The problem maybe the logic of the dropdown, and add the setState() when you add the item to the people list
I use this code:
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
final TextEditingController _newPersonController =
new TextEditingController();
List<String> _persons = [];
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Material App',
home: Scaffold(
appBar: AppBar(
title: Text('Material App Bar'),
),
body: Center(
child: Column(
children: <Widget>[
DropdownButton(
items: List.generate(
_persons.length,
(i) => DropdownMenuItem(
child: Text(_persons[i]),
)),
onChanged: (_) {}),
TextFormField(
controller: _newPersonController,
decoration: InputDecoration(
hintText: 'Add New Person',
prefixIcon: Icon(
Icons.local_hospital,
size: 30,
),
fillColor: Colors.white,
filled: true,
contentPadding: EdgeInsets.all(15),
)),
FlatButton(
onPressed: () {
savePerson();
setState(() {
_newPersonController.clear();
});
},
child: Text('Add Person'))
],
),
),
),
);
}
void savePerson() {
String newperson = _newPersonController.text;
setState(() {
_persons.add(newperson);
});
}
}
Probably can help you

Dart, Flutter List onTap to get index of taped item

i created a search delegate class and what i want sounds logically simple but i cant wrap my head around it as i am new programming
i want to get the text or maybe i should say string of the text in the listTile i tap on ,
then pass that text to the showResult of search delegate and view it in a text widget
... here is my code
import 'package:flutter/material.dart';
import 'package:schooler/style/const.dart';
//follow steps 1 - 3
class DataSearch extends SearchDelegate<String> {
final List<String> languages = [//3.here is my list
'dart',
'Csharp',
'Java',
'JavaScript',
'C++',
'go ',
'python',
'php'
];
final List<String> recentSearch = [
'go ',
'python',
'php',
];
#override
List<Widget> buildActions(BuildContext context) {
return [
IconButton(
icon: Icon(Icons.clear),
onPressed: () {
query = '';
},
)
];
}
#override
Widget buildLeading(BuildContext context) {
return IconButton(
icon: AnimatedIcon(
icon: AnimatedIcons.menu_arrow,
progress: transitionAnimation,
),
onPressed: () {
close(context, null);
},
);
}
#override
Widget buildResults(BuildContext context) {
return Scaffold(
body: ListView(
physics: BouncingScrollPhysics(),
children: <Widget>[
Row(
children: <Widget>[
CircleAvatar(),
Text(languages[0].substring(query.length)),//2.i want to return the gotten index here
],
),
],
),
);
}
#override
Widget buildSuggestions(BuildContext context) {
final suggestionList = query.isEmpty
? recentSearch
: languages.where((element) => element.startsWith(query)).toList();
return ListView.builder(
physics: BouncingScrollPhysics(),
itemBuilder: (context, index) => ListTile(
onTap: () {
showResults(context); //1.when i tap the item on the listTile i want it to get the index of the taped item
},
leading: query.isEmpty
? Icon(
Icons.history,
)
: Icon(Icons.search),
title: RichText(
text: TextSpan(
text: suggestionList[index].substring(
0,
query.length,
),
style: TextStyle(
color: kBlackColor,
fontWeight: kBold,
),
children: [
TextSpan(
text: suggestionList[index].substring(query.length),
style: TextStyle(color: kGreyColor),
),
],
),
),
),
itemCount: suggestionList.length,
);
}
}
here if i tap on 'go' it should get get the text and pass it to the showResult
here is my show result ..but i just hard coded my 'list[0]index in there' i guess what i am trying to say is get the text from the item i taped and show it here
First lets fix your itemBuilder in your ListView so it indexes each element and then add that index into your showResults() function call so you have access to it:
ListView.builder(
physics: BouncingScrollPhysics(),
itemBuilder: (context, index) => ListTile( // Add index here to pass the index to the builder.
onTap: () {
showResults(context, index); // Add the index to function call
},
Just be sure your showResults() function is modified to accept an int index parameter, and while I dont see that function, I am assuming it calls buildResults() at some point which needs to be modified to accept an index:
#override
Widget buildResults(BuildContext context, int index) {
return Scaffold(
body: ListView(
physics: BouncingScrollPhysics(),
children: <Widget>[
Row(
children: <Widget>[
CircleAvatar(),
Text(languages[index].substring(query.length)),// Use the index here to return the desired text
],
),
],
),
);
}