Whenever I add an item to my least it adds to the list at the current state but when I reopen after pop context the item is no more there
*How can I have the items in list permanently *enter image description hereenter image description hereenter image description hereenter image description hereenter image description here
class Prabesh extends StatefulWidget {
#override
_PrabeshState createState() => _PrabeshState();
}
class _PrabeshState extends State<Prabesh> {
final List users = [
'Ram',
'Shyam',
'Hari',
'Paudel',
'Pandey',
'Sashwat',
'Kismat',
];
// ondlt(Key key) {
// for (int i = 0; i <= users.length; i++) {
// var a = users.elementAt(i);
// if (key == a.key) {
// users.removeAt(i);
// }
// }
// }
void onClk() {
myDialog(BuildContext, context);
}
final myUser = TextEditingController();
myDialog(BuildContext, context) {
showDialog(
barrierDismissible: false,
context: context,
builder: (context) {
return AlertDialog(
title: Text('Add a user'),
content: TextFormField(
controller: myUser,
maxLength: 20,
decoration: InputDecoration(
hintText: 'Enter Username',
),
),
actions: [
ElevatedButton(
onPressed: () => Navigator.pop(context),
child: Text('Cancel')),
ElevatedButton(
onPressed: () {
setState(() {
if (myUser.text.isEmpty) {
return Navigator.pop(context);
} else {
users.add(myUser.text);
return Navigator.pop(context);
}
});
},
child: Text('Add'),
),
],
);
});
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Prabesh'),
leading: BackButton(
onPressed: () => Navigator.pop(context),
),
),
body: ListView.builder(
itemCount: users.length,
itemBuilder: (context, index) {
return Card(
elevation: 10,
child: ListTile(
// key: Key(users[index]),
//onLongPress: () => ondlt(key),
onTap: () {},
title: Text(users[index]),
trailing: Icon(Icons.menu),
leading: CircleAvatar(
child: Text(users[index].substring(0, 1)),
),
),
);
},
),
floatingActionButton: FloatingActionButton(
onPressed: () => onClk(),
child: Icon(Icons.add),
),
),
);
}
}
You must save your data locally or on an online database.
For saving data on mobile storage you can use this package.
But for saving data on an online database you can use Firebase or you must develop a web server.
Related
Basically, I have two classes Register and AddUser. I want to navigate value from the AddUser page to the RegisterPage but I am not getting any values despite using the constructor and getting null value while debugging.
User First lands on the Register page where there is floatingAction button and it navigates to the AddUser Page. After providing the input , on clicking save button, it navigates back to the Register page where user will get the list of input.
**Register**
class Register extends StatefulWidget {
late String? names;
Register({required this.names});
#override
_RegisterState createState() => _RegisterState(names);
}
class _RegisterState extends State<Register> {
late String? names;
_RegisterState(this.names);
List<UserModel> getUserModel() {
return [
UserModel(
name: widget.names??'',
)
];
}
// final user = UserSimplePreferences.getUser();
#override
void initState() {
// TODO: implement initState
super.initState();
}
#override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Padding(
padding: const EdgeInsets.only(top: 10, bottom: 10),
child: Text('Seleccione una categoría:',
textAlign: TextAlign.center,
style: TextStyle(color: Colors.black)
),
),
Expanded(
child: ListView.builder(
itemCount: getUserModel().length,
itemBuilder: (BuildContext ctx, int index) {
return Container(
margin: EdgeInsets.all(20),
height: 150,
child: Stack(
children: [
Text(getUserModel()[index].name)
],
)
);
},
),
),
FloatingActionButton(
backgroundColor: Colors.indigo[900],
onPressed: () {
print(names);
Navigator.push(
context,
MaterialPageRoute(builder: (_) {
return AddUser(idUser: '',);
}),
);
},
child: Icon(Icons.add, color: Colors.white),
),
]
);
}
}
**AddUser**
class AddUser extends StatefulWidget {
final String? idUser;
const AddUser({required this.idUser});
#override
_AddUserState createState() => _AddUserState();
}
class _AddUserState extends State<AddUser> {
final formKey = GlobalKey<FormState>();
TextEditingController saaaaa = new TextEditingController();
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) => Scaffold(
appBar: AppBar(
automaticallyImplyLeading: false,
title: Text(
'Please Enter Your Details',
textAlign: TextAlign.center,
)),
body: SafeArea(
child: ListView(
padding: EdgeInsets.all(16),
children: [
buildName(),
const SizedBox(height: 12),
],
),
),
);
Widget buildName() => buildTitle(
title: 'Name',
child: TextFormField(
controller: saaaaa,
//initialValue: name,
decoration: InputDecoration(
border: OutlineInputBorder(),
hintText: 'Your Name',
),
onChanged: (namer) => setState(() => namer = saaaaa.text),
),
);
Widget buildButton() => ButtonWidget(
text: 'Save',
onClicked: () async {
setState(() async {
Register(names : saaaaa.text );
Navigator.pop(context);
});
});
Widget buildTitle({
required String title,
required Widget child,
}) =>
Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text(
title,
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 18),
),
const SizedBox(height: 8),
child,
],
);
}
You can achive this things by then callback in navigator and pass your value when you pop add screen.
Please replace your code with below code
Register
class Register extends StatefulWidget {
#override
_RegisterState createState() => _RegisterState();
}
class _RegisterState extends State<Register> {
List<UserModel> userList = [];
// final user = UserSimplePreferences.getUser();
#override
void initState() {
// TODO: implement initState
super.initState();
}
#override
Widget build(BuildContext context) {
return Column(crossAxisAlignment: CrossAxisAlignment.stretch, children: [
Padding(
padding: const EdgeInsets.only(top: 10, bottom: 10),
child: Text('Seleccione una categoría:',
textAlign: TextAlign.center, style: TextStyle(color: Colors.black)),
),
Expanded(
child: ListView.builder(
itemCount: userList.length,
itemBuilder: (BuildContext ctx, int index) {
return Container(
margin: EdgeInsets.all(20),
height: 150,
child: Stack(
children: [Text(userList[index].name)],
));
},
),
),
FloatingActionButton(
backgroundColor: Colors.indigo[900],
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (_) {
return AddUser(
idUser: '',
);
}),
).then((value) {
if (value != null) {
userList.add(UserModel(name: value));
setState(() {});
}
});
},
child: Icon(Icons.add, color: Colors.white),
),
]);
}
}
**AddUser**
class AddUser extends StatefulWidget {
final String? idUser;
const AddUser({required this.idUser});
#override
_AddUserState createState() => _AddUserState();
}
class _AddUserState extends State<AddUser> {
final formKey = GlobalKey<FormState>();
TextEditingController saaaaa = new TextEditingController();
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) => Scaffold(
appBar: AppBar(
automaticallyImplyLeading: false,
title: Text(
'Please Enter Your Details',
textAlign: TextAlign.center,
)),
body: SafeArea(
child: ListView(
padding: EdgeInsets.all(16),
children: [
buildName(),
buildButton(),
const SizedBox(height: 12),
],
),
),
);
Widget buildName() => buildTitle(
title: 'Name',
child: TextFormField(
controller: saaaaa,
//initialValue: name,
decoration: InputDecoration(
border: OutlineInputBorder(),
hintText: 'Your Name',
),
onChanged: (namer) => setState(() => namer = saaaaa.text),
),
);
Widget buildButton() => ButtonWidget(
text: 'Save',
onClicked: () async {
setState(() async {
// Register(names : saaaaa.text );
Navigator.pop(context, saaaaa.text);
});
});
Widget buildTitle({
required String title,
required Widget child,
}) =>
Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text(
title,
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 18),
),
const SizedBox(height: 8),
child,
],
);
}
This may help and work for you
Register screen
FloatingActionButton(
backgroundColor: Colors.indigo[900],
onPressed: () async {
print(names);
var result = await Navigator.push(
context,
MaterialPageRoute(
builder: (BuildContext context) => AddUser(idUser: '')));
print(result);
names = result;
setState((){});
},
child: const Icon(Icons.add, color: Colors.white),
)
Add screen
Widget buildButton() => MaterialButton(
child: Text('Save'),
onPressed: () {
Navigator.pop(context, saaaaa.text);
});
I guess here after you can take and store in list in register page and then list down the names
You can achieve this thing by using a callback function
add Callback function to your AddUser class and on save button just call your call back function like below:
class AddUser extends StatefulWidget {
final String? idUser;
// add this to your register class
final Function(String) addedUser;
const AddUser({required this.idUser,required this.addedUser});
#override
_AddUserState createState() => _AddUserState();
}
class _AddUserState extends State<AddUser> {
final formKey = GlobalKey<FormState>();
TextEditingController saaaaa = new TextEditingController();
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) => Scaffold(
appBar: AppBar(
automaticallyImplyLeading: false,
title: Text(
'Please Enter Your Details',
textAlign: TextAlign.center,
)),
body: SafeArea(
child: ListView(
padding: EdgeInsets.all(16),
children: [
buildName(),
const SizedBox(height: 12),
],
),
),
);
Widget buildButton() => ButtonWidget(
text: 'Save',
onClicked: () async {
setState(() async {
/// Just call addedUser like this
widget.addedUser(saaaaa.text);
Navigator.pop(context);
});
});
}
Simply where you are calling AddUser in Register Screen, add addedUser in the constructor of AddUser
import 'package:flutter/material.dart';
class Register extends StatefulWidget {
late String? names;
Register({required this.names});
#override
_RegisterState createState() => _RegisterState(names);
}
class _RegisterState extends State<Register> {
late String? names;
_RegisterState(this.names);
#override
Widget build(BuildContext context) {
FloatingActionButton(
backgroundColor: Colors.indigo[900],
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (_) {
//just add parameter to your AddUser constructor
return AddUser(idUser: '',addedUser:(value){
///In this value variable you get the value of user you added on addUser page///
print(value);
});
}),
);
},
child: Icon(Icons.add, color: Colors.white),
),
]
);
}
}
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.
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'),
),
],
),
),
),
);
}
}
I implemented a search list with consultation to firebase. Initially, all registered users appear on the screen and when I click on one of the users, the app shows another screen with all the data for that user. When you start typing in the search field, only users with respect to the text entered appear.
However, a problem arose: when filtering a customer, only it appears on the screen and when I click to open the customer's information, the app shows the information of the first user in the general list (without taking into account the filter).
I believe that this happens due to the index, which looks at the position of the document in the firebase.
How to fix this? Thank you!
body: Column(
children: <Widget>[
SizedBox(
height: 5,
),
TextField(
controller: _procurarpaciente,
decoration: InputDecoration(
border: OutlineInputBorder(), labelText: "Pesquisar paciente",prefixIcon: Icon(Icons.search)
),
onChanged: (val) {
setState(() {
nome = val;
});
},
),
Expanded(
child: StreamBuilder<QuerySnapshot>(
stream: (nome != "" && nome != null)
? Firestore.instance
.collection('pacientes')
.where("indexList", arrayContains: nome)
.snapshots()
: Firestore.instance.collection("pacientes").snapshots(),
builder: (context, snapshot) {
switch(snapshot.connectionState){
case ConnectionState.none:
case ConnectionState.waiting:
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(Icons.error_outline),
Text("Usuário não encontrado")
],
),
);
default:
// List<DocumentSnapshot> documentos =
// snapshot.data.documents;
return ListView.builder(
itemCount: snapshot.data.documents.length,
itemBuilder: (context, index) {
DocumentSnapshot data = snapshot.data.documents[index];
return ListTile(
title: Text(
data['nome'],
style: TextStyle(
fontWeight: FontWeight.w700,
fontSize: 16,
),),
subtitle:Text(
"Quarto: ${data['quarto']}",
style: TextStyle(
fontWeight: FontWeight.w700,
fontSize: 14,
),),
leading:CircleAvatar(
backgroundImage: NetworkImage(data['foto']),
),
onTap: ()=> {
//print(data.documentID),
_navegarParaPerfil(context, items[index]),
}
);
},
);
}
}
),
)
],
),
void _navegarParaPerfil(BuildContext context, Paciente paciente) async{
await Navigator.push(context,
MaterialPageRoute(builder: (context) => TelaPaciente(paciente)),
);
}
dsdsd
Step 1:
class Employee {
Employee(this.employeeID, this.employeeName, this.branch, this.designation, this.location,
this.salary,
{this.reference});
double employeeID;
String employeeName;
String designation;
String branch;
String location;
double salary;
DocumentReference reference;
factory Employee.fromSnapshot(DocumentSnapshot snapshot) {
Employee newEmployee = Employee.fromJson(snapshot.data());
newEmployee.reference = snapshot.reference;
return newEmployee;
}
factory Employee.fromJson(Map<String, dynamic> json) =>
_employeeFromJson(json);
Map<String, dynamic> toJson() => _employeeToJson(this);
#override
String toString() => 'employeeName ${employeeName}';
}
Step 2:
class EmployeeRepository {
List<Employee> employees = [];
final CollectionReference collection =
FirebaseFirestore.instance.collection('employees');
Stream<QuerySnapshot> getStream() {
return collection.snapshots();
}
Future<DocumentReference> add(Employee employee) {
var documentReference = collection.add(employee.toJson());
return documentReference;
}
update(Employee employee) async {
collection.doc(employee.reference.id).update(employee.toJson());
}
delete(Employee employee) async {
collection.doc(employee.reference.id).delete();
}
fromSnapShot(DocumentSnapshot snapshot) => Employee.fromSnapshot(snapshot);
Future<List<Employee>> buildData(
AsyncSnapshot snapshot, String filterKey) async {
List<Employee> list = [];
List<Employee> filteredList = [];
/// Based on the user snapShot, you can convert into the List and return to
/// the futurebuilder
await Future.forEach(snapshot.data.docs, (element) async {
list.add(Employee.fromSnapshot(element));
}).then((value) {
if (filterKey != null) {
filteredList = list
.where((element) =>
element.employeeID.toString() == filterKey ||
element.employeeName == filterKey ||
element.designation == filterKey ||
element.branch == filterKey ||
element.location == filterKey ||
element.salary.toString() == filterKey)
.toList();
}
});
if (filteredList.isEmpty) {
return Future<List<Employee>>.value(list);
} else {
return Future<List<Employee>>.value(filteredList);
}
}
}
Step 3:
EmployeeRepository employeeRepository = EmployeeRepository();
TextEditingController textEditingController = TextEditingController();
String filteredText = '';
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
appBar: AppBar(
title: Text('ListView'),
),
body: StreamBuilder(
stream: employeeRepository.getStream(),
builder: (context, snapShot) {
if (snapShot.data == null ||
snapShot.connectionState == ConnectionState.waiting ||
snapShot.hasError ||
snapShot.data.docs.length == 0) {
return Container(
child: Center(child: CircularProgressIndicator()),
);
} else {
return StatefulBuilder(builder: (context, innerSetState) {
return FutureBuilder(
future: employeeRepository.buildData(
snapShot, filteredText),
builder: (context, futureSnapShot) {
if (!futureSnapShot.hasData) {
return Container(
child: Center(child: CircularProgressIndicator()),
);
} else {
return Column(
children: [
TextField(
controller: textEditingController,
decoration: InputDecoration(
icon: Icon(Icons.search),
hintText: 'Search here!'),
onSubmitted: (value) {
innerSetState(() {
filteredText = value;
});
},
onChanged: (value) {
innerSetState(() {
filteredText = value;
});
},
),
Container(
height: 400,
child: ListView.builder(
itemCount: futureSnapShot.data.length,
itemBuilder: (context, index) {
final Employee employee =
futureSnapShot.data[index];
return ListTile(
title: Text(employee.employeeName),
trailing:
Text('Salary${employee.salary}'),
subtitle: Text(employee.designation),
onTap: () {
print(employee.salary);
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
EmployeeDetailsPage(
employee)));
},
);
},
),
),
],
);
}
});
});
}
},
)));
}
Step 4:
class EmployeeDetailsPage extends StatelessWidget {
final Employee employeeData;
const EmployeeDetailsPage(this.employeeData);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Employee Details'),
),
body: Column(
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Center(child: Text(employeeData.employeeName, style: TextStyle(fontSize: 30))),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Center(child: Text(employeeData.designation, style: TextStyle(fontSize: 20))),
),
Text('Salary ${employeeData.salary.toString()}'),
],
),
);
}
}
<blockquote class="imgur-embed-pub" lang="en" data-id="a/aqBaJ7N" data-context="false" ></blockquote><script async src="//s.imgur.com/min/embed.js" charset="utf-8"></script>
Hey! Unfortunately it didn't work, look what keeps happening.
I think this is because of the index I send as a parameter, which does not understand that the values have been filtered:
onTap: ()=> {
//print(data.documentID),
_navegarParaPerfil(context, items[index]),
}
void _navegarParaPerfil(BuildContext context, Paciente paciente) async{
await Navigator.push(context,
MaterialPageRoute(builder: (context) => TelaPaciente(paciente)),
);
}
Ideally, it would be validated by documentID instead of this index, but I was unable to change it
I have a page with a list and a bar that reaches a detail page.
I would like to add a pop on the detail page to retrieve an item and save it to a todo page but I have a problem with my detail page.
With a Stateless, I have no worries but, if I'm not mistaken, I need a Stateful to add a Future, showDialog .. but, I have problems with my indexes... and there, I'm lost ...
Can someone give me a track or an explanation?
Thank you
home.dart
import 'dart:core';
import 'package:flutter/material.dart';
import 'package:test_todo_list/DataList.dart';
import 'package:test_todo_list/detail.dart';
class Home extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Liste Items'),
actions: <Widget>[
IconButton(icon: Icon(Icons.search),
onPressed: () {
showSearch(context: context, delegate: DataSearch(listWords));
})
],
),
body: ListView.separated(
itemCount: listWords.length,
separatorBuilder: (BuildContext context, int i) =>
Divider(color: Colors.grey),
itemBuilder: (context, i) {
return ListTile(
onTap: () {
Navigator.push(
context,MaterialPageRoute(
builder: (context) => Detail(listWordsDetail: listWords[i]),
),
);
},
title: RichText(
textAlign:TextAlign.left,
text: TextSpan(
children:<TextSpan>[
TextSpan(
text:listWords[i].titlelist,
style:Theme.of(context).textTheme.title.merge(TextStyle(color: Colors.blueGrey)),
),
]
)
),
subtitle: Text(listWords[i].definitionlist,
style: Theme.of(context).textTheme.subtitle.merge(
TextStyle(fontStyle: FontStyle.italic, color: Colors.grey)),
),
trailing: Icon(Icons.arrow_forward_ios, color: Colors.grey),
);
},
),
);
}
}
class DataSearch extends SearchDelegate<String> {
final List<ListWords> listWords;
DataSearch(this.listWords);
#override
List<Widget> buildActions(BuildContext context) {
//Actions for app bar
return [IconButton(icon: Icon(Icons.clear), onPressed: () {
query = '';
})];
}
#override
Widget buildLeading(BuildContext context) {
//leading icon on the left of the app bar
return IconButton(
icon: AnimatedIcon(icon: AnimatedIcons.menu_arrow,
progress: transitionAnimation,
),
onPressed: () {
close(context, null);
});
}
#override
Widget buildResults(BuildContext context) {
// show some result based on the selection
final suggestionList = listWords;
return ListView.builder(itemBuilder: (context, index) => ListTile(
title: Text(listWords[index].titlelist),
subtitle: Text(listWords[index].definitionlist),
),
itemCount: suggestionList.length,
);
}
#override
Widget buildSuggestions(BuildContext context) {
// show when someone searches for something
final suggestionList = query.isEmpty
? listWords
: listWords.where((p) => p.titlelist.contains(RegExp(query, caseSensitive: false))).toList();
return ListView.builder(itemBuilder: (context, index) => ListTile(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => Detail(listWordsDetail: suggestionList[index]),
),
);
},
trailing: Icon(Icons.remove_red_eye),
title: RichText(
text: TextSpan(
text: suggestionList[index].titlelist.substring(0, query.length),
style: TextStyle(
color: Colors.red, fontWeight: FontWeight.bold),
children: [
TextSpan(
text: suggestionList[index].titlelist.substring(query.length),
style: TextStyle(color: Colors.grey)),
]),
),
),
itemCount: suggestionList.length,
);
}
}
detail.dart
import 'package:flutter/material.dart';
import 'package:test_todo_list/DataList.dart';
class Detail extends StatefulWidget {
Detail({Key key, #required this.listWordsDetail}) : super(key: key);
final ListWords listWordsDetail;
#override
_DetailState createState() => _DetailState();
}
class _DetailState extends State<Detail> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
brightness: Brightness.dark,
title: const Text('Détails', style: TextStyle(color: Colors.white)),
iconTheme: IconThemeData(color: Colors.white),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(listWordsDetail.titlelist +' (on detail page)',
style:Theme.of(context).textTheme.title.merge(TextStyle(color: Colors.blueGrey)),
),
Text(listWordsDetail.definitionlist,
style: Theme.of(context).textTheme.subtitle.merge(
TextStyle(fontStyle: FontStyle.italic, color: Colors.grey)),
),
Container(
padding: EdgeInsets.all(40.0),
child: GestureDetector(
onTap: () {
},
child: Icon(Icons.add_shopping_cart),
),
)
],
),
)
);
}
}
DataList.dart
List<ListWords> listWords = [
ListWords('oneWord', 'OneWord definition'),
ListWords('twoWord', 'TwoWord definition.'),
ListWords('TreeWord', 'TreeWord definition'),
];
class ListWords {
String titlelist;
String definitionlist;
ListWords(String titlelist, String definitionlist) {
this.titlelist = titlelist;
this.definitionlist = definitionlist;
}
}
After searching on the web, by chance, I found this solution that I can not explain but it's working...
import 'package:flutter/material.dart';
import 'package:test_todo_list/DataList.dart';
import 'package:test_todo_list/todo_list.dart';
class Detail extends StatefulWidget {
const Detail({Key key, this.listWordsDetail}) : super (key: key);
final ListWords listWordsDetail;
#override
_DetailState createState() => _DetailState();
}
class _DetailState extends State<Detail> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
brightness: Brightness.dark,
title: const Text('Détails', style: TextStyle(color: Colors.white)),
iconTheme: IconThemeData(color: Colors.white),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(widget.listWordsDetail.titlelist),
Text(widget.listWordsDetail.definitionlist),
Container(
padding: EdgeInsets.all(40.0),
child: GestureDetector(
onTap: () {
//open Dialog addTodoList()
},
child: Icon(Icons.add_shopping_cart),
),
)
],
),
)
);
}
Future<Null> addTodoList() async {
showDialog(context: context);
//... à construire
}
}