Related
In my code fetching word from firebase and the user can select words and if the user selects a word and after deselect that then display and save firebase that also. And when the user selects a word then colour also.
I want to add sharedPrefences for that.
Ex: if the user selects words and clicks the next button and after closes the app and reopens later then should save the selected words and deselected words and then colour only selected words.
image
code
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:hexcolor/hexcolor.dart';
import 'package:shared_preferences/shared_preferences.dart';
class uitry extends StatefulWidget {
const uitry({Key? key}) : super(key: key);
#override
State<uitry> createState() => _uitryState();
}
class _uitryState extends State<uitry> {
//list
List<Words12> wordList = [];
//collection path
Future<List<Words12>> fetchRecords() async {
var records = await FirebaseFirestore.instance
.collection('12words')
.where("categoryName", isEqualTo: "Objects12")
.get();
return mapRecords(records);
}
List<Words12> mapRecords(QuerySnapshot<Map<String, dynamic>> records) {
var _wordList =
records.docs.map((data) => Words12.fromJson(data.data())).toList();
return _wordList;
}
#override
void initState() {
super.initState();
dropdownValueselectedWord = selectedWord.first;
checkValueSelectedWord();
dropdownValueDeselectedWord = deSelectedWord?.first;
checkValueDeselectedWord();
}
List<String> selectedWord = [];
String? dropdownValueselectedWord = "";
checkValueSelectedWord() {
_getDataSelectedWord();
}
_saveDataSelectedWord(String dropdownValueSelectedWord) async {
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
sharedPreferences.setString(
"SelectedWordObject", dropdownValueSelectedWord);
}
_getDataSelectedWord() async {
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
dropdownValueselectedWord =
sharedPreferences.getString("SelectedWordObject") ?? selectedWord.first;
setState(() {});
}
List<String>? deSelectedWord = [];
String? dropdownValueDeselectedWord = "";
checkValueDeselectedWord() {
_getDataDeselectedWord();
}
_saveDataDeselectedWord(String dropdownValueDeselectedWord) async {
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
sharedPreferences.setString(
"SelectedWordObject", dropdownValueDeselectedWord);
}
_getDataDeselectedWord() async {
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
dropdownValueselectedWord =
sharedPreferences.getString("SelectedWordObject") ??
deSelectedWord?.first;
setState(() {});
}
#override
Widget build(BuildContext context) {
double height = MediaQuery.of(context).size.height;
double width = MediaQuery.of(context).size.width;
return Scaffold(
body: Container(
decoration: const BoxDecoration(
image: DecorationImage(
image: AssetImage(Config.app_background4), fit: BoxFit.fill),
),
child: SafeArea(
child: Center(
child: SingleChildScrollView(
child: Column(
children: <Widget>[
Row(
children: <Widget>[
Expanded(
child: ListTile(
leading: GestureDetector(
child: const Icon(
Icons.arrow_back_ios_new_sharp,
color: Colors.black,
size: 24.0,
),
onTap: () => Navigator.pop(context),
),
title: const Padding(
padding: EdgeInsets.only(top: 32, right: 35),
child: Text(
"Under 18 months",
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.black,
fontSize: 18.00,
fontWeight: FontWeight.w700,
),
),
),
),
),
],
),
const SizedBox(
height: 00,
),
Padding(
padding: const EdgeInsets.only(top: 1, right: 0),
child: Column(
children: [
Material(
color: HexColor('#E92F54').withOpacity(0.9),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(0).copyWith(
topLeft: const Radius.circular(28.0),
topRight: const Radius.circular(28.0),
),
),
child: SizedBox(
width: width * 0.94,
height: height * 0.062,
child: Column(
children: const <Widget>[
SizedBox(
height: 6.5,
),
Text('Understanding',
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.w700,
fontSize: 16.0)),
Text('Object',
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.w700,
fontSize: 15.0))
],
),
),
),
Material(
color: HexColor('#FFFBFB').withOpacity(0.7),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(2).copyWith(
bottomLeft: const Radius.circular(28.0),
bottomRight: const Radius.circular(28.0),
),
),
child: SizedBox(
width: width * 0.94,
height: height * 0.30, //white box height
child: Column(
children: [
SizedBox(
height: height * 0.18,
child: SingleChildScrollView(
child: Column(
//chip words
children: <Widget>[
const SizedBox(height: 10),
FutureBuilder<List<Words12>>(
future: fetchRecords(),
builder: (context, snapshot) {
if (snapshot.hasError) {
return Text(
'Error: ${snapshot.error}');
} else {
wordList = snapshot.data ?? [];
return Wrap(
children: wordList.map(
(word) {
bool isSelected = false;
if (selectedWord!.contains(
word.wordName)) {
isSelected = true;
}
return GestureDetector(
onTap: () {
if (!selectedWord!
.contains(
word.wordName)) {
if (selectedWord!
.length <
50) {
selectedWord!.add(
word.wordName);
deSelectedWord!
.removeWhere(
(element) =>
element ==
word.wordName);
setState(() {});
print(selectedWord);
}
} else {
selectedWord!.removeWhere(
(element) =>
element ==
word.wordName);
deSelectedWord!
.add(word.wordName);
setState(() {
// selectedHobby.remove(hobby);
});
print(selectedWord);
print(deSelectedWord);
}
},
child: Container(
margin: const EdgeInsets
.symmetric(
horizontal: 5,
vertical: 4),
child: Container(
padding:
const EdgeInsets
.symmetric(
vertical: 5,
horizontal: 12),
decoration: BoxDecoration(
color: isSelected
? HexColor(
'#3A97FF')
: HexColor(
'#D9D9D9'),
borderRadius:
BorderRadius
.circular(
18),
border: Border.all(
color: isSelected
? HexColor(
'#3A97FF')
: HexColor(
'#D9D9D9'),
width: 1)),
child: Text(
word.wordName,
style: TextStyle(
color: isSelected
? Colors.black
: Colors
.black,
fontSize: 14,
fontWeight:
FontWeight
.w700),
),
),
),
);
},
).toList(),
);
}
}),
],
),
),
),
],
),
),
),
],
),
),
const SizedBox(
height: 5,
),
Padding(
padding: const EdgeInsets.only(top: 20, left: 0, bottom: 0),
child: Center(
child: SizedBox(
width: 160.0,
height: 35.0,
child: ElevatedButton(
style: ButtonStyle(
shape:
MaterialStateProperty.all<RoundedRectangleBorder>(
RoundedRectangleBorder(
borderRadius: BorderRadius.circular(18.0),
side: const BorderSide(
color: Colors.blueAccent,
),
),
),
),
onPressed: displayMessage,
child: const Text("next"),
),
),
),
),
],
),
))),
),
);
}
void displayMessage() {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => HomeScreen()),
);
final sp = context.read<SignInProvider>();
FirebaseFirestore.instance.collection("objects").doc(sp.uid).set({
"speackSE": selectedWord,
"speackUN": deSelectedWord,
});
_saveDataSelectedWord(dropdownValueselectedWord!);
_saveDataDeselectedWord(dropdownValueDeselectedWord!);
}
}
Bad State: No Element error is thrown when you're trying to access an element in an iterable at a location that does not exist. Like accessing the first or last element of the list (using the List getters like .first, .last, etc.)
You're using selectedWord.first in case the required data is not found in the prefs. Most probably, there's no item in the list which is the reason for the error.
Check all the places where you've used .first for empty lists. Make sure that the lists are not empty before calling these getters.
This is my output
all these functions are works excellent. But I tried to add sharedPrefence to these dropdowns, select birthday and to the checkbox. But both dropdowns work perfectly, When I select something in the dropdown and click the next button and close the app and reopen again then shows the words that are selected at the last. But after that, I tried to add sharedPrefence to datePicker and thin "Are you agree " check box but then shows some errors. I have no idea how to solve that.
EX:- In this, I used a date picker, Agree checkbox and in there shows "Birthday" word as an initial date and check box is unselecting, when the click selects the button then shows the dates and pick date and can select check box then value is true, That works perfectly. But I wanna add shared Preferences to this When added that, after the selected word and close the app and reopened again then should show the date and check box value true that is selected at the last.
my full code.
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
class FamilyDetailsScreen extends StatefulWidget {
#override
State<FamilyDetailsScreen> createState() => _FamilyDetailsScreenState();
}
class _FamilyDetailsScreenState extends State<FamilyDetailsScreen> {
// 1st dropdown button
#override
void initState() {
super.initState();
dropdownValueMembers = items.first;
dropdownValueNumber = number.first;
dropdownValueBirthday = birthday.first;
dropdownValueBirthday = Agree.first;
checkValueMembers();
checkValueNumber();
checkValueBirthday();
checkValueAgree();
}
String? dropdownValueMembers;
// List of items in our dropdown menu
List<String> items = [
'howmany',
'one',
'two',
'three ',
'four',
'5 or more'
];
checkValueMembers() {
_getData();
}
_saveData(String dropdownValueMembersShared) async {
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
sharedPreferences.setString("data", dropdownValueMembersShared);
}
_getData() async {
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
dropdownValueMembers = sharedPreferences.getString("data") ?? items.first;
setState(() {});
}
// 2nd dropdown button
// data which child
String? dropdownValueNumber;
// // List of items in our dropdown menu
List<String> number = ['which', '1 st', '2 nd', '3 rd ', '4 th ', '5 th'];
//IF "dropdownValueMembers" is empty pass "which" word as a initial value if al ready selected then pass the shared preference value
checkValueNumber() {
_getDataNumber();
}
_saveDataNumbers(String dropdownValueNumberShared) async {
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
sharedPreferences.setString("data2", dropdownValueNumberShared);
}
_getDataNumber() async {
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
dropdownValueNumber = sharedPreferences.getString("data2") ?? number.first;
setState(() {});
}
//date picker
DateTime? selectedDate;
DateTime now = new DateTime.now();
void showDatePicker() {
DateTime mindate = DateTime(now.year - 2, now.month, now.day - 29);
DateTime maxdate = DateTime(now.year - 1, now.month, now.day);
showCupertinoModalPopup(
context: context,
builder: (BuildContext builder) {
return Container(
height: MediaQuery.of(context).copyWith().size.height * 0.25,
color: Colors.white,
child: CupertinoDatePicker(
mode: CupertinoDatePickerMode.date,
initialDateTime: mindate,
onDateTimeChanged: (value) {
if (value != null && value != selectedDate) {
setState(() {
selectedDate = value;
});
}
},
maximumDate: maxdate,
minimumDate: mindate,
),
);
});
}
String? dropdownValueBirthday;
List<String> birthday = [
'Birthday',
];
//sharedPreferences birthday
checkValueBirthday() {
_getDataBirthday();
}
_saveDataBirthday(String dropdownValueBirthdayShared) async {
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
sharedPreferences.setString("dataBirthday", dropdownValueBirthdayShared);
}
_getDataBirthday() async {
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
dropdownValueBirthday =
sharedPreferences.getString("dataBirthday") ?? birthday.first;
setState(() {});
}
//////////////////////////////////
// are you agree button
//boolean value (are you agree)
bool isChecked = false;
checkValueAgree() {
_getDataAgree();
}
_saveDataAgree(String dropdownValueAgreeShared) async {
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
sharedPreferences.setBool("Agree", dropdownValueAgreeShared);
}
_getDataAgree() async {
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
dropdownValueNumber = sharedPreferences.getBool("Agree") ?? isChecked.first;
setState(() {});
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
resizeToAvoidBottomInset: false,
body: SafeArea(
child: Column(
children: <Widget>[
const Text(
'family details',
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.black,
fontSize: 18.00,
fontWeight: FontWeight.w700,
),
),
const SizedBox(
height: 30,
),
Padding(
padding: const EdgeInsets.only(top: 10, left: 15),
child: Row(
children: <Widget>[
const Icon(
Icons.brightness_1,
color: Colors.black,
size: 10.0,
),
const Padding(
padding: EdgeInsets.only(left: 13),
child: Text(
"Number of children",
style:
TextStyle(fontSize: 15, fontWeight: FontWeight.w600),
),
),
],
),
),
const SizedBox(
height: 25,
),
Row(
children: [
Padding(
padding: const EdgeInsets.only(left: 2),
child: Container(
height: 25,
decoration: BoxDecoration(
boxShadow: const <BoxShadow>[
//apply shadow on Dropdown button
BoxShadow(
color: Color.fromRGBO(
0, 0, 0, 0.37), //shadow for button
blurRadius: 5) //blur radius of shadow
],
color: Colors.white,
borderRadius: BorderRadius.circular(15),
),
child: DropdownButton(
underline: Container(),
borderRadius: BorderRadius.circular(20),
// Initial Value
value: dropdownValueMembers,
// Down Arrow Icon
icon: const Icon(Icons.keyboard_arrow_down),
// Array list of items
items: items.map((String data) {
return DropdownMenuItem(
value: data,
child: SizedBox(
height: 15,
width: 120.0, // for example
child: Text(data,
style: const TextStyle(
fontSize: 13.0,
fontWeight: FontWeight.w700),
textAlign: TextAlign.center),
),
);
}).toList(),
// After selecting the desired option,it will
// change button value to selected value
onChanged: (String? newValue) {
setState(
() {
dropdownValueMembers = newValue!;
},
);
},
),
),
),
],
),
Row(
children: [
Padding(
padding: const EdgeInsets.only(left: 20),
child: Text('Which child'),
),
Padding(
padding: const EdgeInsets.only(left: 100, right: 0, top: 20),
child: Container(
height: 30,
decoration: BoxDecoration(
boxShadow: const <BoxShadow>[
//apply shadow on Dropdown button
BoxShadow(
color: Color.fromRGBO(
0, 0, 0, 0.37), //shadow for button
blurRadius: 5) //blur radius of shadow
],
color: Colors.white,
borderRadius: BorderRadius.circular(15),
),
child: DropdownButton(
underline: Container(),
borderRadius: BorderRadius.circular(20),
// Initial Value
value: dropdownValueNumber,
// Down Arrow Icon
icon: const Icon(Icons.keyboard_arrow_down),
// Array list of items
items: number.map((String number) {
return DropdownMenuItem(
value: number,
child: SizedBox(
height: 17,
width: 120.0, // for example
child: Text(number,
style: const TextStyle(
fontSize: 13.0,
fontWeight: FontWeight.w700),
textAlign: TextAlign.center),
),
);
}).toList(),
// After selecting the desired option,it will
// change button value to selected value
onChanged: (String? newNumber) {
setState(
() {
dropdownValueNumber = newNumber!;
},
);
},
),
),
),
],
),
const SizedBox(
height: 60,
),
Padding(
padding: const EdgeInsets.only(left: 15),
child: Row(
children: <Widget>[
const Icon(
Icons.brightness_1,
color: Colors.black,
size: 10,
),
const Padding(
padding: EdgeInsets.only(left: 15.0),
child: Text("birthday",
style: TextStyle(
fontSize: 16.0,
)),
),
Padding(
padding: const EdgeInsets.only(left: 25.0),
child: SizedBox(
width: 110.0,
height: 25.0,
child: DecoratedBox(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12),
color: Colors.white,
),
child: Center(
child: Text(
selectedDate == null
? (dropdownValueBirthday ?? birthday.first)
: '${selectedDate?.year}/${selectedDate?.month}/${selectedDate?.day} ',
style: const TextStyle(
fontSize: 16, fontWeight: FontWeight.w500),
),
),
),
),
),
Padding(
padding: const EdgeInsets.only(left: 15.0),
child: SizedBox(
width: 88.0,
height: 25.0,
child: MaterialButton(
onPressed: showDatePicker,
shape: const StadiumBorder(),
color: Colors.blue,
child: const Text(
'select',
style: TextStyle(color: Colors.white, fontSize: 12),
),
),
),
),
],
),
),
Padding(
padding: const EdgeInsets.only(left: 15.0),
child: Row(
children: <Widget>[
const Icon(
Icons.brightness_1,
color: Colors.black,
size: 10,
),
const Padding(
padding: EdgeInsets.only(left: 15.0),
child: Text(
"Are you agree",
style:
TextStyle(fontSize: 16, fontWeight: FontWeight.w500),
),
),
const Padding(
padding: EdgeInsets.only(left: 30),
child: Text(
'yes',
style:
TextStyle(fontSize: 15, fontWeight: FontWeight.bold),
),
),
Checkbox(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8.0),
),
side: MaterialStateBorderSide.resolveWith(
(states) =>
BorderSide(width: 3.0, color: Colors.blueAccent),
),
value: isChecked,
onChanged: (bool? value) {
setState(() {
isChecked = value!;
});
},
),
],
),
),
Padding(
padding: const EdgeInsets.only(bottom: 0.0, top: 150),
child: SizedBox(
width: 160.0,
height: 35.0,
child: ElevatedButton(
style: ButtonStyle(
shape: MaterialStateProperty.all<RoundedRectangleBorder>(
RoundedRectangleBorder(
borderRadius: BorderRadius.circular(18.0),
side: const BorderSide(
color: Colors.blueAccent,
),
),
),
),
onPressed: () {
//do null check 1st
_saveData(dropdownValueMembers!);
_saveDataNumbers(dropdownValueNumber!);
_saveDataBirthday(dropdownValueBirthday!);
_saveDataAgree(isChecked!);
},
child: const Text('next')),
),
),
],
),
),
);
}
}
How to solve and how to add sharedPreference to this datepicker and to checkbox
Lot's of ways to go about it. Simplist way in your case, get rid of all the setStates in all your methods except the last one. You're layering all those setStates and they're calling while other things are still awaiting.
I suggest awaiting each method before calling any setState. You can't await in the initState, but in the first method, call the each of the subsequent ones with awaits from there. So just call checkValueMembers(); (or create a new one getAllValues or whatever).
Within getAllValues, await all the other methods.
Then you can be sure that everything is done, and finally, call setState this way:
WidgetsBinding.instance.addPostFrameCallback((_) {
setState((){});
});
It ensures you don't call setState until the entire widget tree is done.
Entire thing could look like this: remember to get rid of all the other setStates
Future checkValueMembers() async {
await _getData();
await _getDataNumber();
await _getDataBirthday();
await _getDataAgree();
WidgetsBinding.instance.addPostFrameCallback((_) {
setState((){});
});
}
I am trying to create the build method without side effects (without blinking). I solved this problem using StatefulBuilder, but I read that I should rebuild 1000x times without any change or effect.
The Staggered Grid View Builder Widget are rebuilt when the keyboard is opening, or whenever I open again the page, or add/remove an item from it. That's good, normally, but with side effects like you see below. Maybe there is any solution to animate the remove/add functionality, or the infinite reloading and keep the rest of the items in cache. So I need to limit the builder recreate inside Grid View Builder?
On other applications I don't see this ugly "blinking". Where is the problem and how can I solve it? I used Animation Limiter but it's not working for me, neither PrecacheImage, somehow I need to rebuild without blink (first items).
My code:
class VisionBoard extends StatefulWidget {
const VisionBoard({Key? key}) : super(key: key);
#override
_VisionBoardState createState() => _VisionBoardState();
}
class _VisionBoardState extends State<VisionBoard> with SingleTickerProviderStateMixin {
ScreenshotController screenshotController = ScreenshotController();
String saveGoalsButtonText = "SAVE GOALS";
String wallpaperButtonText = "CREATE WALLPAPER";
String saveWallpaperButtonText = "SAVE";
bool createWallpaper = false;
bool isWallpaperCreated = false;
late File imageFile;
late String newImage;
late Uint8List imageRaw;
int noOfImages = 0;
late Uint8List wallpaperBytes;
String title = "My Vision Board";
String goals = "";
late List<String> visions = <String>[];
final TextEditingController _textFieldController = TextEditingController();
final TextEditingController _goalsController = TextEditingController();
static final _formKey = GlobalKey<FormState>();
#override
void initState() {
super.initState();
loadVisionBoardTitleAndImages();
}
void loadVisionBoardTitleAndImages() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
//await prefs.clear();
setState(() {
_textFieldController.text = prefs.getString('titlu') ?? title;
visions = prefs.getStringList('visions') ?? <String>[];
_goalsController.text = prefs.getString('goals') ?? goals;
});
}
void _removeVisions(int index) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
setState(() {
isButtonDisabled=true;
visions.removeAt(index);
prefs.setStringList('visions', visions);
createWallpaper = false;
wallpaperButtonText = "CREATE WALLPAPER";
isWallpaperCreated = false;
});
await CreateWallpaperLayouts().createWallpaper(visions).then((value) {
setState(() {
wallpaperBytes = value;
wallpaper = Image.memory(wallpaperBytes);
precacheImage(wallpaper.image, context);
isButtonDisabled=false;
});
});
}
#override
Widget build(BuildContext context) {
return Sizer(
builder: (context, orientation, deviceType) {
return GestureDetector(
onTap: () {
FocusScopeNode currentFocus = FocusScope.of(context);
if (!currentFocus.hasPrimaryFocus) {
currentFocus.unfocus();
}
},
child: Scaffold(
body: AnimationLimiter(
child: Container(
decoration: const BoxDecoration(
image: DecorationImage(
image: AssetImage("assets/background-marmura.jpeg"), fit: BoxFit.cover)),
child: SafeArea(
child: SingleChildScrollView(
child: Container(
margin: const EdgeInsets.fromLTRB(20, 0, 20, 0),
child: Column(
children: [
StatefulBuilder(
builder: (BuildContext context, StateSetter setState) {
return Row(
children: [
Flexible(
child: Text(_textFieldController.text,
style: const TextStyle(
fontWeight: FontWeight.w700,
fontSize: 21,
color: Color(0xff393432),
),
),
),
IconButton(
icon: const Icon(
Icons.edit,
size: 21,
color: Color(0xff393432),
),
onPressed: () {
showAlertDialog(context, setState);
},
)
]);
}
),
const SizedBox(height: 5),
GridView.builder(
clipBehavior: Clip.none,
physics: const ScrollPhysics(),
shrinkWrap: true,
gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
maxCrossAxisExtent: SizeConfig.screenWidth!/3,),
itemCount: (visions.length == 12) ? visions.length : visions.length + 1,
itemBuilder: (BuildContext ctx, index) {
if (index < visions.length) {
return AnimationConfiguration.staggeredGrid(
position: index,
duration: const Duration(milliseconds: 1000),
columnCount: 3,
child: ScaleAnimation(
child: FadeInAnimation(
child: OpacityAnimatedWidget.tween(
opacityEnabled: 1, //define start value
opacityDisabled: 0, //and end value
enabled: index < visions.length, //bind with the boolean
child: Stack(
alignment: Alignment.center,
children: [
Container(
width: 25.w,
height: 25.w,
decoration: BoxDecoration(
image: DecorationImage(
image: CleverCloset.imageFromBase64String(visions[index]).image,
fit: BoxFit.fill),
borderRadius: const BorderRadius.all(
Radius.circular(
5.0) // <--- border radius here
),
),
),
Positioned(
top:0,
right:0,
child: ClipOval(
child: InkWell(
onTap: () {
_removeVisions(index);
},
child: Container(
padding: const EdgeInsets.all(5),
color: Colors.white,
child:
const Icon(
Icons.delete,
size: 16,
color: Color(0xff393432)),
),
),
),
),
],
clipBehavior: Clip.none,
),
),
),
),
);
}
else if(index<12){
return InkWell(
onTap: () {
_openGallery(context);
},
child:
Stack(
alignment: Alignment.center,
children:[
Container(
width: 25.w,
height: 25.w,
decoration:
BoxDecoration(
border: Border.all(color: const Color(0xff393432)),
borderRadius: const BorderRadius.all(Radius.circular(5.0)),
),
child:
const Icon(
Icons.add,
size: 25,
color: Color(0xff393432),
)
),
],
),
);
}
else {
return Container(color: Colors.red);
}
}
),
const SizedBox(height: 10),
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: const [
Text("You can add up to 12 pictures.",
style: TextStyle(
fontSize: 15,
fontWeight: FontWeight.w400,
fontStyle: FontStyle.italic,
),),
],
),
const SizedBox(height: 10),
StatefulBuilder(
builder: (BuildContext context, StateSetter setState) {
return Column (
children: [
if(visions.isNotEmpty && visions.length>1 && !isWallpaperCreated) Row(
children: [
SizedBox(
width: 50.w,
child: OpacityAnimatedWidget.tween(
opacityEnabled: 1, //define start value
opacityDisabled: 0, //and end value)
enabled: !isWallpaperCreated &&
visions.isNotEmpty && visions.length > 1,
child: OutlinedButton(
onPressed: visions.isNotEmpty &&
visions.length > 1 ? () async{
setState(() {
wallpaperButtonText = "CREATING...";
//_createWallpaper();
});
wallpaperBytes = await CreateWallpaperLayouts().createWallpaper(visions);
setState(() {
noOfImages = visions.length;
isWallpaperCreated = true;
createWallpaper = true;
});
//Navigator.pushReplacementNamed(context, '/masterclasses');
} : null,
style: OutlinedButton.styleFrom(
primary: const Color(0xffE4BCB4),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(
18.0),
),
side: const BorderSide(
width: 3, color: Color(0xffE4BCB4)),
),
child: Text(
wallpaperButtonText,
style: const TextStyle(
color: Color(0xff393432),
fontSize: 14,
fontWeight: FontWeight.w700,
)
),
),
),
),
],
),
const SizedBox(height:40),
if(createWallpaper==true) OpacityAnimatedWidget.tween(
opacityEnabled: 1, //define start value
opacityDisabled: 0, //and end value
enabled: createWallpaper, //bind with the boolean
child: Row(
children: const [
Flexible(
child: Text("Wallpaper",
style: TextStyle(
fontWeight: FontWeight.w700,
fontSize: 21,
color: Color(0xff393432),
),
),
),
],
),
),
if(createWallpaper==true) const SizedBox(height:15),
if(createWallpaper==true)
OpacityAnimatedWidget.tween(
opacityEnabled: 1, //define start value
opacityDisabled: 0, //and end value
enabled: createWallpaper,
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children:[ Container(
width: 50.w,//double.infinity,
height: 50.h,//SizeConfig.screenHeight,
decoration: BoxDecoration(
image: DecorationImage(
image: Image.memory(wallpaperBytes).image,
fit: BoxFit.fill,
)
),
//child: CreateWallpaperLayouts().createWallpaper(visions),
),],
),
),
if(createWallpaper==true) const SizedBox(height:10),
if(createWallpaper==true) StatefulBuilder(
builder: (BuildContext context, StateSetter setState) {
return OpacityAnimatedWidget.tween(
opacityEnabled: 1, //define start value
opacityDisabled: 0, //and end value
enabled: createWallpaper,
child: Row(
children: [
SizedBox(
width: 50.w,
child: OutlinedButton(
onPressed: () {
_saveWallpaper(wallpaperBytes);
setState(() {
saveWallpaperButtonText = "SAVED!";
});
Future.delayed(const Duration(milliseconds: 1300), () {
setState(() {
saveWallpaperButtonText = "SAVE";
});
});
//Navigator.pushReplacementNamed(context, '/masterclasses');
},
style: OutlinedButton.styleFrom(
primary: const Color(0xffE4BCB4),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(18.0),
),
side: const BorderSide(width: 3, color: Color(0xffE4BCB4)),
),
child: Text(
saveWallpaperButtonText,
style: const TextStyle(
color: Color(0xff393432),
fontSize: 14,
fontWeight: FontWeight.w700,
)
),
),
),
const SizedBox(width: 10),
],
),
);
}
),
if(createWallpaper==true) const SizedBox(height:50),
Row(
children: const [
Flexible(
child: Text("Goals & Affirmations",
style: TextStyle(
fontWeight: FontWeight.w700,
fontSize: 21,
color: Color(0xff393432),
),
),
),
],
),
],
);
}
),
const SizedBox(height: 10),
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: const [
Text("Add goals and affirmations.",
style: TextStyle(
fontSize: 15,
),),
],
),
const SizedBox(height: 10),
StatefulBuilder(
builder: (BuildContext context, StateSetter setState) {
return Column(
children: [
Card(
elevation: 0,
color: const Color(0xffEFEFEF),
child: Padding(
padding: const EdgeInsets.all(10.0),
child: TextFormField(
key: _formKey,
controller: _goalsController,
maxLines: 8,
decoration: const InputDecoration(border: InputBorder.none),
),
)
),
const SizedBox(height: 10),
Row(
children: [
Container(
width: 50.w,
margin: const EdgeInsets.fromLTRB(0, 0, 0, 40),
child: OutlinedButton(
onPressed: () async{
setState(() {
saveGoalsButtonText = "SAVED!";
});
Future.delayed(const Duration(seconds: 1), () {
setState(() {
saveGoalsButtonText = "SAVE GOALS";
});
});
SharedPreferences prefs = await SharedPreferences.getInstance();
setState(() {
goals = _goalsController.text;
prefs.setString('goals', goals);
});
//Navigator.pushReplacementNamed(context, '/masterclasses');
},
style: OutlinedButton.styleFrom(
primary: const Color(0xffE4BCB4),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(18.0),
),
side: const BorderSide(width: 3, color: Color(0xffE4BCB4)),
),
child: Text(
saveGoalsButtonText,
style: const TextStyle(
color: Color(0xff393432),
fontSize: 14,
fontWeight: FontWeight.w700,
)
),
),
),
],
),
],
);
}
),
],
),
),
),
),
),
),
),
);
}
);
}
}
This Error Showing When i Click On Notification Navigation Item from Profile Page To Notification
Exception has occurred. FlutterError (setState() called after
dispose(): _MyProfileState#c3ad1(lifecycle state: defunct, not
mounted) This error happens if you call setState() on a State object
for a widget that no longer appears in the widget tree (e.g., whose
parent widget no longer includes the widget in its build). This error
can occur when code calls setState() from a timer or an animation
callback. The preferred solution is to cancel the timer or stop
listening to the animation in the dispose() callback. Another solution
is to check the "mounted" property of this object before calling
setState() to ensure the object is still in the tree. This error might
indicate a memory leak if setState() is being called because another
object is retaining a reference to this State object after it has been
removed from the tree. To avoid memory leaks, consider breaking the
reference to this object during dispose().)
Profile Page :
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:play_big_win/constants.dart';
import 'package:play_big_win/services/firebase-auth-helper.dart';
class MyProfile extends StatefulWidget {
#override
_MyProfileState createState() => _MyProfileState();
}
class _MyProfileState extends State<MyProfile> {
final firebaseUser = FirebaseAuth.instance.currentUser;
final db = FirebaseFirestore.instance;
String fullname = '';
String email = '';
#override
void dispose() {
SystemChrome.setEnabledSystemUIOverlays(SystemUiOverlay.values);
super.dispose();
}
#override
initState() {
SystemChrome.setEnabledSystemUIOverlays([]);
super.initState();
}
getData() async {
while (mounted) {
dynamic names = await FirebaseAuthHelper().getCurrentUserData();
if (names != null) {
fullname = names[0];
email = names[1];
setState(() {});
} else {
print("Nulllll");
}
}
}
#override
Widget build(BuildContext context) {
getData();
return Scaffold(
backgroundColor: kPrimaryColor,
body: SafeArea(
child: ListView(
shrinkWrap: true,
children: [
SizedBox(
height: 20,
),
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.all(
Radius.circular(15),
),
),
width: MediaQuery.of(context).size.width - 25,
height: 150,
child: Row(
children: [
CircleAvatar(
radius: 60.0,
backgroundImage: NetworkImage(
'https://res.cloudinary.com/dqunmzmqo/image/upload/v1606248032/male-clipart-avatar_ewaerc.png',
),
),
Padding(
padding: const EdgeInsets.only(top: 45.0),
child: Column(
children: [
Text(
"Name: $fullname",
style: TextStyle(
fontSize: 14,
),
),
SizedBox(
height: 10,
),
Text(
"Email: $email",
style: TextStyle(
fontSize: 14,
),
),
SizedBox(
height: 10,
),
Text(
"Refer Code: Xasdsas",
style: TextStyle(
fontSize: 14,
),
)
],
),
),
],
),
),
Padding(
padding: const EdgeInsets.only(top: 8.0),
child: Text(
'Play Big Win Big',
style: TextStyle(
fontFamily: 'Pacifico',
fontSize: 20.0,
color: Colors.white,
),
),
),
SizedBox(
height: 5,
),
Text(
'V1.0',
style: TextStyle(
fontSize: 10.0,
letterSpacing: 2.5,
color: Colors.teal.shade100,
fontWeight: FontWeight.bold,
),
),
SizedBox(
height: 20.0,
width: 150.0,
child: Divider(
color: Colors.teal.shade100,
),
),
GestureDetector(
onTap: () {
// Navigator.push(
// context,
// MaterialPageRoute(
// builder: (context) => MyprivacyPolicy(),
// ));
},
child: Card(
color: Colors.white,
margin:
EdgeInsets.symmetric(vertical: 10.0, horizontal: 25.0),
child: ListTile(
leading: Icon(
Icons.group_add,
color: Colors.teal,
),
title: Text(
'Invite Friends',
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 17.0,
color: Colors.teal.shade900,
),
),
),
),
),
GestureDetector(
onTap: () {
// Navigator.push(
// context,
// MaterialPageRoute(
// builder: (context) => MyprivacyPolicy(),
// ));
},
child: Card(
color: Colors.white,
margin:
EdgeInsets.symmetric(vertical: 10.0, horizontal: 25.0),
child: ListTile(
leading: Icon(
Icons.question_answer,
color: Colors.teal,
),
title: Text(
"FAQ's",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 17.0,
color: Colors.teal.shade900,
),
),
),
),
),
GestureDetector(
onTap: () {
// Navigator.push(
// context,
// MaterialPageRoute(
// builder: (context) => MyprivacyPolicy(),
// ));
},
child: Card(
color: Colors.white,
margin:
EdgeInsets.symmetric(vertical: 10.0, horizontal: 25.0),
child: ListTile(
leading: Icon(
Icons.privacy_tip,
color: Colors.teal,
),
title: Text(
'Privacy Policy',
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 17.0,
color: Colors.teal.shade900,
),
),
),
),
),
GestureDetector(
onTap: () {
// Navigator.push(
// context,
// MaterialPageRoute(
// builder: (context) => TermsandCondtions(),
// ));
},
child: Card(
color: Colors.white,
margin:
EdgeInsets.symmetric(vertical: 10.0, horizontal: 25.0),
child: ListTile(
leading: Icon(
Icons.auto_fix_normal,
color: Colors.teal,
),
title: Text(
'Terms & Conditions',
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 17.0,
color: Colors.teal.shade900,
),
),
),
),
),
],
),
],
),
),
);
}
}
Notification Page:
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import '../../constants.dart';
class MyNotification extends StatefulWidget {
#override
_MyNotificationState createState() => _MyNotificationState();
}
class _MyNotificationState extends State<MyNotification> {
#override
void dispose() {
SystemChrome.setEnabledSystemUIOverlays(SystemUiOverlay.values);
super.dispose();
}
#override
initState() {
SystemChrome.setEnabledSystemUIOverlays([]);
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
centerTitle: true,
backgroundColor: kPrimaryColor,
title: Text(
"Notifications",
),
),
body: Center(
child: Padding(
padding: const EdgeInsets.all(15.0),
child: Container(
decoration: BoxDecoration(
color: Colors.deepPurple,
borderRadius: BorderRadius.all(
Radius.circular(
20,
),
),
),
height: 300,
width: MediaQuery.of(context).size.width,
child: Center(
child: Padding(
padding: const EdgeInsets.all(12.0),
child: Text(
"Today Is Your sadsadasdas das das dsa sa dsa dsad asd as das asd sad asd asds das sa dsa",
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.w600,
),
),
),
),
),
),
),
);
}
}
My Authenticate Code:
Future getCurrentUserData() async {
try {
DocumentSnapshot ds = await users.doc(firebaseUser.uid).get();
String fullname = ds.get('full_name');
String email = ds.get('email');
return [fullname, email];
} catch (e) {
print(e.toString());
return null;
}
}
This Code Which I Call in Profile Page:
getData() async {
while (mounted) {
dynamic names = await FirebaseAuthHelper().getCurrentUserData();
if (names != null) {
fullname = names[0];
email = names[1];
setState(() {});
} else {
print("Null");
}
}
}
You are using setState in async function, After an await, your widget may not be mounted anymore. Doing setState gives you an exception at that time. use the below code or place it at any other place
if (this.mounted) {
setState(() {
});
}
or more clear approach override setState
#override
void setState(fn) {
if(mounted) {
super.setState(fn);
}
}
I have a question palette in the flutter screen, where a user taps on the question number that question is shown, and a next button to display the next question.
If I am traversing between the questions using the question palette it's working fine but when I click next button, it does not turn the question number on the palette to green(I want that question number to get green) and also it does not return the next question but the loop iterates. As after I press the button for some time, it says that there are no next questions as I have set this message when the loop ends.
Here is my code:
class quizpage extends StatefulWidget{
var questions,surveyid;
quizpage(this.questions,this.surveyid);
//quizpage({Key key, #required this.questions}) : super(key : key);
#override
_quizpageState createState() => _quizpageState(questions,surveyid);
}
class _quizpageState extends State<quizpage> with SingleTickerProviderStateMixin {
var questions,surveyid;
_quizpageState(this.questions,this.surveyid);
int i = 0;
int flag = 0;
int counter = 0;
int length;
Map<String, Color> btncolor = {
"1" : Colors.grey,
"2" : Colors.grey,
"3" : Colors.grey,
"4" : Colors.grey,
"5" : Colors.grey,
"6" : Colors.grey,
"7" : Colors.grey,
"8" : Colors.grey,
"9" : Colors.grey,
};
final answercontroller = TextEditingController();
#override
Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations([
DeviceOrientation.portraitDown, DeviceOrientation.portraitUp
]);
SizeConfig().init(context);
// TODO: implement build
return Scaffold(
body: SingleChildScrollView(
scrollDirection: Axis.vertical,
child: SizedBox(
height: 600,
child: Column(
children: <Widget>[
Expanded(
flex: 1,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Numberofquestion()
],
),
),
Expanded(
flex: 4,
child: Center(
child: Container(
width: 400,
height: 400,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Container(
width: 250,
child: Material(
elevation: 5,
color: Colors.deepOrange,
borderRadius: BorderRadius.all(
Radius.circular(10.0)),
child: TextField(
enabled: false,
maxLines: 6,
decoration: InputDecoration(
fillColor: Colors.white,
filled: true,
hintText: questions[i]
),
style: TextStyle(
fontSize: 20,
color: Colors.black
),
),
),
)
],
),
),
)
),
Expanded(
flex: 2,
child: Center(
child: Container(
width: 300,
height: 300,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Container(
width: 250,
child: Material(
elevation: 2,
color: Colors.deepOrange,
borderRadius: BorderRadius.all(
Radius.circular(10.0)),
child: TextField(
controller: answercontroller,
maxLines: 1,
//enabled: false,
decoration: InputDecoration(
fillColor: Colors.white,
filled: true,
hintText: 'Answer'
),
style: TextStyle(
fontSize: 20,
color: Colors.black
),
),
),
),
]
)
)
)
),
Expanded(
flex: 2,
child: Align(
alignment: Alignment.topCenter,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
RaisedButton(onPressed: SkipQuestion,
color: Colors.deepOrange,
textColor: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(10.0))),
child: Text('Skip',
style: TextStyle(
fontSize: 20
),
),
),
RaisedButton(onPressed: NextQuestion,
color: Colors.green,
textColor: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(10.0))),
child: Text('Next',
style: TextStyle(
fontSize: 20
),
),
),
],
),
],
),
)
)
],
),
),
),
),
);
}
#override
void setState(fn) {
// TODO: implement setState
super.setState(fn);
if(btncolor[(i+1).toString()] == Colors.deepOrange){
btncolor[(i+1).toString()] = Colors.purple;
flag = 1;
}
else if(btncolor[(i+1).toString()] == Colors.green){
btncolor[(i+1).toString()] = Colors.purple;
flag = 2;
}
else{
btncolor[(i+1).toString()] = Colors.purple;
}
}
void NextQuestion() async {
if(answercontroller.text.length == 0){
await showDialog(
context: context,
builder: (context) => new AlertDialog(
title: new Text('Alert'),
content: Text(
'Please enter an answer.'),
actions: <Widget>[
new FlatButton(
onPressed: () {
Navigator.of(context, rootNavigator: true)
.pop(); // dismisses only the dialog and returns nothing
},
child: new Text('OK'),
),
],
),
);
}
else{
setState(() async {
if(i < (questions.length - 1)){
// ignore: unnecessary_statements
btncolor[(i+1).toString()] = Colors.green;
i++;
}
else{
await showDialog(
context: context,
builder: (context) => new AlertDialog(
title: new Text('Alert'),
content: Text(
'There are no next questions.'),
actions: <Widget>[
new FlatButton(
onPressed: () {
Navigator.of(context, rootNavigator: true)
.pop(); // dismisses only the dialog and returns nothing
},
child: new Text('OK'),
),
],
),
);
}
});
}
}
#override
void initState() {
SystemChrome.setEnabledSystemUIOverlays([]);
super.initState();
}
void SkipQuestion() {
setState(() {
if(i < (questions.length - 1)){
// ignore: unnecessary_statements
btncolor[(i+1).toString()] = Colors.deepOrange;
i++;
}
else{
Navigator.of(context).pushReplacement(MaterialPageRoute(
builder: (context) => resultpage(surveyid),
));
}
});
}
void ChooseQuestion() {
setState(() {
if(i < (questions.length)){
for(int k =0; k< (questions.length); k++){
if(k != i){
if(btncolor[(k+1).toString()] == Colors.purple){
if(flag == 1){
btncolor[(k+1).toString()] = Colors.red;
flag =0;
}
else if(flag == 2){
btncolor[(k+1).toString()] = Colors.green;
flag =0;
}
else{
btncolor[(k+1).toString()] = Colors.grey;
}
}
}
else{
if(btncolor[(k+1).toString()] == Colors.purple){
if(flag == 1){
btncolor[(k+1).toString()] = Colors.red;
}
else if(flag == 2){
btncolor[(k+1).toString()] = Colors.green;
flag =0;
}
else{
btncolor[(k+1).toString()] = Colors.grey;
}
}
}
}
//i++;
}
else{
Navigator.of(context).pushReplacement(MaterialPageRoute(
builder: (context) => resultpage(surveyid),
));
}
});
}
Widget Numberofquestion() {
if(questions.length == 9){
return Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Container(
width: 40,
padding: EdgeInsets.all(5),
child: RaisedButton(onPressed: () {
i = 0;
ChooseQuestion();
},
color: btncolor["1"],
textColor: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(10.0))),
child: Text("1",
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 20
),
),
),
),
Container(
width: 40,
padding: EdgeInsets.all(5),
child: RaisedButton(onPressed: () {
i = 1;
ChooseQuestion();
},
color: btncolor["2"],
textColor: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(10.0))),
child: Text('2',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 20
),
),
),
),
Container(
width: 40,
padding: EdgeInsets.all(5),
child: RaisedButton(onPressed: () {
i = 2;
ChooseQuestion();
},
color: btncolor["3"],
textColor: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(10.0))),
child: Text('3',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 20
),
),
),
),
Container(
width: 40,
padding: EdgeInsets.all(5),
child: RaisedButton(onPressed: () {
i = 3;
ChooseQuestion();
},
color: btncolor["4"],
textColor: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(10.0))),
child: Text('4',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 20
),
),
),
),
],
);
}
}
}
Here, questions is the array which stores the question.
When I am using the 'Skip' button, the setState works perfectly but when I am using 'Next' button the setState is not working.
Can someone help me with this please?
I'd say that you're manipulating the state in a wrong way
As docs refers:
#protected
void setState (VoidCallback fn)
The provided callback is immediately called synchronously. It must not return a future (the callback cannot be async), since then it would be unclear when the state was actually being set.
things to note:
don't call setState() inside initState()
don't call setState() in synchronous code inside build()
setState() should run synchronously so new updates happen atomically
hence, try not to mark setState() as async
You might see the link, hope it's useful
try this
#override
void setState(fn) {
if(btncolor[(i+1).toString()] == Colors.deepOrange){
btncolor[(i+1).toString()] = Colors.purple;
flag = 1;
}
else if(btncolor[(i+1).toString()] == Colors.green){
btncolor[(i+1).toString()] = Colors.purple;
flag = 2;
}
else{
btncolor[(i+1).toString()] = Colors.purple;
}
super.setState(fn);//move here
}