I have a bloc which I use to upload images from the gallery. I then have a TextField where I enter text. And finally another bloc where I have a button. The button is used to submit the data to a server(image and text). My problem is enabling the button. My code for enabling is:
class ObservationPage extends StatefulWidget {
#override
_ObservationPageState createState() => _ObservationPageState();
}
class _ObservationPageState extends State<ObservationPage> {
List<File> files = [];
TextEditingController _descriptionController = TextEditingController();
TextEditingController _taskNameController = TextEditingController();
String taskName;
List<String> _selectedUsers = [];
bool _enabled = false;
#override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () async {
BlocProvider.of<ImageBloc>(context).add(DeleteAllImages(files: files));
return true;
},
child: Scaffold(
backgroundColor: Colors.grey[200],
appBar: AppBar(
centerTitle: true,
iconTheme: IconThemeData(
color: RioColours.darkGrey,
),
backgroundColor: Colors.grey[200],
elevation: 0,
title: Text('Observation',style:TextStyle(color: Colors.black))
),
body: SingleChildScrollView(
child: Padding(
padding: EdgeInsets.only(left: 20.0, right: 20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(height: 20,),
Column(children: [
AutoSizeText(
'Make an Observation and assign to a colleague ',
maxLines: 1,
style: RioTextStyle.auditQuestion(context),
),
SizedBox(height: 20,),
AttachPhoto(),
SizedBox(height: 20,),
BlocBuilder<ImageBloc, ImageState>(builder: (context, state) {
if (state is ImageInitial) {
return Container();
}
if (state is ImageLoadInProgress) {
return CircularProgressIndicator();
}
if (state is ImageLoadSuccess) {
//print(state.files);
files = state.files;
return SizedBox(
//height: MediaQuery.of(context).size.height*.5,
child: ListView.builder(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
itemCount: state.files.length,
itemBuilder: (context, item) {
return Padding(
padding: const EdgeInsets.only(bottom:10.0),
child: ImageContainer(context: context, file: state.files[item]),
);
}),
);
}
if (state is NoImages) {
return Container();
}
if (state is ImageLoadFailure) {
return Container();
}
return Container();
})
]),
Text(
'Notes',
style: RioTextStyle.auditHeaders(context),
),
SizedBox(
height:10
),
SizedBox(height: 140,
child: TextField(
textInputAction: TextInputAction.next,
keyboardType: TextInputType.multiline,
maxLines: 5,
controller: _descriptionController,
onChanged: (String value) {
setState(() {});
},
style: TextStyle(fontSize: 16.0, height: 2.0, color: Colors.black),
decoration: new InputDecoration(
hintStyle: RioTextStyle.hintText(context),
fillColor: Colors.white,
filled: true,
focusedBorder: OutlineInputBorder(),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
borderSide: BorderSide(color: Colors.grey[300]),
),
hintText: "Enter your notes here"
),
),
),
SizedBox(
height: MediaQuery.of(context).size.height * .04,
),
Text(
'Task Name',
style: RioTextStyle.auditHeaders(context),
),
SizedBox(
height: 10
),
TextField(
controller: _taskNameController,
onChanged: (String value) {
setState(() {});
},
textInputAction: TextInputAction.next,
style: TextStyle(fontSize: 16.0, height: 2.0, color: Colors.black),
decoration: new InputDecoration(
fillColor: Colors.white,
filled: true,
focusedBorder: OutlineInputBorder(),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
borderSide: BorderSide(color: Colors.grey[300]),
),
hintStyle: RioTextStyle.hintText(context),
hintText: "Enter your task name here"
),
),
SizedBox(
height: 20
),
SizedBox(
height: 20
),
BlocBuilder<ObservationBloc, ObservationState>(builder: (context, state) {
if (state is UsersLoadInProgress) {
return Center(child: CircularProgressIndicator());
}
if (state is UsersLoadSuccess) {
final users = state.users;
return Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
Text(
'Assign to',
style: RioTextStyle.auditHeaders(context),
),
SizedBox(
height: MediaQuery.of(context).size.height * .02,
),
MultiSelectDialogField(
buttonIcon: Icon(Icons.arrow_drop_down,color: Colors.grey,),
chipDisplay: MultiSelectChipDisplay(
chipColor: Colors.white,
textStyle: TextStyle(color: Colors.black),
),
onConfirm: (results) {
_selectedUsers.clear();
for (User user in results) {
_selectedUsers.add(user.id);
setState(() {
_enabled = true;
});
}
// _selectedUsers = results;
print(_selectedUsers);
},
items: users.map((user) => MultiSelectItem<User>(user, user.first_name)).toList(),
title: Text(
'Assign Owners',
style: TextStyle(color: RioColours.splashBlue),
),
cancelText: Text(
"CANCEL",
style: TextStyle(color: RioColours.splashBlue),
),
confirmText: Text(
"ASSIGN",
style: TextStyle(color: RioColours.splashBlue),
),
buttonText: Text(
"Choose Owners",
style: RioTextStyle.dropDownHint(context),
),
),
SizedBox(
height: MediaQuery.of(context).size.height * .05,
),
]);
}
if (state is UserLoadFailure) {
return Text('error');
}
return Container();
}),
BlocConsumer<ButtonBloc, ButtonState>(listener: (context, state) {
if (state is UploadFailure) {
RioHelpers.showFailureFlushBar(context, 'Error Uploading');
Navigator.of(context).pop();
}
if (state is UpLoadSuccess) {
_submit();
}
}, builder: (context, state) {
if (state is Loading) {
return Center(child: CircularProgressIndicator());
}
if (state is ButtonInitial) {
print(_enabled);
return SizedBox(
height: MediaQuery.of(context).size.height * .07,
width: MediaQuery.of(context).size.width,
child: RaisedButton(
onPressed: (_descriptionController.text.isNotEmpty && _taskNameController.text.isNotEmpty && _enabled) ? () => callupLoad() : null,
color: RioColours.splashBlue,
child: Text(
'Submit',
style: RioTextStyle.buttonText(context),
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(4),
),
),
);
}
if (state is UpLoadSuccess) {
BlocProvider.of<ImageBloc>(context).add(DeleteAllImages(files: files));
return SizedBox(
height: MediaQuery.of(context).size.height * .07,
width: MediaQuery.of(context).size.width,
child: RaisedButton(
onPressed: (_descriptionController.text.isNotEmpty && _taskNameController.text.isNotEmpty && _enabled) ? () => callupLoad() : null,
color: RioColours.splashBlue,
child: Text(
'Submit',
style: RioTextStyle.buttonText(context),
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(4),
),
),
);
}
if (state is UploadFailure) {
return SizedBox(
height: MediaQuery.of(context).size.height * .07,
width: MediaQuery.of(context).size.width,
child: RaisedButton(
onPressed: () {},
//onPressed: (controller.text.isNotEmpty && _enabled) ? () => callupLoad() : null,
color: RioColours.splashBlue,
child: Text(
'Submit',
style: RioTextStyle.buttonText(context),
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(4),
),
),
);
}
return Container(
color: Colors.yellow,
height: 10,
);
}),
SizedBox(
height: MediaQuery.of(context).size.height * .12,
),
],
),
),
)),
);
}
callupLoad() {
BlocProvider.of<ButtonBloc>(context).add(UploadTaskRequest(files: files, notes: _descriptionController.text, taskName: _taskNameController.text, owners: _selectedUsers));
}
_submit() async {
print('called called called called called ');
RioHelpers.showSuccessFlushBar(context, 'Observation recorded');
BlocProvider.of<ImageBloc>(context).add(DeleteAllImages(files: files));
await Future.delayed(Duration(seconds: 3));
Navigator.of(context).pop();
}
#override
void initState() {
BlocProvider.of<ObservationBloc>(context).add(RequestUsers());
super.initState();
print("init calledx");
_enabled = false;
}
}
So the _controller works great for enabling/disabling the button. However _enabled which is a boolean state variable is my problem. In my blocbuilder I update my state to _enabled= true when the image upload is successful. However this is not making any difference to enabling the button. I've also updated the state variable using a bloclistener but that didn't work either.
How can I trigger the button to be enabled when I upload an image from the Gallery
Set a local variable in the builder, not in the class itself, unless you want to use in another place. If you want to do so, wrap the variable assignment in a setState call.
Related
when i navigate from NewSales screen to CreateItem screen and add item and press the add button
the item is added to sqflite database then it navigates back to new sales but the state is not updated , it's updated only if i restarted the app
the NewSales screen
class _NewSalesState extends State<NewSales> {
final controller = TextEditingController();
showAlertDialog(BuildContext context,String name) {
// Create button
// Create AlertDialog
AlertDialog alert = AlertDialog(
title: const Text("Alert"),
content: const Text("you want to delete this item?"),
actions: [
TextButton(
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all(Colors.green)),
child: const Text("CANCEL", style: TextStyle(color: Colors.white)),
onPressed: () {
Navigator.of(context).pop();
},
),
BlocBuilder<SalesCubit, SalesState>(
builder: (context, state) {
final bloc=BlocProvider.of<SalesCubit>(context);
return TextButton(
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all(Colors.red)),
child: const Text(
"DELETE",
style: TextStyle(color: Colors.white),
),
onPressed: () {
Navigator.of(context).pop();
bloc.deleteItem(name).then((value) {
bloc.getAllItems();
});
},
);
},
)
],
);
// show the dialog
showDialog(
context: context,
builder: (BuildContext context) {
return alert;
},
);
}
// #override
#override
Widget build(BuildContext context) {
final deviceSize = MediaQuery
.of(context)
.size;
return BlocConsumer<SalesCubit, SalesState>(
listener: (context, state) {},
builder: (context, state) {
final bloc = BlocProvider.of<SalesCubit>(context);
if (state is SalesInitial) {
bloc.getAllItems();
}
return Scaffold(
drawer: const navDrawer(),
appBar: AppBar(
title: const Text("Ticket"),
actions: [
IconButton(
onPressed: () async {
String barcodeScanRes;
// Platform messages may fail, so we use a try/catch PlatformException.
try {
barcodeScanRes = await FlutterBarcodeScanner.scanBarcode(
'#ff6666', 'Cancel', true, ScanMode.BARCODE);
print('barcodeScanRes $barcodeScanRes');
print(bloc.bsResult);
} on PlatformException {
barcodeScanRes = 'Failed to get platform version.';
}
// If the widget was removed from the tree while the asynchronous platform
// message was in flight, we want to discard the reply rather than calling
// setState to update our non-existent appearance.
if (!mounted) return;
bloc.toggleSearch();
controller.text = barcodeScanRes;
bloc.filterItems(barcodeScanRes);
},
icon: const Icon(Icons.scanner),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: IconButton(
onPressed: () {
Navigator.of(context).pushNamed(Routes.addCustomerRoute);
},
icon: Icon(Icons.person_add)),
),
],
),
body: Column(
children: [
// the first button
Container(
width: double.infinity,
height: deviceSize.height * .1,
color: Colors.grey,
child: GestureDetector(
onTap: ()=>displayMessage("an item was charged successfully", context),
child: Padding(
padding: const EdgeInsets.all(10),
child: Container(
color: Colors.green,
child: const Center(
child: Text("charge",style: TextStyle(color: Colors.white),),
),
),
),
),
),
// the second container
SizedBox(
width: deviceSize.width,
height: deviceSize.height * .1,
child: Row(
children: [
DecoratedBox(
decoration:
BoxDecoration(border: Border.all(color: Colors.grey)),
child: SizedBox(
width: deviceSize.width * .8,
child: bloc.isSearch
? TextFormField(
autofocus: true,
controller: controller,
decoration:
const InputDecoration(hintText: "Search"),
onChanged: (value) {
bloc.filterItems(controller.text);
},
)
: DropdownButtonFormField<String>(
// underline: Container(),
// value: "Discounts",
hint: const Padding(
padding: EdgeInsets.only(left: 10),
child: Text('Please choose type'),
),
items: <String>['Discounts', 'All Items']
.map((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
onChanged: (_) {},
),
),
),
DecoratedBox(
decoration:
BoxDecoration(border: Border.all(color: Colors.grey)),
child: SizedBox(
width: deviceSize.width * .2,
child: IconButton(
onPressed: () {
bloc.toggleSearch();
if (!bloc.isSearch) {
bloc.filterItems('');
}
},
icon: Icon(
!bloc.isSearch ? Icons.search : Icons.close)),
),
)
],
),
),
// the third container
if (state is IsLoading || state is SalesInitial)
const Center(
child: CircularProgressIndicator(
color: Colors.green,
backgroundColor: Colors.green,
),
),
if (state is Loaded || state is IsSearch || state is SearchDone)
bloc.items.isEmpty
? const Center(
child: Text("no items added yet"),
)
: Expanded(
child: bloc.filteredItems.isEmpty
? const Center(
child: Text(
"no items found with this name",
style: TextStyle(color: Colors.green),
),
)
: ListView.builder(
itemCount: bloc.filteredItems.length,
itemBuilder: (context, i) {
final item = bloc.filteredItems[i];
return Card(
child: ListTile(
leading: CircleAvatar(
backgroundColor: Colors.green,
radius: 20,
child: Text(item.price),
),
title: Text(item.name),
subtitle: Text(item.barcode),
trailing: Column(
children: [
IconButton(
onPressed: () {
showAlertDialog(context,item.name);
// bloc.deleteItem(item.name).then((value) {
// bloc.getAllItems();
// });
},
icon: const Icon(
Icons.delete,
color: Colors.red,
))
],
)),
);
}))
],
),
floatingActionButton: FloatingActionButton(
child: const Icon(Icons.add),
onPressed: ()async {
Navigator.of(context).pushNamed(Routes.createItemRoute);
},
),
);
},
);
}
}
the CreateItem screen
class _CreateItemState extends State<CreateItem> {
final nameController = TextEditingController();
final priceController = TextEditingController();
final costController = TextEditingController();
final skuController = TextEditingController();
final barcodeController = TextEditingController();
final inStockController = TextEditingController();
bool each = true; // bool variable for check box
bool isColor = true;
bool switchValue = false;
File? file;
String base64File = "";
String path = "";
final _formKey = GlobalKey<FormState>();
#override
void dispose() {
nameController.dispose();
priceController.dispose();
costController.dispose();
skuController.dispose();
barcodeController.dispose();
inStockController.dispose();
super.dispose();
}
Future pickImage(ImageSource source) async {
File? image1;
XFile imageFile;
final imagePicker = ImagePicker();
final image = await imagePicker.pickImage(source: source);
imageFile = image!;
image1 = File(imageFile.path);
List<int> fileUnit8 = image1.readAsBytesSync();
setState(() {
base64File = base64.encode(fileUnit8);
});
}
#override
Widget build(BuildContext context) {
final deviceSize = MediaQuery.of(context).size;
return BlocProvider(
create: (BuildContext context) => CreateItemCubit(),
child: Builder(builder: (context){
final bloc=BlocProvider.of<CreateItemCubit>(context);
return Scaffold(
appBar: AppBar(
leading: IconButton(
onPressed: () => Navigator.of(context).pushNamedAndRemoveUntil(Routes.newSalesRoute, (route) => false),
icon: const Icon(Icons.arrow_back)),
title: const Text("Create Item"),
actions: [TextButton(onPressed: () {}, child: const Text("SAVE"))],
),
body: Padding(
padding: const EdgeInsets.all(10),
child: Form(
key: _formKey,
child: ListView(
children: [
TextFormField(
controller: nameController,
cursorColor: ColorManager.black,
decoration: const InputDecoration(hintText: "Name"),
validator: (value) {
if (value!.isEmpty || value.length < 5) {
return "name can't be less than 5 chars";
}
return null;
},
),
gapH24,
Text(
"Category",
style: TextStyle(color: ColorManager.grey),
),
SizedBox(
width: deviceSize.width,
child: DropdownButtonFormField<String>(
// value: "Categories",
hint: const Padding(
padding: EdgeInsets.only(left: 10),
child: Text('No Category'),
),
items: <String>['No Category', 'Create Category']
.map((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
onChanged: (_) {},
),
),
gapH24,
const Text(
"Sold by",
style: TextStyle(color: Colors.black),
),
gapH24,
Row(
children: [
Checkbox(
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(5.0))), // Rounded Checkbox
value: each,
onChanged: (inputValue) {
setState(() {
each = !each;
});
},
),
gapW4,
const Text(
"Each",
style: TextStyle(fontWeight: FontWeight.bold),
),
],
),
gapH24,
Row(
children: [
Checkbox(
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(5.0))), // Rounded Checkbox
value: !each,
onChanged: (inputValue) {
setState(() {
each = !each;
});
},
),
gapW4,
const Text(
"Weight",
style: TextStyle(fontWeight: FontWeight.bold),
),
],
),
TextFormField(
controller: priceController,
decoration: InputDecoration(
hintText: "Price",
hintStyle: TextStyle(color: ColorManager.grey)),
validator: (value) {
if (value!.isEmpty) {
return "price can,t be empty";
}
return null;
},
),
gapH4,
Text(
"leave the field blank to indicate price upon sale",
style: TextStyle(color: ColorManager.grey),
),
gapH20,
Text(
"Cost",
style: TextStyle(color: ColorManager.grey),
),
TextFormField(
controller: costController,
decoration: InputDecoration(
hintText: "cost",
hintStyle: TextStyle(color: ColorManager.black)),
validator: (value) {
if (value!.isEmpty) {
return "cost can't be empty";
}
return null;
},
),
gapH20,
Text(
"SKU",
style: TextStyle(color: ColorManager.grey),
),
TextFormField(
controller: skuController,
decoration: InputDecoration(
hintText: "Sku",
hintStyle: TextStyle(color: ColorManager.black)),
validator: (value) {
if (value!.isEmpty) {
return "Sku can't be empty";
}
return null;
},
),
gapH30,
TextFormField(
controller: barcodeController,
decoration: InputDecoration(
hintText: "Barcode",
hintStyle: TextStyle(color: ColorManager.grey)),
validator: (value) {
if (value!.isEmpty) {
return "Barcode can't be empty";
}
return null;
},
),
gapH30,
// Divider(thickness: 1,color: ColorManager.black,),
Text(
"Inventory",
style: TextStyle(
color: ColorManager.green,
fontSize: 15,
fontWeight: FontWeight.bold),
),
// ListTile(
// title: Text("TrackStock",style: TextStyle(color: ColorManager.green,fontSize: 15,fontWeight: FontWeight.bold)),
// trailing: Switch(value: switchValue, onChanged: (bool value) {
// setState(() {
// switchValue=!switchValue;
// });
// },),
// ),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text("TrackStock",
style: TextStyle(
color: ColorManager.grey,
fontSize: 15,
fontWeight: FontWeight.bold)),
Switch(
value: switchValue,
onChanged: (bool value) {
setState(() {
switchValue = !switchValue;
});
},
),
],
),
gapH10,
if (switchValue)
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"in stock",
style:
TextStyle(color: ColorManager.grey, fontSize: 15),
),
TextFormField(
keyboardType: TextInputType.number,
controller: inStockController,
decoration: const InputDecoration(hintText: "0"),
validator: (value) {
if (value!.isEmpty) {
return "value can't be empty";
}
return null;
},
)
],
),
gapH20,
Text(
"Representation in POS",
style: TextStyle(
color: ColorManager.green,
fontSize: 15,
fontWeight: FontWeight.bold),
),
gapH15,
Row(
children: [
Checkbox(
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(5.0))), // Rounded Checkbox
value: isColor,
onChanged: (inputValue) {
setState(() {
if (!isColor) {
isColor = !isColor;
}
});
},
),
gapW4,
const Text(
"Color and Shape",
style: TextStyle(fontWeight: FontWeight.bold),
),
],
),
gapH10,
Row(
children: [
Checkbox(
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(5.0))), // Rounded Checkbox
value: !isColor,
onChanged: (inputValue) {
setState(() {
if (isColor) {
isColor = !isColor;
}
});
},
),
gapW4,
const Text(
"Image",
style: TextStyle(fontWeight: FontWeight.bold),
),
],
),
isColor
? GridView.builder(
physics:
const NeverScrollableScrollPhysics(), // to disable GridView's scrolling
shrinkWrap: true, // You won't see infinite size error
gridDelegate:
const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 4,
crossAxisSpacing: 5.0,
mainAxisSpacing: 5.0,
),
itemCount: containers().length,
itemBuilder: (BuildContext context, int index) {
return containers()[index];
},
)
: Padding(
padding: const EdgeInsets.all(10),
child: Row(
children: [
Expanded(
flex: 1,
child: base64File == ""
? const Icon(Icons.person)
: Container(
decoration: BoxDecoration(
borderRadius:
BorderRadius.circular(5)),
child: Image.memory(
base64.decode(base64File)))),
gapW4,
Expanded(
flex: 2,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
TextButton(
onPressed: () =>
pickImage(ImageSource.camera),
child: Row(
children: [
Icon(
Icons.camera_alt,
color: ColorManager.black,
),
gapW8,
Text(
"Take a photo",
style: TextStyle(
color: ColorManager.black,
),
)
],
),
),
const Divider(
thickness: 1,
color: Colors.grey,
),
TextButton(
onPressed: () =>
pickImage(ImageSource.gallery),
child: Row(
children: [
Icon(Icons.camera_alt,
color: ColorManager.black),
gapW8,
Text(
"Choose from gallery",
style: TextStyle(
color: ColorManager.black,
),
)
],
),
)
],
),
)
],
),
)
],
),
),
),
floatingActionButton: FloatingActionButton(
child: const Icon(Icons.save,color: Colors.white,),
onPressed: () async {
bool isValid = _formKey.currentState!.validate();
if (isValid) {
FocusScope.of(context).unfocus();
ItemModel? item=await bloc.checkItem(nameController.text);
if(item!=null){
displayMessage("this item was inserted before", context);
}else{
int? res=await bloc.saveItem(ItemModel(
nameController.text,
priceController.text,
costController.text,
skuController.text,
barcodeController.text));
if(res!=null){
displayMessage("an item was inserted successfully", context);
Navigator.of(context).pushAndRemoveUntil(MaterialPageRoute(builder: (context)=>const NewSales()), (route) => false);
}
}
}
},
),
);
}
),
);
}
}
this is the SaleCubit
class SalesCubit extends Cubit<SalesState> {
SalesCubit() : super(SalesInitial());
bool isSearch=false;
ItemDBHelper db=ItemDBHelper();
List<ItemModel> items=[];
List<ItemModel> filteredItems=[];
String bsResult='Unknown'; //barcode search result
void toggleSearch(){
isSearch=!isSearch;
emit(IsSearch());
}
void setBarcodeResult(String value){
bsResult=value;
emit(SearchDone());
}
void filterItems(String query){
// emit(Searching());
query.isEmpty?
filteredItems=items:
filteredItems=items.where((item) => item.name.toLowerCase().contains(query.toLowerCase())).toList();
emit(SearchDone());
}
Future<List<ItemModel>?> getAllItems()async{
try{
emit(IsLoading());
items=await db.getAllItems();
filteredItems=items;
print(items);
return items;
}finally{
emit(Loaded());
}
}
Future<void> deleteItem(String name)async{
await db.deleteItem(name);
emit(SearchDone());
}
}
this is the SalesState
part of 'sales_cubit.dart';
#immutable
abstract class SalesState {}
class SalesInitial extends SalesState {}
class IsSearch extends SalesState {}
class IsLoading extends SalesState {}
class Loaded extends SalesState {}
class Searching extends SalesState {}
class SearchDone extends SalesState {}
I have created a container. His child is a text.
When I tap on the container/text, it display a modal and a Picker.
Then, the user can select a value. Press the confirm button and my text widget should change to display the value selected by the user.
But in my case, it is not updating the value of the text widget. I have used that in the past and it was working very well. But here it is not and I do not see why. I am on this since 8:00. A little help would be appreciated. Many thanks.
int valuePickerUnitSelected =0;
String unitCount = '';
int unitCountInt;
String goal = "";
List <String> unitForHabits = ['Count', 'Minute(s)','Hour(s)','Gramme(s)', 'Pound(s)'];
class AddingHabitDetails extends StatefulWidget {
const AddingHabitDetails({Key key}) : super(key: key);
#override
_AddingHabitDetailsState createState() => _AddingHabitDetailsState();
}
class _AddingHabitDetailsState extends State<AddingHabitDetails> {
BuildContext get ctx => null;
#override
Widget build(BuildContext context) {
return Scaffold(
//drawer: new MyMenu(), //TODO a remettre
appBar: new AppBar(
title: new Text('Habits'),
),
body: Column(
children: [
titleZone('Name'),
textFieldHabits('Habit name', context),
titleZone('Goals'),
FlatButton(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
if (unitCount.length < 2 )...[
Container(
width: 65,
decoration: BoxDecoration(
border: Border.all(color: Colors.blue,
),
color: Colors.blue,
borderRadius: BorderRadius.all(Radius.circular(20))),
child:
Center(child: Text(
'Time', style: TextStyle(color: Colors.black,))))
]
else
...[
Container(
width: 65,
decoration: BoxDecoration(
border: Border.all(color: Colors.blue,),
color: Colors.blue,
borderRadius: BorderRadius.all(
Radius.circular(20))),
child: Center(
child: Text(
unitCount, style: TextStyle(color: Colors.black,))))
],
],
),
onPressed: () {
setState(() {
showModalBottomSheet(
context: context,
builder: (BuildContext context) {
return ShowPickerUnite(unitForHabits);
});
},
);
},
),
//ChipGoalV3(ctx),// ChipGoal(),
textFieldHabits('Goals', context),
titleZone('Frequency'),
textFieldHabits('Frequency', context),
titleZone('Time Range'),
titleZone('Reminder'),
titleZone('Habits Term'),
],
),
);
}
}
//########################################################################
class ShowPickerUnite extends StatefulWidget {
List<String> myListUnit;
ShowPickerUnite(this.myListUnit, {Key key}) : super(key: key);
#override
_ShowPickerUniteState createState() => _ShowPickerUniteState(
myListUnit);
}
class _ShowPickerUniteState extends State<ShowPickerUnite> {
List <String> myListUnit;
_ShowPickerUniteState(this.myListUnit);
#override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Container(
decoration: BoxDecoration(
color: Color(0xffffffff),
border: Border(
bottom: BorderSide(
color: Color(0xffffffff),
width: 0.0,
),
),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
CupertinoButton(
child: Text('Cancel'),
onPressed: () {
Navigator.of(context).pop();
},
padding: const EdgeInsets.symmetric(
horizontal: 16.0,
vertical: 5.0,
),
),
DefaultTextStyle(
style: TextStyle(
fontSize: 16.0,
color: Colors.black,
fontWeight: FontWeight.bold),
child: Text('Select what you want'),
),
// Text('Energy Needed', style: TextStyle(fontSize: 12.0, color: Colors.black),
// ),
CupertinoButton(
child: Text('Confirm'),
onPressed: () {
setState(() {
unitCount = unitForHabits[valuePickerUnitSelected];
print(unitCount);
});
Navigator.of(context).pop();
},
padding: const EdgeInsets.symmetric(
horizontal: 16.0,
vertical: 5.0,
),
),
],
),
),
Container(
//width: 360,
height: 200,
decoration:BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(15.0)),
),
child: CupertinoPicker(
backgroundColor: Colors.white ,
useMagnifier: true,
magnification: 1.3,
scrollController: FixedExtentScrollController(initialItem: 0),
itemExtent: 25,
children: [
for (String name in myListUnit)
Center(
child:Text(name)),
],
onSelectedItemChanged: (value) {
setState(() {
valuePickerUnitSelected = value;
// taskEnergy = myListEnergy[valuePickerEnergySelected];
// taskNewValue ['task_Energy'] = taskEnergy;
});
}))
]);
}
}
Widget inputNameHabit (){
return Padding(
padding: const EdgeInsets.all(8.0),
child: Text ('Name Habits',style: TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold),),
);
}
Widget titleZone (String _titleName){
return Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: [
Text ( _titleName,
style: TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold),),
],
),
);
}
Widget textFieldHabits (String item,context){
return TextField(
decoration: InputDecoration(
hintText: item,
filled: true,
fillColor: Colors.grey[300],
border: OutlineInputBorder(
borderSide: BorderSide.none,
borderRadius: BorderRadius.circular(50)
),
),
onTap: (){
Navigator.push(context,
MaterialPageRoute(
builder: (context) => HabitGoalUnitSelection(), //TODO MODIFIER route selon source
),
);
},);
}
Wait for the dialog to finish and then call setState to update the UI.
Modify this way
onPressed: () async {
await showModalBottomSheet(
context: context,
builder: (BuildContext context) {
return ShowPickerUnite(unitForHabits);
});
setState(() {});
With my current code, my list is put into separate cards. I need it to be in one. I'm using two ListView.builders and a loop. I believe that's what's causing the problem. Please tell me if I'm wrong.
Every time the user taps submit on my second TextField a new TextField appears, functionality I would like to keep one way or another.
I'm just staring out so any help if appreciated.
My end goal is to have a bullet point list but the bullet points aren't important right now.
Here's my code:
class PostNote extends StatefulWidget {
User user;
PostNote({
required this.user,
});
#override
State<PostNote> createState() => _PostNoteState();
}
class _PostNoteState extends State<PostNote> {
FirebaseFirestore firestore = FirebaseFirestore.instance;
TextEditingController titleController = TextEditingController();
final List<TextField> _textFields = [];
final List<TextEditingController> _controllers = [];
bool loading = false;
#override
void initState() {
super.initState();
_addTextField();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Color(0xFF162242),
elevation: 0,
),
body: GestureDetector(
onTap: () {
FocusScope.of(context).unfocus();
},
child: SingleChildScrollView(
child: Padding(
padding: EdgeInsets.all(20),
child: Column(
children: [
Text(
"Title",
style: TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
SizedBox(
height: 15,
),
Container(
height: 60,
decoration: BoxDecoration(
borderRadius: BorderRadius.all(
Radius.circular(10),
),
color: Colors.white,
),
padding: EdgeInsets.only(left: 10, right: 10),
child: TextField(
decoration: InputDecoration(
enabledBorder: UnderlineInputBorder(
borderSide: BorderSide(color: Colors.transparent),
),
),
textInputAction: TextInputAction.next,
style: TextStyle(
color: Color(0xFF192A4F),
fontSize: 18,
),
controller: titleController,
autofocus: true,
),
),
SizedBox(
height: 30,
),
Text(
"Notes",
style: TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
SizedBox(
height: 15,
),
Container(
padding: EdgeInsets.only(left: 10, right: 10),
decoration: BoxDecoration(
borderRadius: BorderRadius.all(
Radius.circular(10),
),
color: Colors.white,
),
child: ListView.builder( // HERE
shrinkWrap: true,
itemCount: _textFields.length,
itemBuilder: (_, index) {
return _textFields[index];
},
),
),
SizedBox(
height: 50,
),
loading
? Center(
child: CircularProgressIndicator(),
)
: Container(
height: 50,
width: MediaQuery.of(context).size.width,
child: ElevatedButton(
child: Text(
"Add Note",
style: TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold,
),
),
style: ButtonStyle(
backgroundColor:
MaterialStateProperty.all(Color(0xFF162242)),
shape: MaterialStateProperty.all<
RoundedRectangleBorder>(
RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
),
),
onPressed: () async {
for (var notesController in _controllers) // HERE {
if (titleController.text == "" ||
notesController.text.isEmpty) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content:
Text("All fields are required")));
} else {
setState(() {
loading = true;
});
await FirestoreServiceEdit().insertNote(
titleController.text,
notesController.text,
widget.user.uid);
CollectionReference notes =
firestore.collection('notes');
QuerySnapshot allResults = await notes.get();
allResults.docs.forEach((DocumentSnapshot result) {
print(result.data());
});
if (!mounted) return;
setState(() {
loading = false;
});
Navigator.pop(context);
}
}
}),
),
]),
),
),
),
);
}
void _addTextField() {
final notesController = TextEditingController();
_textFields.add(
TextField(
decoration: InputDecoration(
prefix: Icon(
Icons.circle,
size: 8,
color: Colors.black,
),
),
autofocus: true,
controller: notesController,
onSubmitted: (_) => setState(() => _addTextField()),
),
);
_controllers.add(notesController);
}
}
class FirestoreServiceEdit{
FirebaseFirestore firestore = FirebaseFirestore.instance;
Future insertNote(String title, String notes, String? userId,)async{
try{
await firestore.collection('notes').add({
"title":title,
"notes":notes,
"userId":userId
});
} catch (e) {}
}
}
class NoteModelEdit {
String id;
String title;
String notes;
String userId;
NoteModelEdit({
required this.id,
required this.title,
required this.notes,
required this.userId
});
factory NoteModelEdit.fromJson(DocumentSnapshot snapshot){
return NoteModelEdit(
id: snapshot.id,
title: snapshot['title'],
notes: snapshot['notes'],
userId: snapshot['userId']
);
}
}
Home screen:
body: StreamBuilder(
stream: FirebaseFirestore.instance
.collection("notes")
.where('userId', isEqualTo: user.uid)
.snapshots(),
builder: (context, AsyncSnapshot snapshot) {
if (snapshot.hasData) {
if (snapshot.data.docs.length > 0) {
return ListView.builder( // HERE
itemCount: snapshot.data.docs.length,
itemBuilder: (context, index) {
NoteModelEdit note =
NoteModelEdit.fromJson(snapshot.data.docs[index]);
return Card(
margin: EdgeInsets.only(top: 18, left: 15, right: 15),
child: Column(children: [
ListTile(
title: Center(
child: Container(
padding: EdgeInsets.only(bottom: 10),
decoration: BoxDecoration(
border: Border(
bottom: BorderSide(width: 0.5),
),
),
child: Text(
note.title,
textWidthBasis: TextWidthBasis.longestLine,
style: TextStyle(
fontSize: 40,
fontWeight: FontWeight.w600),
textAlign: TextAlign.center,
),
),
),
onTap: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (context) => EditNoteScreen(),
));
},
),
SizedBox(
height: 15,
),
Align(
alignment: Alignment.centerLeft,
child: Text(
note.notes,
textAlign: TextAlign.left,
style: TextStyle(
fontSize: 18, fontWeight: FontWeight.w700),
),
),
SizedBox(
height: 15,
),
]),
);
});
Thank you for your time!
You will need to augment your logic to look at all the TextFields at the same time rather than one at a time and inserting a note for each.
if (titleController.text.isEmpty ||
_controllers.any((element) => element.text.isEmpty)) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content:
Text("All fields are required")));
} else {
setState(() {
loading = true;
});
}
await FirestoreServiceEdit().insertNote(
titleController.text,
_controllers.map((element) => element.text).join("\n"),
widget.user.uid);
you can do like this :
Widget listInCard() {
List testList = ["note1", "note2", "note3"];
return Card(
color: Colors.blue.shade200,
elevation: 5,
child: ListView.builder(
itemCount: testList.length,
itemBuilder: (context, index) {
return Text(testList[index]);
}),
);
}
The blue color is the Card and inside it, it is a list of notes.
You can also use Container instead of Card.
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.
This my contacts list page
class Contacts extends StatefulWidget with NavigationStates {
#override
_ContactsState createState() => _ContactsState();
}
class _ContactsState extends State<Contacts>{
DatabaseHelper databaseHelper = DatabaseHelper();
List<contacts> contactsList;
int count = 0;
#override
Widget build(BuildContext context, ) {
if(contactsList == 0){
contactsList = List<contacts>();
updateListView();
}
return Scaffold(
resizeToAvoidBottomPadding: false,
appBar: AppBar(
title: Text("Contacts"),
backgroundColor: Colors.lightGreenAccent,
centerTitle: true,
),
body: Column(
children: <Widget>[
Container(
padding: EdgeInsets.all(4.0),
margin: EdgeInsets.all(5.0),
child: TextField(
//controller: searchController,
decoration: InputDecoration(
labelText:'Search Contacts',
border: new OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(25)),
borderSide: new BorderSide(
color: Colors.pinkAccent
)
),
prefixIcon: Icon(
Icons.search,
color: Colors.black,
)
),
),
),
Expanded(
child: ListView.builder(
itemCount: count,
itemBuilder: (context , int position){
return Card(
elevation: 1.0,
shape: RoundedRectangleBorder(
side: BorderSide(color: Colors.pinkAccent,width: 1),
borderRadius: BorderRadius.circular(20)
),
child: Container(
margin: EdgeInsets.all(6.0),
padding: EdgeInsets.all(4.0),
color: Colors.white,
child: ListTile(
leading: CircleAvatar(
radius: 30.0,
backgroundColor: Colors.lightBlueAccent,
child: Icon(Icons.person,color: Colors.black,),
),
title: Text(this.contactsList[position].first_name,style: TextStyle(color: Colors.black,fontSize: 28.0),),
subtitle: Text(this.contactsList[position].last_name,style:TextStyle(color: Colors.black38,fontSize: 15.0),),
trailing: GestureDetector(
child: Icon(Icons.delete, color: Colors.pinkAccent,),
onTap: () {
_delete(context, contactsList[position]);
},
),
),
),
);
},
),
)
],
),
floatingActionButton: new FloatingActionButton(onPressed: null,
child: new Icon(Icons.dialpad,color: Colors.black,size: 30,),
backgroundColor: Colors.pinkAccent,
),
bottomNavigationBar: CurvedNavigationBar(
color: Colors.lightGreenAccent,
backgroundColor: Colors.white,
buttonBackgroundColor: Colors.pinkAccent,
height: 50,
index: 1,
items:<Widget>[
Icon(Icons.call,size: 25,color: Colors.black,),
Icon(Icons.home,size: 30,color: Colors.black,),
Icon(Icons.person_add_rounded,size: 25,color: Colors.black,),
],
animationDuration: Duration(
milliseconds: 400
),
animationCurve: Curves.easeIn,
onTap: (index) async {
if (index == 0)
Navigator.of(context).push(
MaterialPageRoute(
builder: (BuildContext context) {
return logs();
}
)
);
if (index == 1)
Navigator.of(context).push(
MaterialPageRoute(
builder: (BuildContext context) {
return Contacts();
}
)
);
if (index == 2)
navigateToDetail(contacts('',''));
}
),
);
}
updateListView() {
final Future<Database> dbFuture = databaseHelper.initalizeDatabase();
dbFuture.then((database) {
Future<List<contacts>> contactsListFuture = databaseHelper.getContactList();
contactsListFuture.then((contactsList){
setState(() {
this.contactsList = contactsList;
this.count = contactsList.length;
});
});
});
}
Color getStorageColor() {
int storage;
switch (storage) {
case 1:
return Colors.pinkAccent;
break;
case 2:
return Colors.lightBlueAccent;
break;
default:
return Colors.lightBlueAccent;
}
}
void navigateToDetail(contacts contact) async{
bool result = await Navigator.push(context, MaterialPageRoute(builder: (context) {
return AddContacts(contact);
}));
if (result == true) {
updateListView();
}
}
void _delete(BuildContext context, contacts contact) async {
int result = await databaseHelper.deleteContact(contact.id);
if (result != 0) {
_SnackBar(context, 'Contact Deleted Successfully');
updateListView();
}
}
void _SnackBar(BuildContext context, String message) {
final snackBar = SnackBar(
content: Text(message),
action: SnackBarAction(
label: 'Undo',
onPressed: (){},
),
);
// ignore: deprecated_member_use
Scaffold.of(context).showSnackBar(snackBar);
}
}
This is my contacts details page
import 'dart:io';
//import 'package:contacts_service/contacts_service.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
//import 'package:sqflite/sqflite.dart';
import 'package:mycontacts_app/models/Contact.dart';
import 'dart:async';
import 'package:mycontacts_app/utils/database_helper.dart';
//import 'package:intl/intl.dart';
class AddContacts extends StatefulWidget {
final contacts contact;
AddContacts(this.contact);
//AddContacts(contacts contact);
#override
State<StatefulWidget> createState() {
// _AddContactsState();
return _AddContactsState(this.contact);
}
}
class _AddContactsState extends State<AddContacts> {
//TextEditingController _fnameController,_numberController,_lnameController;
DatabaseHelper helper = DatabaseHelper();
PickedFile _imageFile;
final ImagePicker _picker = ImagePicker();
_AddContactsState(this.contact);
TextEditingController _fnameController = TextEditingController();
TextEditingController _numberController = TextEditingController();
TextEditingController _lnameController = TextEditingController();
contacts contact;
List _Storage = ['Phone','Sim'];
//String _storageval;
#override
Widget build(BuildContext context) {
//_nameController = contacts.first_name
_fnameController.text = contact.first_name;
_lnameController.text = contact.last_name;
_numberController.text = contact.phone_no as String;
return Scaffold(
appBar: AppBar(
title: Text("New Contact"),
backgroundColor: Colors.lightGreenAccent,
centerTitle: true,
),
body: SingleChildScrollView(
child: Container(
padding: EdgeInsets.symmetric(
vertical: 40.0,
horizontal: 10.0,
),
//margin: EdgeInsets.all(15),
child: Form(
child: Column(
//crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Padding(
padding: const EdgeInsets.all(16.0),
child: Container(
padding: EdgeInsets.only(left: 16.0,right: 16.0),
decoration: BoxDecoration(
border: Border.all(
color: Colors.white
),
borderRadius: BorderRadius.circular(20.0),
),
child: DropdownButton(
hint: Text('Store In '),
dropdownColor: Colors.black12,
elevation: 5,
icon: Icon(Icons.arrow_drop_down),
iconSize: 20.0,
isExpanded: true,
style: TextStyle(
color: Colors.black,fontSize: 18.0
),
items: _Storage.map((value){
return DropdownMenuItem(
value: value,
child: Text(value),
);
}).toList(),
value: getStorageAsString(contact.storage),
onChanged: (value){
setState(() {
//_storageval = value;
updateStorageAsInt(value);
});
},
),
),
),
imageProfile(),
Padding(
padding: const EdgeInsets.all(8.0),
child: TextFormField(
controller: _fnameController,
onChanged: (value){
updateFirstname();
},
decoration: InputDecoration(
hintText: 'First Name',
prefixIcon: Icon(Icons.person),
//prefixText: "Name",
suffixIcon: Icon(Icons.keyboard_arrow_down),
fillColor: Colors.white,
filled: true,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(20.0),
),
contentPadding: EdgeInsets.all(15),
),
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: TextFormField(
controller: _lnameController,
onChanged: (value){
updateLastName();
},
decoration: InputDecoration(
hintText: 'Last Name',
prefixIcon: Icon(Icons.person),
//prefixText: "Name",
//suffixIcon: Icon(Icons.keyboard_arrow_down),
fillColor: Colors.white,
filled: true,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(20.0),
),
contentPadding: EdgeInsets.all(15),
),
),
),
// SizedBox(height: 15),
Padding(
padding: const EdgeInsets.all(8.0),
child: TextFormField(
controller: _numberController,
onChanged: (value){
//updateNumber();
},
decoration: InputDecoration(
hintText: 'Number',
prefixIcon: Icon(Icons.phone_android),
//prefixText: "Name",
//suffixIcon: Icon(Icons.keyboard_arrow_down),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(20.0),
),
fillColor: Colors.white,
filled: true,
contentPadding: EdgeInsets.all(15),
),
),
),
//SizedBox(height: 15),
Padding(
padding: const EdgeInsets.all(8.0),
child: TextFormField(
//controller: _nameController,
decoration: InputDecoration(
hintText: 'Address',
prefixIcon: Icon(Icons.location_on_rounded),
//prefixText: "Name",
suffixIcon: Icon(Icons.keyboard_arrow_down),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(20.0),
),
fillColor: Colors.white,
filled: true,
contentPadding: EdgeInsets.all(15),
),
),
),
//SizedBox(height: 15),
Padding(
padding: const EdgeInsets.all(8.0),
child: TextFormField(
//controller: _nameController,
decoration: InputDecoration(
hintText: 'Email',
prefixIcon: Icon(Icons.email),
//prefixText: "Name",
//suffixIcon: Icon(Icons.keyboard_arrow_down),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(20.0),
),
fillColor: Colors.white,
filled: true,
contentPadding: EdgeInsets.all(15),
),
),
),
//SizedBox(height: 15),
Padding(
padding: const EdgeInsets.all(8.0),
child: TextFormField(
//controller: _nameController,
decoration: InputDecoration(
hintText: 'Website',
prefixIcon: Icon(Icons.language),
//prefixText: "Name",
//suffixIcon: Icon(Icons.keyboard_arrow_down),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(20.0),
),
fillColor: Colors.white,
filled: true,
contentPadding: EdgeInsets.all(15),
),
),
),
//SizedBox(height: 15),
Padding(
padding: const EdgeInsets.all(8.0),
child: TextFormField(
//controller: _nameController,
decoration: InputDecoration(
hintText: 'Work Info',
prefixIcon: Icon(Icons.business),
//prefixText: "Name",
//suffixIcon: Icon(Icons.keyboard_arrow_down),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(20.0),
),
fillColor: Colors.white,
filled: true,
contentPadding: EdgeInsets.all(15),
),
),
),
/*ListView.builder(
itemBuilder: (context, index){
return ExpansionTile(
title: ListTile(
title: TextField(
decoration: InputDecoration(
hintText: "Name"
),
style: TextStyle(
color: Colors.black,
fontSize: 15.0,
),
),
),
children: <Widget>[
ListTile(
title:TextFormField(
decoration: InputDecoration(
hintText: "Name Prefix"
),
)
),
ListTile(
title:TextFormField(
decoration: InputDecoration(
hintText: " First Name"
),
)
),
ListTile(
title:TextFormField(
decoration: InputDecoration(
hintText: " Middle Name"
),
)
),
ListTile(
title:TextFormField(
decoration: InputDecoration(
hintText: "Last Name"
),
)
),
ListTile(
title:TextFormField(
decoration: InputDecoration(
hintText: "Name Suffix"
),
)
)
],
);
}
)*/
Padding(
padding: const EdgeInsets.only(top: 15.0, bottom: 15.0),
child: Row(
children: <Widget>[
Expanded(
child: RaisedButton(
color: Colors.lightGreenAccent,
textColor: Colors.black,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(18.0),
side: BorderSide(color: Colors.pinkAccent),
),
onPressed: () {
debugPrint("Save button clicked");
_save();
},
child: Text(
"Save"
),
),
),
Container(width: 5.0,),
Expanded(
child: RaisedButton(
color: Colors.lightGreenAccent,
textColor: Colors.black,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(18.0),
side: BorderSide(color: Colors.pinkAccent),
),
onPressed: () {
_delete();
},
child: Text(
"Cancel"
),
),
)
],
),
)
],
),
),
),
),
);
}
Widget imageProfile() {
return Center(
child: Stack(
children: <Widget>[
CircleAvatar(
radius: 50.0,
backgroundImage: _imageFile==null? AssetImage("assets/default.png"):FileImage(File(_imageFile.path)),
),
Positioned(
bottom: 20.0,
right: 20.0,
child: InkWell(
onTap: () {
showModalBottomSheet(
context: context,
builder: ((builder) => bottomSheet()),
);
},
child: Icon(
Icons.camera_alt,
color: Colors.lightGreenAccent,
size: 28.0,
),
),
),
],
),
);
}
Widget bottomSheet() {
return Container(
height: 100.0,
width: MediaQuery.of(context).size.width,
margin: EdgeInsets.symmetric(
horizontal: 20,
vertical: 20,
),
child: Column(
children: <Widget>[
Text(
"Choose Contact Image",
style: TextStyle(
fontSize: 20,
),
),
SizedBox(
height: 20,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
FlatButton.icon(
icon: Icon(Icons.camera),
onPressed: (){
takePhoto(ImageSource.camera);
},
label: Text("Camera"),
),
FlatButton.icon(
icon: Icon(Icons.image),
onPressed: (){
takePhoto(ImageSource.gallery);
},
label: Text("Gallery"),
)
],
)
],
),
);
}
void takePhoto(ImageSource source) async {
final pickedFile = await _picker.getImage(
source: source,
);
setState(() {
_imageFile = pickedFile;
});
}
void updateFirstname(){
contact.first_name = _fnameController.text;
}
// Update the description of Note object
void updateLastName() {
contact.last_name = _lnameController.text;
}
/*void updateNumber() {
contact.phone_no = _numberController.text as int;
}*/
void _save() async {
moveToLastScreen();
//n.date = DateFormat.yMMMd().format(DateTime.now());
int result;
if (contact.id != null) { // Case 1: Update operation
result = await helper.updateContact(contact);
} else { // Case 2: Insert Operation
result = await helper.insertContact(contact);
}
if (result != 0) { // Success
_showAlertDialog('Status', 'Contact Saved Successfully');
} else { // Failure
_showAlertDialog('Status', 'Problem Saving Contact');
}
}
void moveToLastScreen() {
//Navigator.pop(context);
Navigator.pop(context, true);
}
void _delete() async {
moveToLastScreen();
// Case 1: If user is trying to delete the NEW NOTE i.e. he has come to
// the detail page by pressing the FAB of NoteList page.
if (contact.id == null) {
_showAlertDialog('Status','No Contact was deleted');
return;
}
// Case 2: User is trying to delete the old note that already has a valid ID.
int result = await helper.deleteContact(contact.id);
if (result != 0) {
_showAlertDialog('Status','Contact Deleted Successfully');
} else {
_showAlertDialog('Status', 'Error Occured while Deleting Contact');
}
}
void _showAlertDialog(String title, String message) {
AlertDialog alertDialog = AlertDialog(
title: Text(title),
content: Text(message),
);
showDialog(
context: context,
builder: (_) => alertDialog
);
}
void updateStorageAsInt(String value) {
switch (value) {
case 'Phone':
contact.storage = 1;
break;
case 'Sim':
contact.storage = 2;
break;
}
}
// Convert int priority to String priority and display it to user in DropDown
String getStorageAsString(int value) {
String storage;
switch (value) {
case 1:
storage = _Storage[0]; // 'High'
break;
case 2:
storage = _Storage[1]; // 'Low'
break;
}
return storage;
}
}
The contact card and icon is displayed but the name is not displaying.
I was even getting error like :-
This widget has been unmounted, so the State no longer has a context (and should be considered defunct).
It is not even showing the position or file of error
And I am not being able to solve the error .