[Flutter]How to import image from gallery dynamically - flutter

I am a new flutter learner and trying to create my first app. My problem is...
(1). I use a method to build a place(widget) for image which will come from gallery or camera.
void _showPicker(context) {
showModalBottomSheet(
context: context,
builder: (BuildContext bc) {
return SafeArea(
child: Container(
child: new Wrap(
children: <Widget>[
new ListTile(
leading: new Icon(Icons.photo_library),
title: new Text('Gallery'),
onTap: () {
_imgFromGallery();
Navigator.of(context).pop();
}),
new ListTile(
leading: new Icon(Icons.photo_camera),
title: new Text('Camera'),
onTap: () {
_imgFromCamera();
Navigator.of(context).pop();
},
),
],
),
),
);
});
}
(2). I created a method to import image by using image_picker package.
Future _imgFromGallery() async {
final pickedImage =
await _picker.getImage(source: ImageSource.gallery, imageQuality: 50);
setState(() {
if (pickedImage != null) {
this._image = new File(pickedImage.path);
}
});
}
(3). I create a button which if pressed, will call method (1) and medthod (1) contained medthod (2).
(4). When I added the first image, everything fine but, when I add the second image, the first image also changed to the second
image
So, could you please help me for figure out of this problem?
Sorry that I didn't share the code that call _showPicker (function for displayed image) here is the code...please focus at GestureDetector(...),
_createListStepRow(String item, int index) {
return Column(children: [
Container(
margin: EdgeInsets.only(top: 3),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: new BorderRadius.circular(15),
border: Border.all(color: Colors.black)),
child: Column(children: [
Row(crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[
Container(
width: 1175.0.w,
child: TextField(
autofocus: this.autoFocus,
cursorColor: Colors.black,
decoration: InputDecoration(
prefixIcon: Icon(
Icons.restaurant_outlined,
color: Constants.primaryColor,
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(15),
borderSide: BorderSide(color: Colors.white, width: 1.5),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: BorderSide(color: Colors.white, width: 0),
),
contentPadding: EdgeInsets.symmetric(vertical: 8),
hintText: item,
floatingLabelBehavior: FloatingLabelBehavior.never,
)),
),
IconButton(
icon: Icon(Icons.delete),
onPressed: () {
setState(() {
_itemsStep.removeAt(index);
});
},
),
]),
GestureDetector(
onTap: () async {
_showPicker(context);
},
child: Container(
padding: EdgeInsets.all(8),
// height: 800.0.h,
width: double.infinity,
decoration: BoxDecoration(
color: Colors.grey[200],
// image: DecorationImage(
// image: AssetImage('assets/images/food1.jpg'),
// fit: BoxFit.fill,
// ),
shape: BoxShape.rectangle,
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
new Column(children: [
Container(
// height: 200.0.h,r
child: _image == null
? _nullImage
: Image.file(_image, fit: BoxFit.contain),
),
// Text(
// 'Click to Add Step Image',
// style: GoogleFonts.poppins(fontSize: 14),
// ),
]),
]),
),
),
SizedBox(height: 60.0.h),
]),
),
SizedBox(height: 30.0.h),
]);
}

First off, you're not storing the images. You're basically choosing the latest one. Lets fix that. Find where you've declared var _image; and change that to final List<File> _images;.
Next, change the Column in the GestureDetector in _showPicker to this:
Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
new ListView.builder(
itemBuilder: (context, index) {
return Container(
// height: 200.0.h,r
child: _images[index] == null
? _nullImage
: Image.file(_images[index], fit: BoxFit.contain),
);
},
itemCount: _images.length,
// Text(
// 'Click to Add Step Image',
// style: GoogleFonts.poppins(fontSize: 14),
// ),
)
],
),
If the code you gave was working as you said before, this should probably work.

Related

Error on my UI using SingleChildScrollView when i try to run my firebase?

this is my first time using community to ask about my project. First thing first, english isn't my first language and I'm a very beginner in flutter world. I'm trying to build my first mobile application using flutter and now I'm trying to connect my project to firebase (I looked at youtube tutorial). I don't know if the firebase already connect because when I'm trying to run the application and go to registration page, there this error message.
And here is my code:
import 'package:dfu_check_application/common/auth_controller.dart';
import 'package:flutter/material.dart';
import 'package:dfu_check_application/common/theme_helper.dart';
import 'package:dfu_check_application/pages/widgets/header_widget.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:hexcolor/hexcolor.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'profile_page.dart';
class RegistrationPage extends StatefulWidget {
#override
State<StatefulWidget> createState() {
return _RegistrationPageState();
}
}
class _RegistrationPageState extends State<RegistrationPage> {
final _formKey = GlobalKey<FormState>();
bool checkedValue = false;
bool checkboxValue = false;
#override
Widget build(BuildContext context) {
var nameController = TextEditingController();
var emailController = TextEditingController();
var passwordController = TextEditingController();
return Scaffold(
backgroundColor: Colors.white,
body: SingleChildScrollView(
child: Stack(children: [
Container(
height: 150,
child: HeaderWidget(150, false, Icons.person_add_alt_1_rounded),
),
Container(
margin: EdgeInsets.fromLTRB(25, 50, 25, 10),
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
alignment: Alignment.center,
child: Column(
children: [
Form(
key: _formKey,
child: Column(
children: [
GestureDetector(
child: Stack(
children: [
Container(
padding: EdgeInsets.all(10),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(100),
border:
Border.all(width: 5, color: Colors.white),
color: Colors.white,
boxShadow: [
BoxShadow(
color: Colors.black12,
blurRadius: 20,
offset: const Offset(5, 5),
),
],
),
child: Icon(
Icons.person,
color: Colors.grey.shade300,
size: 80.0,
),
),
Container(
padding: EdgeInsets.fromLTRB(80, 80, 0, 0),
child: Icon(
Icons.add_circle,
color: Colors.grey.shade700,
size: 25.0,
),
),
],
),
),
SizedBox(
height: 30,
),
Container(
child: TextFormField(
controller: nameController,
decoration: ThemeHelper().textInputDecoration(
'Full Name', 'Enter your full name'),
),
decoration: ThemeHelper().inputBoxDecorationShaddow(),
),
SizedBox(
height: 30,
),
SizedBox(height: 20.0),
Container(
child: TextFormField(
controller: emailController,
decoration: ThemeHelper().textInputDecoration(
"E-mail address", "Enter your email"),
keyboardType: TextInputType.emailAddress,
validator: (val) {
// ignore: prefer_is_not_empty
if (!(val!.isEmpty) &&
!RegExp(r"^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+#[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,253}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,253}[a-zA-Z0-9])?)*$")
.hasMatch(val)) {
return "Enter a valid email address";
}
return null;
},
),
decoration: ThemeHelper().inputBoxDecorationShaddow(),
),
SizedBox(height: 20.0),
Container(
child: TextFormField(
obscureText: true,
controller: passwordController,
decoration: ThemeHelper().textInputDecoration(
"Password*", "Enter your password"),
validator: (val) {
if (val!.isEmpty) {
return "Please enter your password";
}
return null;
},
),
decoration: ThemeHelper().inputBoxDecorationShaddow(),
),
SizedBox(height: 15.0),
FormField<bool>(
builder: (state) {
return Column(
children: <Widget>[
Row(
children: <Widget>[
Checkbox(
value: checkboxValue,
onChanged: (value) {
setState(() {
checkboxValue = value!;
state.didChange(value);
});
}),
Text(
"I accept all terms and conditions.",
style: TextStyle(color: Colors.grey),
),
],
),
Container(
alignment: Alignment.centerLeft,
child: Text(
state.errorText ?? '',
textAlign: TextAlign.left,
style: TextStyle(
color: Theme.of(context).errorColor,
fontSize: 12,
),
),
)
],
);
},
validator: (value) {
if (!checkboxValue) {
return 'You need to accept terms and conditions';
} else {
return null;
}
},
),
SizedBox(height: 20.0),
GestureDetector(
onTap: () {
AuthController.instance.register(
nameController.text.trim(),
emailController.text.trim(),
passwordController.text.trim());
},
),
Container(
decoration: ThemeHelper().buttonBoxDecoration(context),
child: ElevatedButton(
style: ThemeHelper().buttonStyle(),
child: Padding(
padding: const EdgeInsets.fromLTRB(40, 10, 40, 10),
child: Text(
"Register".toUpperCase(),
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
),
onPressed: () {
if (_formKey.currentState!.validate()) {
Navigator.of(context).pushAndRemoveUntil(
MaterialPageRoute(
builder: (context) => ProfilePage()),
(Route<dynamic> route) => false);
}
},
),
),
SizedBox(height: 30.0),
Text(
"Or create account using social media",
style: TextStyle(color: Colors.grey),
),
SizedBox(height: 25.0),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
GestureDetector(
child: FaIcon(
FontAwesomeIcons.google,
size: 35,
color: HexColor("#EC2D2F"),
),
onTap: () {
setState(() {
showDialog(
context: context,
builder: (BuildContext context) {
return ThemeHelper().alartDialog(
"Google Account",
"You tap on Google icon.",
context);
},
);
});
},
),
],
),
],
),
),
],
),
),
]),
),
);
}
}
If you guys see more error on my code, please tell me because I'm very clueless about this. Thank you in advance!
The issue occurs from Stack the one inside
Column(
children: [
Form(
key: _formKey,
child: Column(
children: [
GestureDetector(
child: Stack( // this one
Can be fixed by providing hight
GestureDetector(
child: SizedBox(
height: MediaQuery.of(context).size.height, //this based on your need
child: Stack(
I think you can re struct the widget and don't need to use multi-Stack.
More about /ui/layout and Unbounded height / width

How to make Dependent DropdownButtonFormField in showDialog in flutter?

I make the Dependent DropdownButtonFormField in showDialog.
when i select the item of first dropdown the values not showing in second dropdown which is dependent on first dropdown.
But when i close the Dialog and reopen the dialog the values showing in second dropdown.
So here my Question is how to refresh second dropdown when first dropdown value is changed?
Future<bool> showDropDownDialog(title) async {
List<DropdownMenuItem<AllocationType>> items = [];
dropDownAllocationTypeModels.forEach((element) {
items.add(DropdownMenuItem(
child: Text(
element.allocationTypeName!,
style: Themes.getTextStyle(context),
),
value: element,
));
});
List<DropdownMenuItem<ServiceArea>> serviceAreaitems = [];
dropDownServiceAreaModels.forEach((element) {
serviceAreaitems.add(DropdownMenuItem(
child: Text(
element.serviceAreaName ?? "1",
style: Themes.getTextStyle(context),
),
value: element,
));
});
void onTeamChange(area) {
setState(() {
dropdownValueTeamType = null;
dropdownValueServiceArea = area;
dropDownTeamTypeModels = [];
});
ApiHelper()
.getTeamsByServiceArea(dropdownValueServiceArea!.id!)
.then((value) => {
setState(() {
dropDownTeamTypeModels = value;
})
});
}
return await showDialog(
context: context,
builder: (context) => Center(
child: Form(
key: _formKey,
child: Container(
padding: EdgeInsets.all(10),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Card(
color: Colors.blueGrey[100],
child: ClipRRect(
borderRadius: BorderRadius.circular(10),
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ClipRRect(
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(15),
bottomRight: Radius.circular(15),
),
child: Container(
padding: EdgeInsets.all(10),
alignment: Alignment.center,
width: 300,
color:
Themes.getPrimaryDarkBackgroundColor(
context),
child: Text(
title,
style: Themes.getTitleTextStyleWhite(
context),
),
),
),
],
),
Padding(
padding: EdgeInsets.only(
left: Constants.APP_PADDING,
right: Constants.APP_PADDING,
top: Constants.APP_PADDING),
child: DropdownButtonFormField<ServiceArea>(
style: Themes.getTextFieldTextStyle(context),
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: AppLocalizations.of(context)
.hintSelectServiceArea,
),
value: dropdownValueServiceArea,
isExpanded: true,
items: serviceAreaitems,
onChanged: (value) {
setState(() {
dropdownValueServiceArea = value;
onTeamChange(value);
});
},
),
),
Padding(
padding: EdgeInsets.only(
left: Constants.APP_PADDING,
right: Constants.APP_PADDING,
top: Constants.APP_PADDING),
child: DropdownButtonFormField<dynamic>(
style: Themes.getTextFieldTextStyle(context),
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: AppLocalizations.of(context)
.hintSelectTeamType,
),
value: dropdownValueTeamType,
isExpanded: true,
items: dropDownTeamTypeModels.map((team) {
return DropdownMenuItem<dynamic>(
value: team,
child: Text(team),
);
}).toList(),
onChanged: (value) {
setState(() {
dropdownValueTeamType = value;
});
},
),
),
],
)),
elevation: 8,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10)),
),
],
),
),
),
),
) ??
false; //if showDialouge had returned null, then return false
}
As I see you use statefull widget approach.
So I believe you have to wrap parent dialog widget to statefull, declare variables (as dropdownValueServiceArea) in it, and change them inside dropdown callbacks with
setState(()=> dropdownValueServiceArea = newValue);

Flutter: How do i shift my code to another page and access it here

I am very new to Dart, and coding in general. I have produced this code after watching tutorials on YouTube. For the most part, I have been able to troubleshoot most of my problems on my own, here I feel I need some help. I have written code to upload photograph, but I wanted to shift the method to another and access the functionality.
Here is my code
class EditProfile extends StatefulWidget {
EditProfile({Key? key}) : super(key: key);
#override
State<EditProfile> createState() => _EditProfileState();
}
class _EditProfileState extends State<EditProfile> {
File? image;
Future PickedImage(ImageSource source) async {
try {
final image = await ImagePicker()
.pickImage(source: source, maxWidth: 160, maxHeight: 160);
if (image == null) return;
setState(() {
final _imgTemp = File(image.path);
});
} on PlatformException catch (e) {
print('failed to Upload $e');
}
}
#override
Widget build(BuildContext context) {
var _textController = ProfileEdit();
return Scaffold(
body: GetX<ProfileController>(
init: Get.put<ProfileController>(ProfileController()),
builder: (ProfileController profileController) {
return Container(
child: ListView.builder(
itemCount: profileController.profiles.length,
itemBuilder: (BuildContext context, int i) {
final _profileModel = profileController.profiles[i];
setTextEditControllerValue(_textController, _profileModel);
return SafeArea(
child: Container(
padding: EdgeInsets.all(20),
child: Form(
child: Column(
children: [
const SizedBox(
height: 20,
),
GestureDetector(
onTap: () {
photoBottomSheet();
},
child: CircleAvatar(
radius: 100,
backgroundImage: NetworkImage(
'https://www.alchinlong.com/wp-content/uploads/2015/09/sample-profile.png'),
),
),
const SizedBox(
height: 40,
),
TextFormField(
decoration: const InputDecoration(
labelText: 'First Name',
border: OutlineInputBorder(
borderSide: BorderSide()),
),
controller: _textController.fNameController),
SizedBox(
height: 10,
),
TextFormField(
decoration: const InputDecoration(
labelText: 'First Name',
border:
OutlineInputBorder(borderSide: BorderSide()),
),
controller: _textController.lNameController,
),
SizedBox(
height: 10,
),
TextFormField(
decoration: const InputDecoration(
labelText: 'Address',
border:
OutlineInputBorder(borderSide: BorderSide()),
),
controller: _textController.adressController,
),
SizedBox(
height: 10,
),
TextFormField(
decoration: const InputDecoration(
labelText: 'Phone Numbaer',
border:
OutlineInputBorder(borderSide: BorderSide()),
),
controller: _textController.phoneController,
),
SizedBox(
height: 10,
),
TextFormField(
decoration: const InputDecoration(
labelText: 'School Name',
border:
OutlineInputBorder(borderSide: BorderSide()),
),
controller: _textController.sclNameController,
),
SizedBox(
height: 10,
),
TextFormField(
decoration: const InputDecoration(
labelText: 'Student Class',
border:
OutlineInputBorder(borderSide: BorderSide()),
),
controller: _textController.stdClassController,
),
SizedBox(
height: 10,
),
ElevatedButton(
onPressed: () async {
CircularProgressIndicator();
ProfileModel profileModel =
profileModelVal(_textController);
await FirestoreDb.updateProfile(profileModel);
Get.offAll(ProfileScreen());
},
child: Text('Update'))
],
),
),
),
);
}),
);
},
));
}
void photoBottomSheet() {
Get.bottomSheet(
Container(
//color: Colors.white,
height: 150,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment:
CrossAxisAlignment.center,
children: [
//Text('Select from source'),
GestureDetector(
onTap: () =>
PickedImage(ImageSource.camera),
child: Row(
mainAxisAlignment:
MainAxisAlignment.center,
children: [
Icon(
Icons.camera,
size: 25,
color: Colors.white,
),
SizedBox(
width: 10,
),
Text(
'Camera',
style: TextStyle(fontSize: 25, color: Colors.white),
),
],
),
),
SizedBox(
height: 10,
),
Divider(
thickness: 0.5, color: Colors.white,
),
SizedBox(
height: 10,
),
GestureDetector(
onTap: () =>
PickedImage(ImageSource.gallery),
child: Row(
mainAxisAlignment:
MainAxisAlignment.center,
children: [
Icon(
Icons.image,
size: 25,
color: Colors.white,
),
SizedBox(
width: 10,
),
Text(
'Gallery',
style: TextStyle(fontSize: 25, color: Colors.white),
),
],
),
),
],
),
),
backgroundColor: Color(0xff2AA8A1),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)),
);
}
ProfileModel profileModelVal(ProfileEdit _textController) {
final profileModel = ProfileModel(
firstName: _textController.fNameController.text.trim(),
lastName: _textController.lNameController.text.trim(),
parentName: _textController.fatherNameController.text.trim(),
phoneNumber: _textController.phoneController.text.trim(),
address: _textController.adressController.text.trim(),
schoolName: _textController.sclNameController.text.trim(),
stdClass: _textController.stdClassController.text.trim());
return profileModel;
}
void setTextEditControllerValue(
ProfileEdit _textController, ProfileModel _profileModel) {
_textController.fNameController.value =
TextEditingValue(text: _profileModel.firstName);
_textController.lNameController.value =
TextEditingValue(text: _profileModel.lastName);
_textController.fatherNameController.value =
TextEditingValue(text: _profileModel.parentName);
_textController.adressController.value =
TextEditingValue(text: _profileModel.address);
_textController.phoneController.value =
TextEditingValue(text: _profileModel.phoneNumber);
_textController.sclNameController.value =
TextEditingValue(text: _profileModel.schoolName);
_textController.stdClassController.value =
TextEditingValue(text: _profileModel.stdClass);
}
void clearTextController(ProfileEdit _textController) {
_textController.fNameController.clear();
_textController.lNameController.clear();
_textController.fatherNameController.clear();
_textController.adressController.clear();
_textController.phoneController.clear();
_textController.sclNameController.clear();
_textController.stdClassController.clear();
}
}
Now the method photoBottomSheet() has to be shifted to another file and I should use it in any page I want. Please help me Here.
create a dart file called photo_bottom_sheet and add the method there, then where ever you want to add it you will just have to import that file on the top of the dart file like so :
import 'package:app/photo_bottom_sheet';
and then add the method wwhere you need it
photoBotomSheet()
where you want it.
1.copy the function and make separate .dart file.
2. import that function from that file wherever you want just like you import package.

setState() or markNeedsBuild() called during build Query Widget

I have a problem with Graphql Flutter.
I am trying to display a search list retrieved with graphql.
But flutter tells me:
This widget cannot be marked as needing to build because the framework is already in the process of building widgets. A widget can be marked as needing to be built during the build phase only if one of its ancestors is currently building. This exception is allowed because the framework builds parent widgets before children, which means a dirty descendant will always be built. Otherwise, the framework might not visit this widget during this build phase.
I added some Future Builder to avoid this kind of issue but unfortunately it doesn't seem to work
this is my code:
Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Flexible(
flex: 5,
child: AnimatedContainer(
duration: Duration(milliseconds: 500),
padding: EdgeInsets.symmetric(horizontal: 25),
height: 42.0,
width: width,
decoration: BoxDecoration(
borderRadius:
BorderRadius.circular(20.0),
color: const Color(0xffffffff),
boxShadow: [
BoxShadow(
color: const Color(0x29000000),
offset: Offset(0, 0),
blurRadius: 12,
),
],
),
child: Form(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Flexible(
flex: 1,
child: Container(
width: 17.0,
height: 17.0,
decoration: BoxDecoration(
image: DecorationImage(
image: const AssetImage(
'assets/images/XDSearch.png'),
fit: BoxFit.cover,
),
),
),
),
Flexible(
flex: 6,
child: TextFormField(
onChanged: (value){
setState(() {
textSearch = value;
});
},
keyboardType: TextInputType.emailAddress,
decoration: const InputDecoration(
focusedBorder: InputBorder.none,
enabledBorder: InputBorder.none,
errorBorder: InputBorder.none,
disabledBorder: InputBorder.none,
border: InputBorder.none,
hintText: 'Recherche'
),
style: TextStyle(
fontFamily: 'Roboto',
fontSize: 16,
color: const Color(0x8c000000),
fontWeight: FontWeight.w700,
),
textAlign: TextAlign.left,
focusNode: _focus,
),
)
],
),
),
),
),
clickOnBar == false ? Flexible(
flex: 1,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Container(
width: 30.0,
height: 30.0,
margin: EdgeInsets.fromLTRB(0, 0, 0, 0),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15.0),
image: DecorationImage(
image: const AssetImage('assets/images/XDProfil.png'),
fit: BoxFit.fill,
),
),
)
],
),
) : Container()
],
),
textSearch != null && textSearch != 'undefined' && textSearch.isNotEmpty ? FutureBuilder(
builder: (context, projectSnap) {
return Query(
options: QueryOptions(
documentNode: gql("""
query getListSearch(\$text : String!){
listSearchProPages(text: \$text) {
categorie {
idCat
title
}
subCat {
idSubCat
title
}
pagePro {
idPagesPro
title
}
}
}
"""
),
variables: <String, dynamic>{
"text": textSearch,
},
pollInterval: 10
),
builder: (QueryResult result, {VoidCallback refetch, FetchMore fetchMore}){
print(result);
if (result.hasException) {
return Text(result.exception.toString());
}
if (result.loading) {
return Text('Loading');
}
var tmpObject = {
"categorie": result.data['listSearchProPages'].first['categorie'],
"subCat": result.data['listSearchProPages'].first['subCat'],
"pagePro": result.data['listSearchProPages'].first['pagePro'],
};
return FutureBuilder(
future: updateListSearch(tmpObject),
builder: (context, projectSnap){
if(tmpObject.length > 0) {
ListView.builder(
itemCount: tmpObject.length,
itemBuilder: (context, index) {
print(tmpObject);
final repository = tmpObject[index];
print(repository["categorie"]
.first['title']);
return Text(
repository["categorie"]
.first['title']);
}
);
}else {
return Container();
}
return Container();
}
);
},
);
}
) : Container()
],
),
Do you have the solution ?
Please do not create a new future on every call of the build method as you do now.
You need to create a future once (or maybe more often, but certainly not on every build) and then use that future in your build method:
Create a variable of your future type in your state class.
In your initState method, create the future, by assigning the result of updateListSearch(tmpObject) to your variable.
In your build method, use the variable as your parameter for the future in the FutureBuilder.

Why is selected value not reflecting in showModalBottomSheet with flutter?

First of all, I created a designed bottom sheet, In which, there are two lists to show numbers(left side) and options(hour, day, week, month) with the help of CupertinoPicker widget,
Numbers will depend on what option I select, If I select the hour, numbers of the left side should be 1-24, and if I select week, numbers should be 1-4, I select the day, numbers should be 1-30 and last I select month number should be 1-12.
Code :
All Lists variable:
List<String> reminderDay = ['hour','day','week','month'];
List<String> reminderHoursVal =['1','2','3','4','5','6','7','8','9','10','11','12','13','14','15','16','17','18','19','20','21','22','23','24'];
List<String> reminderDaysVal =['1','2','3','4','5','6','7','8','9','10','11','12','13','14','15','16','17','18','19','20','21','22','23','24','25','26','27','28','29','30','31'];
List<String> reminderMonthsVal =['1','2','3','4','5','6','7','8','9','10','11','12'];
List<String> reminderWeeksVal =['1','2','3','4'];
String selectedReminderVal='1';
String selectedReminderDay ='hour';
Code of bottom sheet:
addReminder(){
showModalBottomSheet(
context: context,
builder: (BuildContext context) {
return AnimatedPadding(
padding: MediaQuery.of(context).viewInsets,
duration: const Duration(milliseconds: 100),
curve: Curves.decelerate,
child: Container(
padding: const EdgeInsets.only(top:8,right: 8, left:8,bottom: 8),
height: MediaQuery.of(context).size.height/2,
// color: Colors.transparent,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(30),
topRight: Radius.circular(30)
)
),
child: Container(
child: Column(
// mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
SizedBox(height:10),
Text("Set a reminder",
style: TextStyle(
fontSize:18,
fontWeight:FontWeight.bold,
color: Colors.grey
),
),
SizedBox(height:20),
Container(
margin: const EdgeInsets.only(left: 10, right: 10),
height: MediaQuery.of(context).size.height/4,
decoration: BoxDecoration(
color: Colors.grey[100],
borderRadius: BorderRadius.circular(10)
),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Expanded(
child: CupertinoPicker(
scrollController: new FixedExtentScrollController(
initialItem: 0,
),
itemExtent: 30,
backgroundColor: Colors.grey[100],
onSelectedItemChanged: (int val) {
setState(() {
if(selectedReminderDay=='day'){
selectedReminderVal = reminderDaysVal[val];
}else if(selectedReminderDay=='week'){
selectedReminderVal = reminderWeeksVal[val];
}else if(selectedReminderDay=='month'){
selectedReminderVal = reminderMonthsVal[val];
}else{
selectedReminderVal = reminderHoursVal[val];
}
print("selectedReminderVal:$selectedReminderVal");
});
},
children:selectedReminderDay=='day'?reminderDaysVal
:selectedReminderDay=='week'?reminderWeeksVal
:selectedReminderDay=='month'?reminderMonthsVal:reminderHoursVal// ['hour','day','week','month']; reminderHoursVal
.map(
(item) => Center(
child: Text(
item,
style: TextStyle(
fontSize: 16,
// fontWeight:FontWeight.bold,
),
),
),
)
.toList()),
),
Expanded(
child: CupertinoPicker(
scrollController: new FixedExtentScrollController(
initialItem: 0,
),
itemExtent: 30,
backgroundColor: Colors.grey[100],
onSelectedItemChanged: (int val) {
setState(() {
selectedReminderDay = reminderDay[val];
print("selectedReminderDay:$selectedReminderDay");
});
},
children: reminderDay
.map(
(item) => Center(
child: Text(
item,
style: TextStyle(
fontSize: 16,
// fontWeight:FontWeight.bold,
),
),
),
)
.toList()),
),
])
),
SizedBox(height:15),
// selectedVal!=null?Text(selectedVal.toString()):Container()
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text("You'll get the reminder"),
Text('$selectedReminderVal $selectedReminderDay before the event')
],
),
SizedBox(height:25),
Padding(
padding: const EdgeInsets.only(left: 10, right: 10),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
InkWell(
onTap: (){
Navigator.pop(context);
},
child: Text("Cancel",
style: TextStyle(
fontSize: 18,
color: Colors.blue,
fontWeight: FontWeight.bold
),
),
),
InkWell(
onTap: (){
Navigator.pop(context);
},
child: Container(
alignment: Alignment.center,
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.circular(8)
),
width: MediaQuery.of(context).size.width/5,
height: MediaQuery.of(context).size.height/25 ,
child: Text("Save", style:TextStyle(
color: Colors.white,
fontSize: 19
)),
),
)
],
),
)
],
),
)
),
);
},
);
}
Screenshot:
This is because the state you are setting is different from the state in the modal bottom sheet.
Right now, when you are calling setState, you are actually rebuilding the stateful widget under the modal bottom sheet.
To fix this, just wrap your bottom sheet in a Stateful Builder.
StatefulBuilder(
builder: (context, setState) {
return AnimatedPadding(
padding: MediaQuery.of(context).viewInsets,
duration: const Duration(milliseconds: 100),
curve: Curves.decelerate,
child: Container(
padding: const EdgeInsets.only(top:8,right: 8, left:8,bottom: 8),
height: MediaQuery.of(context).size.height/2,
// color: Colors.transparent,
decoration: BoxDecoration(
color: Colors.white,
....
when we create new context widgets in existing state there states become different, bottomSheets are similar to dialogBox with new context and builder build a completely new widget out of the parent state, to create its own stateful state Wrap it with the stateful builder and user its own setState to change anything in this context not the parent one
eg:
StatefulBuilder(
builder: (context, setStateChild) {
return AnimatedPadding(...
Expanded(
child: CupertinoPicker(
scrollController: new FixedExtentScrollController(
initialItem: 0,
),
itemExtent: 30,
backgroundColor: Colors.grey[100],
onSelectedItemChanged: (int val) {
setStateChild(() {
selectedReminderDay = reminderDay[val];
print("selectedReminderDay:$selectedReminderDay");
});
},);
child: ... ),
}