Flutter Saving button state on device - flutter

I have a search screen where users can search for a county and a list of vaccination posts in said county is shown. Some counties have many some have very few.
In the list of vaccination posts, there is a button that when pressed, the button is disabled. All is good until here, but when I re-search the same county, the button that was once disabled is no longer disabled, meaning it can be pressed again. I would like to avoid that.
I have a list of bools, "true" for each vaccination post. When button is pressed, respective index in the list is changed to "false" thus disabling the button.
Question: How can I keep the button disable? (Whether the same county is re-searched or the app is re-opened)
import 'package:colour/colour.dart';
import 'package:firebase_database/firebase_database.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:google_fonts/google_fonts.dart';
import 'dart:async';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
// import 'package:shared_preferences/shared_preferences.dart';
class VaccineCenterList extends StatefulWidget {
const VaccineCenterList({key}) : super(key: key);
static const String idScreen = "VaccineCenterList";
#override
_VaccineCenterListState createState() => _VaccineCenterListState();
}
class _VaccineCenterListState extends State<VaccineCenterList> {
TextEditingController hospitalCountyEditingController =
TextEditingController();
final databaseReference = FirebaseDatabase.instance.reference();
final firestoreInstance = FirebaseFirestore.instance;
FirebaseAuth auth = FirebaseAuth.instance;
List<Hospitals> driverList = [];
List<bool> buttonPressed = [];
// Map<String, List> buttonPressed = {};
buttonControls(numOfLocations) {
print(numOfLocations);
int checker = 0;
if (numOfLocations > buttonPressed.length) {
try {
while (numOfLocations >= checker) {
buttonPressed.add(true);
checker = checker + 1;
}
} catch (e) {
print("$e");
}
} else {}
print(buttonPressed);
}
#override
void initState() {
super.initState();
print("I'm in the vaccine list search screen");
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.grey[100],
appBar: AppBar(
backgroundColor: Colors.grey[100],
centerTitle: true,
elevation: 0,
iconTheme: const IconThemeData(
color: Colors.black,
),
title: Text(
"Pamoja",
style: GoogleFonts.lexendMega(
fontWeight: FontWeight.bold,
color: Colors.black,
fontSize: 35,
),
),
),
body: GestureDetector(
onTap: () {
FocusScope.of(context).requestFocus(FocusNode());
},
child: SingleChildScrollView(
child: Column(
children: [
Container(
// textfield
padding: const EdgeInsets.all(8.0),
child: TextField(
controller: hospitalCountyEditingController,
keyboardType: TextInputType.text,
textCapitalization: TextCapitalization.words,
decoration: InputDecoration(
border: const OutlineInputBorder(
borderSide: BorderSide(
color: Colors.black,
style: BorderStyle.solid,
width: 1,
),
),
labelText: "Search County",
labelStyle: const TextStyle(
fontSize: 14.0,
color: Colors.blueGrey,
),
hintStyle: GoogleFonts.lexendMega(
color: Colors.grey,
fontSize: 10,
),
),
style: GoogleFonts.lexendMega(
fontSize: 14,
color: Colors.black,
),
),
),
ElevatedButton(
// search button
onPressed: () {
setState(() {
FocusScope.of(context).requestFocus(
FocusNode(),
);
driverList.clear();
if (hospitalCountyEditingController.text == "" ||
hospitalCountyEditingController.text == " ") {
isTrueOrFalse = "False";
} else {
isTrueOrFalse = "True";
}
});
getHospitalDetails();
},
child: Text(
"Search",
style: GoogleFonts.lexendMega(
fontWeight: FontWeight.bold,
),
),
),
SingleChildScrollView(
child: Column(
children: [
SizedBox(
height: MediaQuery.of(context).size.height,
// height: 50,
// color: Colors.black,
child: Padding(
padding: const EdgeInsets.only(
right: 12.0,
left: 12.0,
bottom: 12.0,
),
child: driverList.isEmpty
? Center(
// child: CircularProgressIndicator(),
child: (isTrueOrFalse == "True")
? const CircularProgressIndicator()
: Column(
mainAxisAlignment:
MainAxisAlignment.center,
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
"Search for one of the counties below",
style:
GoogleFonts.lexendMega()),
),
Text(
"Nairobi, Baringo, Busia, Bomet, Bungoma, Elgeyo Marakwet, Embu, Garissa, Homa Bay, Isiolo, Kajiado, Kakamega, Kericho, Kiambu, Kilifi, Kirinyaga, Kisii, Kisumu, Kitui, Kwale, Laikipia, Lamu, Machakos, Makueni, Mandera, Marsabit, Meru, Migori, Mombasa, Muranga, Nakuru, Nandi, Narok, Nyamira, Nyandarua, Nyeri, Samburu, Siaya County, Taita Taveta, Tana River County, Tharaka Nithi, Trans Nzoia, Turkana, Uasin Gishu, Vihiga, Wajir, West Pokot",
textAlign: TextAlign.center,
style: GoogleFonts.lexendMega(
fontWeight: FontWeight.bold,
),
),
],
),
)
: ListView.builder(
itemCount: driverList.length,
itemBuilder: (context, index) {
final Hospitals hospitals = driverList[index];
final String hospitalLocaiton =
hospitals.location;
final String hospitalPhone = hospitals.phone;
final String hospitalName = hospitals.name;
positiveCount = hospitals.positiveCount;
negativeCount = hospitals.negativeCount;
final int setpercentage =
calculatePositivePercentage(
positiveCount, negativeCount);
buttonControls(driverList.length);
return Padding(
padding: const EdgeInsets.all(8.0),
child: Card(
elevation: 0,
child: ExpansionTile(
title: Text(
hospitalName.toUpperCase(),
style: GoogleFonts.lexendMega(),
textAlign: TextAlign.center,
),
children: [
Column(
children: [
Container(
child: (hospitalPhone
.isNotEmpty)
? ElevatedButton(
onPressed: () {
Clipboard.setData(
ClipboardData(
text:
hospitalPhone,
),
);
ScaffoldMessenger.of(
context)
.showSnackBar(
const SnackBar(
backgroundColor:
Colors.green,
content: Text(
"Number Copied",
textAlign:
TextAlign
.center,
),
),
);
},
child: Text(
hospitalPhone,
textAlign:
TextAlign.center,
style: GoogleFonts
.lexendMega(
fontSize: 13),
),
style: ElevatedButton
.styleFrom(
elevation: 0,
),
)
: const Text(""),
),
const SizedBox(
height: 5,
),
hospitalLocaiton.isNotEmpty
? Container(
padding:
const EdgeInsets.all(
8),
decoration: BoxDecoration(
border: Border.all(
color: Colors.black,
),
borderRadius:
BorderRadius
.circular(10),
),
child: Text(
hospitalLocaiton,
textAlign:
TextAlign.center,
style: GoogleFonts
.lexendMega(
fontSize: 12,
),
),
)
: Text(
hospitalLocaiton,
textAlign:
TextAlign.center,
style: GoogleFonts
.lexendMega(
fontSize: 12,
),
),
const SizedBox(
height: 10,
),
Text(
"$setpercentage% (percent) of voters say this hospital administer vaccines.",
textAlign: TextAlign.center,
style: GoogleFonts.lexendMega(
fontWeight: FontWeight.bold,
fontSize: 12,
color: Colors.deepPurple[400],
),
),
const SizedBox(
height: 10,
),
const Divider(
// thickness: 1,
indent: 20,
endIndent: 20,
color: Colors.black87,
),
const SizedBox(
height: 10,
),
Text(
"Does this Hospital administer Vaccines?\n(To help the public, please vote only if you know.)",
textAlign: TextAlign.center,
style: GoogleFonts.lexendMega(
fontSize: 12,
fontWeight: FontWeight.bold,
),
),
Column(
children: [
Row(
mainAxisAlignment:
MainAxisAlignment
.spaceEvenly,
children: [
ElevatedButton(
onPressed:
buttonPressed[index]
? () {
positiveIncrement(
hospitalName,
index);
buttonPressed[
index] =
false;
ScaffoldMessenger.of(
context)
.showSnackBar(
const SnackBar(
backgroundColor:
Colors.redAccent,
content:
Text(
"Voted",
textAlign:
TextAlign.center,
),
),
);
}
: null,
child: Text(
"Yes",
style: GoogleFonts
.lexendMega(),
),
style: ElevatedButton
.styleFrom(
primary:
Colour("#87D68D"),
),
),
ElevatedButton(
onPressed:
buttonPressed[index]
? () {
negativeIncrement(
hospitalName,
index);
buttonPressed[
index] =
false;
ScaffoldMessenger.of(
context)
.showSnackBar(
const SnackBar(
backgroundColor:
Colors.redAccent,
content:
Text(
"Voted",
textAlign:
TextAlign.center,
),
),
);
}
: null,
child: Text(
"No",
style: GoogleFonts
.lexendMega(),
),
style: ElevatedButton
.styleFrom(
primary:
Colour("#E3655B"),
),
),
],
),
const SizedBox(
height: 10,
),
Text(
"1 - To vote, tap once\n2 - To Undo vote, tap and hold",
style:
GoogleFonts.lexendMega(
fontSize: 12,
),
textAlign: TextAlign.start,
),
const SizedBox(
height: 10,
),
],
),
],
),
],
),
),
);
},
),
),
),
// SizedBox(height: 40),
],
),
),
],
),
),
),
);
}
}
class Hospitals {
final String name;
final String phone;
final String location;
// final String county;
final int positiveCount;
final int negativeCount;
// final int intPercentage;
// final int totalVotes;
Hospitals({
required this.name,
required this.phone,
required this.location,
// required this.county,
required this.positiveCount,
required this.negativeCount,
// required this.intPercentage,
// required this.totalVotes,
});
static Hospitals fromJson(Map<String, dynamic> json) {
return Hospitals(
name: json['HospitalName'],
phone: json['HospitalPhone'],
// county: json['county'],
location: json['HospitalAddres'],
positiveCount: json['poitiveCount'],
negativeCount: json['negativeCount'],
// intPercentage: json['intPercentage'],
// totalVotes: json['totalVotes']
);
}
}

I did that this way: use the provider to set value, make boolean value
late bool isMyButtonEnabled;
//in initState
setState(() {
isMyButtonEnabled=
myProvider.checkIfButtonShouldBeEnabled(widget.Id);
}
//in build
ElevatedButton(
child: Text('SUBMIT'),
onPressed: !isMyButtonEnabled
? null
: () async => {
//some code
}
this way your boolean will be saved and available everywhere in the app using the Provider package (there are other even more advanced analogs of Provider there that can be used as well)

Related

I am getting this error "The instance member 'setState' cant be accessed in an initializer". Flutter/Dart

I am getting this error "The instance member 'setState' cant be accessed in an initializer" here :
This is the full code :
class insertLossEvent extends StatefulWidget {
#override
State<insertLossEvent> createState() => _insertLossEventState();
}
class _insertLossEventState extends State<insertLossEvent> {
static final field_1Controller = TextEditingController();
static final field_4Controller = TextEditingController();
void _sendLogin() async {
var newMessage = await (ReadCache.getString(key: 'cache1'));
var map = <String, dynamic>{
"Field_1": field_1Controller.text,
"Field_4": field_4Controller.text,
"table_id": "25510",
"form_type": "2",
};
var res = await http.post(
Uri.parse("http://192.168.1.4:8080/HongLeong/SET_FORM_REQUEST.do"),
headers: {HttpHeaders.cookieHeader: newMessage},
body: map,
);
final data = jsonDecode(res.body);
print(data);
}
int _selectedIndex = 0;
void _navigateBottomBar(int index) {
setState(() {
_selectedIndex = index;
});
}
static List<String> orgUnit = [
'M1',
'M100138',
'M100078',
'M100108',
'M100069',
'M100118',
'M100071',
'M100150'
];
static String valueChoose;
final List<Widget> _pages = [
Container(
child: SingleChildScrollView(
child: Column(
children: [
//Main Info
ListTileTheme(
tileColor: Colors.grey,
child: ExpansionTile(
title: Text('Main Info',
style: GoogleFonts.poppins(
textStyle: const TextStyle(
color: Colors.black,
fontWeight: FontWeight.bold,
fontSize: 20,
))),
children: [
//Fields
ListTileTheme(
tileColor: Colors.white,
child: ListTile(
title: Text(
'Title : ',
style: GoogleFonts.poppins(
textStyle: const TextStyle(
fontWeight: FontWeight.bold,
fontSize: 20,
),
),
),
),
),
ListTileTheme(
tileColor: Colors.white,
child: ListTile(
title: Container(
decoration: BoxDecoration(
color: Colors.transparent,
border: Border.all(color: Colors.blueGrey),
borderRadius: BorderRadius.circular(10),
),
child: Padding(
padding: const EdgeInsets.all(8.0),
child: TextField(
decoration: InputDecoration(
border: InputBorder.none,
),
controller: field_1Controller,
style: GoogleFonts.poppins(
textStyle: const TextStyle(
fontWeight: FontWeight.normal,
fontSize: 20,
),
),
),
),
),
),
),
ListTileTheme(
tileColor: Colors.white,
child: ListTile(
title: Text(
'Organization Unit : ',
style: GoogleFonts.poppins(
textStyle: const TextStyle(
fontWeight: FontWeight.bold,
fontSize: 20,
),
),
),
),
),
ListTileTheme(
tileColor: Colors.white,
child: ListTile(
title: Container(
decoration: BoxDecoration(
color: Colors.transparent,
border: Border.all(color: Colors.blueGrey),
borderRadius: BorderRadius.circular(10),
),
child: Padding(
padding: const EdgeInsets.all(8.0),
child: DropdownButton<String>(
value: valueChoose,
onChanged: (newValue){
setState(() {
valueChoose = newValue;
});
},
items: orgUnit.map((valueItem) {
return DropdownMenuItem(
value: valueItem,
child: Text(valueItem),
);
}).toList(),
),
),
),
),
),
],
),
),
],
),
),
),
Container(
child: SingleChildScrollView(
child: Column(
children: [
//Shariah Details
ListTileTheme(
tileColor: Colors.grey,
child: ExpansionTile(
title: Text('Shariah Details',
style: GoogleFonts.poppins(
textStyle: const TextStyle(
color: Colors.black,
fontWeight: FontWeight.bold,
fontSize: 20,
))),
children: [
//Fields
],
),
),
],
),
),
)
];
In the best case scenario, I'd like to retain the code as this, but if you know of any improvements, please let me know.
How can I make it better? & what causes it to take place?
Thank You
to solve the problem, just add the pages List in the build Function and add return Container();
#override
Widget build(BuildContext context) {
final List<Widget> _pages = [
....
];
return Container();
}
Define pages like
List<Widget> _pages = [];
Then in initstate add values to it
_pages = [// add values here
];
setState((){});
The issue is that you tried adding set state when the codes are initialising. Adding it in initatate will not theow this error
Using late keyword will fix this issue like
late final List<Widget> _pages = [
But I will suggest to use method instead of variables in this case. Using variable doesn't get update context until you reassign the variable.
Do like this is better
List<Widget> _pages(BuildContext context) => [

Flutter- click is responding to every item in listview.builder

I am trying to create a list of items in flutter with listView.builder, i am also using using elevatedButton in my itemBuilder.
i applied setState in button
i want to change value of single item only
but that is applying to every value in list
here is my code
import 'dart:developer';
import 'package:counter_button/counter_button.dart';
import 'package:flutter/material.dart';
import 'package:fooddeliveryapp/apis.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'models/restrauntmenu.dart';
class RestrauntPage extends StatefulWidget {
final String restrauntId;
final String restrauntName;
final String restrauntType;
final String restrauntApproxBill;
final String restrauntTagline;
const RestrauntPage(
{Key? key,
required this.restrauntId,
required this.restrauntType,
required this.restrauntApproxBill,
required this.restrauntTagline,
required this.restrauntName})
: super(key: key);
#override
State<RestrauntPage> createState() => _RestrauntPageState();
}
class _RestrauntPageState extends State<RestrauntPage> {
int _counterValue = 1;
bool itemAdded = false;
late Future<List<RestrauntMenu>> futureRestrauntMenu;
Future<List<RestrauntMenu>> fetchRestrauntMenu() async {
String restrauntId = widget.restrauntId;
final response = await http.get(Uri.parse(menuApi(restrauntId)));
if (response.statusCode == 200) {
final parsed = json.decode(response.body).cast<Map<String, dynamic>>();
return parsed
.map<RestrauntMenu>((json) => RestrauntMenu.fromMap(json))
.toList();
} else {
throw Exception('Failed to load album');
}
}
addToCartButton(
{required String? itemname,
required String? itemprice,
required int? itemCount,
required String? usermob,
required String? restrauntName}) {
return ElevatedButton(
clipBehavior: Clip.antiAliasWithSaveLayer,
style: ButtonStyle(
elevation: MaterialStateProperty.all(
6,
),
backgroundColor: MaterialStateProperty.all(Colors.white),
),
onPressed: () {
addToCart(
itemname: itemname,
itemprice: itemprice,
restrauntName: restrauntName,
usermob: usermob,
itemCount: itemCount);
},
child: const Padding(
padding: EdgeInsets.all(8.0),
child: Text(
'ADD TO CART',
style: TextStyle(
color: Colors.green,
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
),
);
}
counterButton() {
return Container(
decoration: const BoxDecoration(color: Colors.white),
child: CounterButton(
loading: false,
onChange: (int val) {
setState(() {
_counterValue = val;
});
},
count: _counterValue,
countColor: Colors.green,
buttonColor: Colors.black,
progressColor: Colors.black,
),
);
}
Future addToCart(
{required String? itemname,
required String? itemprice,
required int? itemCount,
required String? usermob,
required String? restrauntName}) async {
itemCount = _counterValue;
var url = addToCartApi(
itemname: itemname,
itemprice: itemprice,
itemCount: itemCount,
usermob: usermob,
restrauntName: restrauntName);
var response = await http.get(
Uri.parse(url),
);
if (response.statusCode == 200) {
setState(() {
itemAdded = true;
});
} else {
return false;
}
}
#override
void initState() {
futureRestrauntMenu = fetchRestrauntMenu();
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
foregroundColor: Colors.black,
elevation: 0,
backgroundColor: Colors.white,
title: const Text('Restraunt Name'),
),
body: SingleChildScrollView(
child: SizedBox(
height: MediaQuery.of(context).size.height,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
SizedBox(
width: MediaQuery.of(context).size.width * 0.03,
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
widget.restrauntName,
style: const TextStyle(
color: Colors.black,
fontSize: 24,
fontWeight: FontWeight.w900,
),
),
// const SizedBox(height: 4),
Text(
widget.restrauntType,
style: const TextStyle(
color: Colors.black,
fontSize: 16,
fontWeight: FontWeight.normal,
),
),
Text(
widget.restrauntTagline,
style: const TextStyle(
color: Colors.black87,
fontSize: 12,
fontWeight: FontWeight.normal,
),
),
const SizedBox(
height: 6,
),
Container(
decoration: BoxDecoration(
color: Colors.grey[200],
borderRadius: BorderRadius.circular(10),
),
child: Padding(
padding: const EdgeInsets.all(8.0),
child: RichText(
text: TextSpan(
children: [
const WidgetSpan(
child: Icon(
Icons.currency_rupee,
size: 16,
color: Color.fromARGB(255, 45, 174, 49),
),
),
TextSpan(
text: widget.restrauntApproxBill,
style: const TextStyle(
color: Colors.black,
fontSize: 12,
fontWeight: FontWeight.bold,
),
),
],
),
),
),
),
],
),
const Spacer(),
Container(
decoration: BoxDecoration(
color: const Color.fromARGB(255, 49, 171, 53),
borderRadius: BorderRadius.circular(12),
),
child: Padding(
padding: const EdgeInsets.all(8.0),
child: RichText(
text: const TextSpan(
children: [
TextSpan(
text: '3.6',
style: TextStyle(
color: Colors.white,
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
WidgetSpan(
child: Icon(
Icons.star,
color: Colors.white,
size: 18,
),
),
],
),
),
),
),
SizedBox(
width: MediaQuery.of(context).size.width * 0.03,
),
],
),
const SizedBox(
height: 12,
),
Expanded(
child: FutureBuilder<List<RestrauntMenu>>(
future: futureRestrauntMenu,
builder: (context, snapshot) {
if (snapshot.hasData) {
return ListView.builder(
itemCount: snapshot.data!.length,
itemBuilder: (context, index) {
return ExpansionTile(
initiallyExpanded: true,
childrenPadding: const EdgeInsets.all(8),
title: Text(
snapshot.data![index].catname!,
style: const TextStyle(
fontSize: 20, fontWeight: FontWeight.bold),
),
children: [
Row(
children: [
Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Text(
snapshot.data![index].itemname!,
style: const TextStyle(
fontSize: 30,
fontWeight: FontWeight.bold,
),
),
const SizedBox(
height: 4,
),
Text(
snapshot.data![index].itemPrice!,
style: const TextStyle(
fontSize: 20,
fontWeight: FontWeight.w600,
),
),
const SizedBox(
height: 4,
),
Text(
snapshot.data![index].itemDescription!,
style: const TextStyle(
fontSize: 12,
fontWeight: FontWeight.normal,
),
),
],
),
const Spacer(),
Stack(
alignment: Alignment.bottomCenter,
children: [
Padding(
padding:
const EdgeInsets.only(bottom: 16),
child: ClipRRect(
borderRadius:
BorderRadius.circular(10),
child: FittedBox(
child: Container(
height: MediaQuery.of(context)
.size
.height *
0.22,
width: MediaQuery.of(context)
.size
.width *
0.4,
decoration: BoxDecoration(
color: Colors.red,
image: DecorationImage(
fit: BoxFit.cover,
image: NetworkImage(
'http://www.jfamoslogistics.com/images/${snapshot.data![index].itemimage!}',
),
),
),
),
),
),
),
Align(
alignment: Alignment.topRight,
child: itemAdded
? counterButton()
: addToCartButton(
itemprice: snapshot
.data![index].itemPrice,
itemname: snapshot
.data![index].itemname,
itemCount: _counterValue,
restrauntName:
widget.restrauntName,
usermob: '9354954343',
))
],
)
],
),
],
);
},
);
} else if (snapshot.hasError) {
return Text("${snapshot.error}");
}
return const Center(
child: CircularProgressIndicator(),
);
},
),
),
],
),
),
),
);
}
}
please check and help me
please let me know if i am missing something or making some mistake in code
i have tried google everywhere but nothing works
thanks in advance
As Giseppe Colucci described, you are using a single counter variable for a list . You can follow the simple approach of using list. On State
int _counterValue = 1; will be replaced with List<int> _counterValue = []
After getting data initialize the list with default value.
if (snapshot.hasData) {
_counterValue =List.generate(snapshot.data!.length, (index) => 1); // you might prefer default value as 0 instead of 1
As for the counter button method we need to update specific index, therefore we will pass index here
counterButton(int index) {
return Container(
decoration: const BoxDecoration(color: Colors.white),
child: CounterButton(
loading: false,
onChange: (int val) {
setState(() {
_counterValue[index] = val;
});
},
count: _counterValue[index],
Now whenever we use this counterButton method we need to pass index and here we get index from listview.
child: itemAdded
? counterButton(index)
: addToCartButton(
That is because your itemAdded bool is only one, for every item in the list, you should make a map, like this:
{'id':true}
where id is the restaurant menu item, and true is whenever the item is selected or not.
If this is too hard for you, just use a simple list.

Flutter project giving Out of Memory error

Currently building my first app. Getting data from firebase. Purpose is to hopefully get more people to get the COVID vaccine in Kenya.
Explanation of the code below: A user will use the search function to search for a specific county, then all vaccination posts in that county will show up with the relevant data. There are also 2 buttons, yes and no. Users can vote to let other users know if a vaccination post is still administering vaccines or not. Also, when button is pressed, they should get disabled.
I have a list that buttonPressed that when called, x number of "true" is added depending on the number of vaccination posts available. They are linked together using their index's.
Problem is after adding the buttons, I am getting an "Out of Memory" error.
Without the buttons, it runs as intended. Buttons are important because some vaccination posts are still operational while others are not.
Question:
1 - How can I get passed "Out of Memory" error?
Code:
import 'package:colour/colour.dart';
import 'package:firebase_database/firebase_database.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:google_fonts/google_fonts.dart';
import 'dart:async';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
// import 'package:shared_preferences/shared_preferences.dart';
class VaccineCenterList extends StatefulWidget {
const VaccineCenterList({key}) : super(key: key);
static const String idScreen = "VaccineCenterList";
#override
_VaccineCenterListState createState() => _VaccineCenterListState();
}
class _VaccineCenterListState extends State<VaccineCenterList> {
List<bool> buttonPressed = [];
buttonControls(numOfDrivers) {
print(numOfDrivers);
while (numOfDrivers > 0) {
buttonPressed.add(true);
}
print(buttonPressed);
}
#override
void initState() {
super.initState();
print("I'm in the vaccine list search screen");
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.grey[100],
appBar: AppBar(
backgroundColor: Colors.grey[100],
centerTitle: true,
elevation: 0,
iconTheme: const IconThemeData(
color: Colors.black,
),
title: Text(
"Pamoja",
style: GoogleFonts.lexendMega(
fontWeight: FontWeight.bold,
color: Colors.black,
fontSize: 35,
),
),
),
body: GestureDetector(
onTap: () {
FocusScope.of(context).requestFocus(FocusNode());
},
child: SingleChildScrollView(
child: Column(
children: [
Container(
// textfield
padding: const EdgeInsets.all(8.0),
child: TextField(
controller: hospitalCountyEditingController,
keyboardType: TextInputType.text,
textCapitalization: TextCapitalization.words,
decoration: InputDecoration(
border: const OutlineInputBorder(
borderSide: BorderSide(
color: Colors.black,
style: BorderStyle.solid,
width: 1,
),
),
labelText: "Search County",
labelStyle: const TextStyle(
fontSize: 14.0,
color: Colors.blueGrey,
),
hintStyle: GoogleFonts.lexendMega(
color: Colors.grey,
fontSize: 10,
),
),
style: GoogleFonts.lexendMega(
fontSize: 14,
color: Colors.black,
),
),
),
ElevatedButton(
// search button
onPressed: () {
setState(() {
FocusScope.of(context).requestFocus(
FocusNode(),
);
driverList.clear();
if (hospitalCountyEditingController.text == "" ||
hospitalCountyEditingController.text == " ") {
isTrueOrFalse = "False";
} else {
isTrueOrFalse = "True";
}
});
getHospitalDetails();
},
child: Text(
"Search",
style: GoogleFonts.lexendMega(
fontWeight: FontWeight.bold,
),
),
),
SingleChildScrollView(
child: Column(
children: [
SizedBox(
height: MediaQuery.of(context).size.height,
// height: 50,
// color: Colors.black,
child: Padding(
padding: const EdgeInsets.only(
right: 12.0,
left: 12.0,
bottom: 12.0,
),
child: driverList.isEmpty
? Center(
// child: CircularProgressIndicator(),
child: (isTrueOrFalse == "True")
? const CircularProgressIndicator()
: Column(
mainAxisAlignment:
MainAxisAlignment.center,
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
"Search for one of the counties below",
style:
GoogleFonts.lexendMega()),
),
Text(
"Nairobi, Baringo, Busia, Bomet, Bungoma, Elgeyo Marakwet, Embu, Garissa, Homa Bay, Isiolo, Kajiado, Kakamega, Kericho, Kiambu, Kilifi, Kirinyaga, Kisii, Kisumu, Kitui, Kwale, Laikipia, Lamu, Machakos, Makueni, Mandera, Marsabit, Meru, Migori, Mombasa, Muranga, Nakuru, Nandi, Narok, Nyamira, Nyandarua, Nyeri, Samburu, Siaya County, Taita Taveta, Tana River County, Tharaka Nithi, Trans Nzoia, Turkana, Uasin Gishu, Vihiga, Wajir, West Pokot",
textAlign: TextAlign.center,
style: GoogleFonts.lexendMega(
fontWeight: FontWeight.bold,
),
),
],
),
)
: ListView.builder(
itemCount: driverList.length,
itemBuilder: (context, index) {
buttonControls(driverList.length);
final Hospitals hospitals = driverList[index];
final String hospitalLocaiton =
hospitals.location;
final String hospitalPhone = hospitals.phone;
final String hospitalName = hospitals.name;
positiveCount = hospitals.positiveCount;
negativeCount = hospitals.negativeCount;
final int setpercentage =
calculatePositivePercentage(
positiveCount, negativeCount);
return Padding(
padding: const EdgeInsets.all(8.0),
child: Card(
elevation: 0,
child: ExpansionTile(
title: Text(
hospitalName.toUpperCase(),
style: GoogleFonts.lexendMega(),
textAlign: TextAlign.center,
),
children: [
Column(
children: [
Container(
child: (hospitalPhone
.isNotEmpty)
? ElevatedButton(
onPressed: () {
Clipboard.setData(
ClipboardData(
text:
hospitalPhone,
),
);
ScaffoldMessenger.of(
context)
.showSnackBar(
const SnackBar(
backgroundColor:
Colors.green,
content: Text(
"Number Copied",
textAlign:
TextAlign
.center,
),
),
);
},
child: Text(
hospitalPhone,
textAlign:
TextAlign.center,
style: GoogleFonts
.lexendMega(
fontSize: 13),
),
style: ElevatedButton
.styleFrom(
elevation: 0,
),
)
: const Text(""),
),
const SizedBox(
height: 5,
),
hospitalLocaiton.isNotEmpty
? Container(
padding:
const EdgeInsets.all(
8),
decoration: BoxDecoration(
border: Border.all(
color: Colors.black,
),
borderRadius:
BorderRadius
.circular(10),
),
child: Text(
hospitalLocaiton,
textAlign:
TextAlign.center,
style: GoogleFonts
.lexendMega(
fontSize: 12,
),
),
)
: Text(
hospitalLocaiton,
textAlign:
TextAlign.center,
style: GoogleFonts
.lexendMega(
fontSize: 12,
),
),
const SizedBox(
height: 10,
),
Text(
"$setpercentage% (percent) of voters say this hospital administer vaccines.",
textAlign: TextAlign.center,
style: GoogleFonts.lexendMega(
fontWeight: FontWeight.bold,
fontSize: 12,
color: Colors.deepPurple[400],
),
),
const SizedBox(
height: 10,
),
const Divider(
// thickness: 1,
indent: 20,
endIndent: 20,
color: Colors.black87,
),
const SizedBox(
height: 10,
),
Text(
"Does this Hospital administer Vaccines?\n(To help the public, please vote only if you know.)",
textAlign: TextAlign.center,
style: GoogleFonts.lexendMega(
fontSize: 12,
fontWeight: FontWeight.bold,
),
),
// Container(
// child: (positiveCount == 0)
// ? Text("Votes: $positiveCount")
// : Text("Votes: " +
// positiveCount.toString()),
// ),
Column(
children: [
Row(
mainAxisAlignment:
MainAxisAlignment
.spaceEvenly,
children: [
ElevatedButton(
onPressed:
buttonPressed[index]
? () {
positiveIncrement(
hospitalName,
index);
ScaffoldMessenger.of(
context)
.showSnackBar(
const SnackBar(
backgroundColor:
Colors.redAccent,
content:
Text(
"Voted",
textAlign:
TextAlign.center,
),
),
);
}
: null,
child: Text(
"Yes",
style: GoogleFonts
.lexendMega(),
),
style: ElevatedButton
.styleFrom(
primary:
Colour("#87D68D"),
),
),
ElevatedButton(
onPressed:
buttonPressed[index]
? () {
negativeIncrement(
hospitalName,
index);
ScaffoldMessenger.of(
context)
.showSnackBar(
const SnackBar(
backgroundColor:
Colors.redAccent,
content:
Text(
"Voted",
textAlign:
TextAlign.center,
),
),
);
}
: null,
child: Text(
"No",
style: GoogleFonts
.lexendMega(),
),
style: ElevatedButton
.styleFrom(
primary:
Colour("#E3655B"),
),
),
],
),
// const SizedBox(
// height: 10,
// ),
// Text(
// "Total No. of Votes: ",
// style:
// GoogleFonts.lexendMega(
// fontSize: 12),
// ),
const SizedBox(
height: 10,
),
Text(
"1 - To vote, tap once\n2 - To Undo vote, tap and hold",
style:
GoogleFonts.lexendMega(
fontSize: 12,
),
textAlign: TextAlign.start,
),
const SizedBox(
height: 10,
),
],
),
],
),
],
),
),
);
},
),
),
),
// SizedBox(height: 40),
],
),
),
],
),
),
),
);
}
}
class Hospitals {
final String name;
final String phone;
final String location;
// final String county;
final int positiveCount;
final int negativeCount;
// final int intPercentage;
// final int totalVotes;
Hospitals({
required this.name,
required this.phone,
required this.location,
// required this.county,
required this.positiveCount,
required this.negativeCount,
// required this.intPercentage,
// required this.totalVotes,
});
static Hospitals fromJson(Map<String, dynamic> json) {
return Hospitals(
name: json['HospitalName'],
phone: json['HospitalPhone'],
// county: json['county'],
location: json['HospitalAddres'],
positiveCount: json['poitiveCount'],
negativeCount: json['negativeCount'],
// intPercentage: json['intPercentage'],
// totalVotes: json['totalVotes']
);
}
}
buttonControls(numOfDrivers) {
print(numOfDrivers);
while (numOfDrivers > 0) {
buttonPressed.add(true);
}
print(buttonPressed);
}
numOfDrivers reference doesn't change over time, because it's a function parameter. Whenever you call buttonControls with numOfDrivers > 0, you get OutOfMemory.
Ask another question. It's a general problem, not related to OutOfMemory statement in title.

Flutter - Disable a button, not all buttons

I am getting a list from Firebase. The list loads as expected, However I have two issues.
1 - When the button in one item from the list is disabled, all the buttons in the other items also get disabled. I don't want this to happen. How can I get passed this?
2 - I am getting "positiveCount" and "negativeCount" from firebase RTDB. I want to get total (positiveCount + negativeCount) and then calculate the percentage of "positiveCount". (Example: positiveCount = 2, negativeCount = 2, percentage of positiveCount should be 50 percent). The problem is, ıf there is only one item that is loaded, it works perfectly. If there is more than one item loaded, I get an error.
Exception:
Exception has occurred.
UnsupportedError (Unsupported operation: Infinity or NaN toInt)
My Code:
import 'package:colour/colour.dart';
import 'package:firebase_database/firebase_database.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:google_fonts/google_fonts.dart';
import 'dart:async';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
// import 'package:shared_preferences/shared_preferences.dart';
class VaccineCenterList extends StatefulWidget {
const VaccineCenterList({key}) : super(key: key);
static const String idScreen = "VaccineCenterList";
#override
_VaccineCenterListState createState() => _VaccineCenterListState();
}
class _VaccineCenterListState extends State<VaccineCenterList> {
final databaseReference = FirebaseDatabase.instance.reference();
final firestoreInstance = FirebaseFirestore.instance;
FirebaseAuth auth = FirebaseAuth.instance;
List<Hospitals> driverList = [];
late String isTrueOrFalse = "False";
// // double percentageInt = 0.0;
int totalVotes = 0;
// int percentage = 0;
int positiveCount = 0;
int negativeCount = 0;
bool buttonPressed = true;
TextEditingController hospitalCountyEditingController =
TextEditingController();
Future<List<Hospitals>> getHospitalDetails() async {
try {
if ((hospitalCountyEditingController.text != "") &&
(hospitalCountyEditingController.text != " ")) {
databaseReference
.child("Hospitals")
.child(hospitalCountyEditingController.text)
.onValue
.listen(
(event) {
setState(
() {
var value = event.snapshot.value;
driverList = Map.from(value)
.values
.map((e) => Hospitals.fromJson(Map.from(e)))
.toList();
},
);
},
);
} else {}
} catch (e) {
}
return driverList;
}
calculatePositivePercentage(
positiveCount, negativeCount) {
// this method gets the number of "yes" and "no" votes. Then calculates the
// percentage of people who voted "yes".
// total = positiveCount + negativeCount;
// percentage = (positiveCount * 100) ~/ total;
totalVotes = positiveCount + negativeCount;
int percentage = positiveCount * 100;
double votePercentage = percentage / totalVotes;
return votePercentage;
}
#override
void initState() {
super.initState();
print("I'm in the vaccine list search screen");
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.grey[100],
appBar: AppBar(
backgroundColor: Colors.grey[100],
centerTitle: true,
elevation: 0,
iconTheme: const IconThemeData(
color: Colors.black,
),
title: Text(
"Pamoja",
style: GoogleFonts.lexendMega(
fontWeight: FontWeight.bold,
color: Colors.black,
fontSize: 35,
),
),
),
body: GestureDetector(
onTap: () {
FocusScope.of(context).requestFocus(FocusNode());
},
child: SingleChildScrollView(
child: Column(
children: [
Container(
padding: const EdgeInsets.all(8.0),
child: TextField(
controller: hospitalCountyEditingController,
keyboardType: TextInputType.text,
textCapitalization: TextCapitalization.words,
decoration: InputDecoration(
border: const OutlineInputBorder(
borderSide: BorderSide(
color: Colors.black,
style: BorderStyle.solid,
width: 1,
),
),
labelText: "Search County",
labelStyle: const TextStyle(
fontSize: 14.0,
color: Colors.blueGrey,
),
hintStyle: GoogleFonts.lexendMega(
color: Colors.grey,
fontSize: 10,
),
),
style: GoogleFonts.lexendMega(
fontSize: 14,
color: Colors.black,
),
),
),
ElevatedButton(
onPressed: () {
buttonPressed = false;
setState(() {
FocusScope.of(context).requestFocus(
FocusNode(),
);
driverList.clear();
if (hospitalCountyEditingController.text == "" ||
hospitalCountyEditingController.text == " ") {
isTrueOrFalse = "False";
} else {
isTrueOrFalse = "True";
}
});
getHospitalDetails();
},
child: Text(
"Search",
style: GoogleFonts.lexendMega(
fontWeight: FontWeight.bold,
),
),
),
SizedBox(
height: MediaQuery.of(context).size.height,
// color: Colors.black,
child: Padding(
padding: const EdgeInsets.all(12.0),
child: driverList.isEmpty
? Center(
// child: CircularProgressIndicator(),
child: (isTrueOrFalse == "True")
? const CircularProgressIndicator()
: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
"Search for one of the counties below",
style: GoogleFonts.lexendMega()),
),
Text(
"Nairobi, Baringo, Busia, Bomet, Bungoma, Elgeyo Marakwet, Embu, Garissa, Homa Bay, Isiolo, Kajiado, Kakamega, Kericho, Kiambu, Kilifi, Kirinyaga, Kisii, Kisumu, Kitui, Kwale, Laikipia, Lamu, Machakos, Makueni, Mandera, Marsabit, Meru, Migori, Mombasa, Muranga, Nakuru, Nandi, Narok, Nyamira, Nyandarua, Nyeri, Samburu, Siaya County, Taita Taveta, Tana River County, Tharaka Nithi, Trans Nzoia, Turkana, Uasin Gishu, Vihiga, Wajir, West Pokot",
textAlign: TextAlign.center,
style: GoogleFonts.lexendMega(
fontWeight: FontWeight.bold,
),
),
],
),
)
: ListView.builder(
itemCount: driverList.length,
itemBuilder: (context, int index) {
final Hospitals hospitals = driverList[index];
final String hospitalLocaiton = hospitals.location;
final String hospitalPhone = hospitals.phone;
// final int totalVotes = hospitals.totalVotes;
final String hospitalName = hospitals.name;
// final String county = hospitals.county;
positiveCount = hospitals.positiveCount;
negativeCount = hospitals.negativeCount;
// final int percentage = positiveCount * 100;
// final double percentageInt =
// percentage / totalVotes;
// ignore: unused_local_variable
final double setpercentage =
calculatePositivePercentage(positiveCount, negativeCount);
**final percentageInt = setpercentage.toInt();**
return Padding(
padding: const EdgeInsets.all(8.0),
child: Card(
elevation: 0,
child: ExpansionTile(
title: Text(
hospitalName.toUpperCase(),
style: GoogleFonts.lexendMega(),
textAlign: TextAlign.center,
),
children: [
Column(
children: [
Container(
child: (hospitalPhone.isNotEmpty)
? ElevatedButton(
onPressed: () {
Clipboard.setData(
ClipboardData(
text: hospitalPhone,
),
);
ScaffoldMessenger.of(
context)
.showSnackBar(
const SnackBar(
backgroundColor:
Colors.green,
content: Text(
"Number Copied",
textAlign:
TextAlign.center,
),
),
);
},
child: Text(
hospitalPhone,
textAlign: TextAlign.center,
style:
GoogleFonts.lexendMega(
fontSize: 13),
),
style:
ElevatedButton.styleFrom(
elevation: 0,
),
)
: const Text(""),
),
const SizedBox(
height: 5,
),
hospitalLocaiton.isNotEmpty
? Container(
padding:
const EdgeInsets.all(8),
decoration: BoxDecoration(
border: Border.all(
color: Colors.black,
),
borderRadius:
BorderRadius.circular(10),
),
child: Text(
hospitalLocaiton,
textAlign: TextAlign.center,
style: GoogleFonts.lexendMega(
fontSize: 12,
),
),
)
: Text(
hospitalLocaiton,
textAlign: TextAlign.center,
style: GoogleFonts.lexendMega(
fontSize: 12,
),
),
const SizedBox(
height: 10,
),
Text(
"$percentageInt% (percent) of voters say this hospital administer vaccines.",
textAlign: TextAlign.center,
style: GoogleFonts.lexendMega(
fontWeight: FontWeight.bold,
fontSize: 12,
color: Colors.deepPurple[400],
),
),
const SizedBox(
height: 10,
),
const Divider(
// thickness: 1,
indent: 20,
endIndent: 20,
color: Colors.black87,
),
const SizedBox(
height: 10,
),
Text(
"Does this Hospital administer Vaccines?\n(To help the public, please vote only if you know.)",
textAlign: TextAlign.center,
style: GoogleFonts.lexendMega(
fontSize: 12,
fontWeight: FontWeight.bold,
),
),
// Container(
// child: (positiveCount == 0)
// ? Text("Votes: $positiveCount")
// : Text("Votes: " +
// positiveCount.toString()),
// ),
Column(
children: [
Row(
mainAxisAlignment:
MainAxisAlignment.spaceEvenly,
children: [
ElevatedButton(
onLongPress: buttonPressed
? () {
buttonPressed = false;
ScaffoldMessenger.of(
context)
.showSnackBar(
const SnackBar(
backgroundColor:
Colors
.purpleAccent,
content: Text(
"Vote Removed",
textAlign:
TextAlign
.center,
),
),
);
undoPositiveIncrement(
hospitalName);
}
: null,
onPressed: buttonPressed ? () {
ScaffoldMessenger.of(
context)
.showSnackBar(
const SnackBar(
backgroundColor:
Colors.greenAccent,
content: Text(
"Voted Yes",
textAlign:
TextAlign.center,
),
),
);
positiveIncrement(
hospitalName);
} : null,
child: Text(
"Yes - $positiveCount",
style: GoogleFonts
.lexendMega(),
),
style:
ElevatedButton.styleFrom(
primary: Colour("#87D68D"),
),
),
ElevatedButton(
onLongPress: buttonPressed ? () {
ScaffoldMessenger.of(
context)
.showSnackBar(
const SnackBar(
backgroundColor:
Colors.purpleAccent,
content: Text(
"Vote Removed",
textAlign:
TextAlign.center,
),
),
);
undoNegativeIncrement(
hospitalName);
} : null,
onPressed: buttonPressed ? () {
ScaffoldMessenger.of(
context)
.showSnackBar(
const SnackBar(
backgroundColor:
Colors.redAccent,
content: Text(
"Voted",
textAlign:
TextAlign.center,
),
),
);
negativeIncrement(
hospitalName);
} : null,
child: Text(
"No - $negativeCount",
style: GoogleFonts
.lexendMega(),
),
style:
ElevatedButton.styleFrom(
primary: Colour("#E3655B"),
),
),
],
),
const SizedBox(
height: 10,
),
Text(
"Total No. of Votes: ",
style: GoogleFonts.lexendMega(
fontSize: 12),
),
const SizedBox(
height: 10,
),
Text(
"1 - To vote, tap once\n2 - To Undo vote, tap and hold",
style: GoogleFonts.lexendMega(
fontSize: 12,
),
textAlign: TextAlign.start,
),
const SizedBox(
height: 10,
),
],
),
],
),
],
),
),
);
},
),
),
),
],
),
),
),
);
}
}
class Hospitals {
final String name;
final String phone;
final String location;
// final String county;
final int positiveCount;
final int negativeCount;
// final int intPercentage;
// final int totalVotes;
Hospitals({
required this.name,
required this.phone,
required this.location,
// required this.county,
required this.positiveCount,
required this.negativeCount,
// required this.intPercentage,
// required this.totalVotes,
});
static Hospitals fromJson(Map<String, dynamic> json) {
return Hospitals(
name: json['HospitalName'],
phone: json['HospitalPhone'],
// county: json['county'],
location: json['HospitalAddres'],
positiveCount: json['poitiveCount'],
negativeCount: json['negativeCount'],
// intPercentage: json['intPercentage'],
// totalVotes: json['totalVotes']
);
}
}
Solution for issue 2:
calculatePositivePercentage(positiveCount, negativeCount) {
// this method gets the number of "yes" and "no" votes. Then calculates the
// percentage of people who voted "yes".
double votePercentage = 0;
if (positiveCount == 0 && negativeCount == 0) {
try {
return votePercentage.toInt();
} catch (e) {
print(e);
}
} else {
try {
totalVotes = positiveCount + negativeCount;
int percentage = positiveCount * 100;
votePercentage = percentage / totalVotes;
return votePercentage.toInt();
} catch (e) {
print(e);
}
}
}
To prevent all buttons to be disabled instead of
bool buttonPressed = true;
use
List<bool> buttonPressed = [true];
and your 2nd error is because may be you are not getting an int value from the response try
int.parse();
to parse a String to int

Inserting new Widgets as List on Pressing Button in Flutter

I am making a screen like this which could select contacts from the phone book and insert the names as lists in my application. I want is that when I press Add caregiver(+) button it should select a contact and show the name.
I made a Widget for the MOM part but whenever I click the button it rewrites the MOM to any contact that I select from the phone book.
I made this screen:
I also want to add Dad and Sister's Contact in the same manner as mom, but I am unable to do it
This is my code for the screen:
import 'package:epicare/NavigBar.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_switch/flutter_switch.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:contact_picker/contact_picker.dart';
//Check contacts permission
Future<PermissionStatus> _getPermission() async {
final PermissionStatus permission = await Permission.contacts.status;
if (permission != PermissionStatus.granted &&
permission != PermissionStatus.denied) {
final Map<Permission, PermissionStatus> permissionStatus =
await [Permission.contacts].request();
return permissionStatus[Permission.contacts] ??
PermissionStatus.undetermined;
} else {
return permission;
}
}
class CaregiverScreen extends StatefulWidget {
#override
_CaregiverScreenState createState() => _CaregiverScreenState();
}
class _CaregiverScreenState extends State<CaregiverScreen> {
final ContactPicker _contactPicker = new ContactPicker();
Contact _contact;
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
bool isSwitched = true;
#override
Widget build(BuildContext context) {
//Size size = MediaQuery.of(context).size;
return Scaffold(
key: _scaffoldKey,
backgroundColor: Colors.white,
appBar: AppBar(
backgroundColor: const Color(0xffE5E0A1),
elevation: 0,
centerTitle: true,
title: Text(
"Add Caregiver",
style: TextStyle(
fontSize: 15.0,
color: Colors.black,
fontFamily: 'Montserrat',
fontWeight: FontWeight.normal,
),
),
leading: IconButton(
icon: Icon(
Icons.arrow_back,
color: Colors.black,
),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) {
return Homepage();
},
),
);
},
),
),
body: SingleChildScrollView(
child: Container(
padding: EdgeInsets.symmetric(horizontal: 10, vertical: 40),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
MaterialButton(
onPressed: () async {
final PermissionStatus permissionStatus = await _getPermission();
if (permissionStatus == PermissionStatus.granted) {
//We can now access our contacts here
// var contactNumber = openContactBook();
Contact contact = await _contactPicker.selectContact();
setState(() {
_contact = contact;
});
}
else {
//If permissions have been denied show standard cupertino alert dialog
showDialog(
context: context,
builder: (BuildContext context) => CupertinoAlertDialog(
title: Text('Permissions error'),
content: Text('Please enable contacts access '
'permission in system settings'),
actions: <Widget>[
CupertinoDialogAction(
child: Text('OK'),
onPressed: () => Navigator.of(context).pop(),
)
],
));
}
},
color: const Color(0xffd4d411),
textColor: Colors.white,
child: Icon(
Icons.add,
size: 32,
),
padding: EdgeInsets.all(3),
shape: CircleBorder(),
),
Text(
'Add a Caregiver',
style: TextStyle(
fontFamily: 'Montserrat',
fontSize: 13,
color: const Color(0xff000000),
height: 1.5384615384615385,
fontWeight: FontWeight.w600),
textHeightBehavior:
TextHeightBehavior(applyHeightToFirstAscent: false),
textAlign: TextAlign.left,
)
],
),
_contact == null ? Container() : CaregiversList(_contact.fullName),
],
),
),
),
);
}
Widget CaregiversList(String name){
print(name);
var c = name.split(' ');
print(c[0]);
var caregiver = c[0];
var output = getInitials(string: caregiver, limitTo: 1);
print(output);
// var i = caregiver.codeUnitAt(0);
// print(i);
return Container(
padding: EdgeInsets.symmetric(vertical: 20, horizontal: 27),
child: Row(
//crossAxisAlignment: CrossAxisAlignment.center,
//mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
CircleAvatar(
radius: 24,
backgroundColor: const Color(0xffd4d411),
child: CircleAvatar(
radius: 22,
backgroundColor: Colors.white,
child: Text(
output,
style: TextStyle(
fontFamily: 'Segoe UI',
fontSize: 20,
color: const Color(0xff000000),
),
),
),
),
SizedBox(width: 19),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
caregiver,
style: TextStyle(
fontFamily: 'Montserrat',
fontSize: 13,
color: const Color(0xff000000),
height: 1.5384615384615385,
fontWeight: FontWeight.w600),
textHeightBehavior: TextHeightBehavior(
applyHeightToFirstAscent: false),
textAlign: TextAlign.left,
),
isSwitched
? Text(
"Activated",
style: TextStyle(
fontFamily: 'Montserrat',
fontSize: 10,
color: const Color(0x80232425),
fontWeight: FontWeight.w500),
textAlign: TextAlign.left,
)
: Text(
"Disabled",
style: TextStyle(
fontFamily: 'Montserrat',
fontSize: 10,
color: const Color(0x80232425),
fontWeight: FontWeight.w500),
textAlign: TextAlign.left,
),
],
),
SizedBox(width: 143),
FlutterSwitch(
width: 40.0,
height: 20.0,
value: isSwitched,
toggleSize: 15,
borderRadius: 40.0,
padding: 2.0,
showOnOff: false,
activeColor: const Color(0xffd4d411),
activeToggleColor: Colors.white,
inactiveColor: const Color(0xffDDDBAF),
inactiveToggleColor: Colors.white,
onToggle: (value) {
setState(() {
isSwitched = value;
print(isSwitched);
});
},
),
],
),
);
}
String getInitials({String string, int limitTo}) {
var buffer = StringBuffer();
var split = string.split(' ');
for (var i = 0 ; i < (limitTo ?? split.length); i ++) {
buffer.write(split[i][0]);
}
return buffer.toString();
}
}
Please help me out as i am new to Flutter.
Thank you in advance :)
You need to manage Caregiverlist you've selected from contacts. for example
class Caregiver {
String name;
bool isActive;
Caregiver({this.name, this.isActive});
factory Caregiver.fromJson(Map<String, dynamic> map) {
if (map == null) return null;
return Caregiver(name: map['name'] ?? "",
isActive: map['isActive']);
}
}
initialize caregiver list
List<Caregiver> _careList = [];
add Caregiver
Contact contact = await _contactPicker.selectContact();
setState(() {
_careList.add(Caregiver(name: contact, isActive: true));
});
show Caregiver list (To show ListView inside of Scrollview, add the following 3 lines.
ListView.separated(
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
primary: false,
itemBuilder: (context, index) {
return _caregiverWidget(index);
},
separatorBuilder: (_, __) => Divider(),
itemCount: _careList.length);
Add new function
Widget _caregiverWidget(int index) {
Caregiver _caregiver = _careList[index];
print(_caregiver.name);
var c = _caregiver.name.split(' ');
print(c[0]);
var caregiver = c[0];
var output = getInitials(string: caregiver, limitTo: 1);
print(output);
// var i = caregiver.codeUnitAt(0);
// print(i);
return Container(
padding: EdgeInsets.symmetric(vertical: 20, horizontal: 27),
child: Row(
//crossAxisAlignment: CrossAxisAlignment.center,
//mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
CircleAvatar(
radius: 24,
backgroundColor: const Color(0xffd4d411),
child: CircleAvatar(
radius: 22,
backgroundColor: Colors.white,
child: Text(
output,
style: TextStyle(
fontFamily: 'Segoe UI',
fontSize: 20,
color: const Color(0xff000000),
),
),
),
),
SizedBox(width: 19),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
caregiver,
style: TextStyle(
fontFamily: 'Montserrat',
fontSize: 13,
color: const Color(0xff000000),
height: 1.5384615384615385,
fontWeight: FontWeight.w600),
textHeightBehavior:
TextHeightBehavior(applyHeightToFirstAscent: false),
textAlign: TextAlign.left,
),
_caregiver.isActive
? Text(
"Activated",
style: TextStyle(
fontFamily: 'Montserrat',
fontSize: 10,
color: const Color(0x80232425),
fontWeight: FontWeight.w500),
textAlign: TextAlign.left,
)
: Text(
"Disabled",
style: TextStyle(
fontFamily: 'Montserrat',
fontSize: 10,
color: const Color(0x80232425),
fontWeight: FontWeight.w500),
textAlign: TextAlign.left,
),
],
),
SizedBox(width: 143),
FlutterSwitch(
width: 40.0,
height: 20.0,
value: _caregiver.isActive,
toggleSize: 15,
borderRadius: 40.0,
padding: 2.0,
showOnOff: false,
activeColor: const Color(0xffd4d411),
activeToggleColor: Colors.white,
inactiveColor: const Color(0xffDDDBAF),
inactiveToggleColor: Colors.white,
onToggle: (value) {
setState(() {
_caregiver.isActive = value;
_careList.removeAt(index);
_careList.insert(index, _caregiver);
});
},
),
],
),
);
}