Related
I have a profile page with some widgets which after saving and redrawing, they keep their new states, but my checkboxes do not, and I have not modified them at all. The new value is being saved on the database, but on the UI it's not preserved. If I turn the email checkbox to true, the 'true' boolean is saved, but it's not displayed on the frontend after pressing the submit button.
class _ProfilePageState extends State<ProfilePage> {
final _formKey = GlobalKey<FormState>();
bool? emailIsChecked = false;
bool? smsisChecked = false;
bool isTextFieldEnabled = false;
bool isIgnored = true;
bool isVisible = false;
bool editIsVisible = true;
bool emailIsEnabled = false;
bool smsIsEnabled = false;
bool nameEdit = false;
late TextEditingController countryController;
late TextEditingController languageController;
#override
void initState() {
super.initState();
countryController = TextEditingController(text: globals.signedInUser!.country);
languageController = TextEditingController(text: globals.signedInUser!.language);
selectedCountry = globals.signedInUser!.country;
selectedLanguage = globals.signedInUser!.language;
globals.signedInUser!.notifications.forEach(
(element) {
if ((element['type']) == 'Email') {
emailIsChecked = element['status'];
}
if ((element['type']) == 'SMS') {
smsisChecked = element['status'];
}
},
);
cleanInputStates();
}
#override
void dispose() {
countryController.dispose();
languageController.dispose();
super.dispose();
}
checkEditVisibility() {
if (editIsVisible == true) {
return true;
}
if (editIsVisible == false) {
return false;
}
}
checkEditAvailability() {
if (editIsVisible == false) {
return true;
}
if (editIsVisible == true) {
return false;
}
}
cleanInputStates() {
isTextFieldEnabled = false;
isIgnored = true;
editIsVisible = true;
isVisible = false;
smsIsEnabled = false;
emailIsEnabled = false;
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Form(
key: _formKey,
child: Row(
children: [
Flexible(
flex: 5,
child: Padding(
padding: const EdgeInsets.only(top: 20),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(
height: 30,
),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Visibility(
visible: editIsVisible,
maintainSize: true,
maintainAnimation: true,
maintainState: true,
child: ElevatedButton.icon(
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all(Colors.green)),
icon: const Icon(Icons.edit),
label: Text('Edit'),
onPressed: () {
setState(() {
isTextFieldEnabled = true;
isIgnored = false;
isVisible = true;
editIsVisible = false;
smsIsEnabled = true;
emailIsEnabled = true;
});
}),
),
SizedBox(
width: 250,
)
],
),
SizedBox(
height: 30,
),
Flexible(
flex: 1,
child: Padding(
padding: const EdgeInsets.only(top: 20),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(
height: 20,
),
... // TextFieldInputs
Row(
children: [
Container(
child: Text(
"Country: ",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 22,
color: Colors.black.withOpacity(0.3),
),
),
),
SizedBox(
width: 100,
),
Container(
width: 300,
child: IgnorePointer(
ignoring: isIgnored,
child: DropdownButtonFormField2(
decoration: InputDecoration(
isDense: true,
contentPadding: EdgeInsets.zero,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(15),
),
),
isExpanded: true,
hint: const Text(
'Select Your Country',
style: TextStyle(fontSize: 14),
),
icon: const Icon(
Icons.arrow_drop_down,
color: Colors.black45,
),
iconSize: 30,
buttonHeight: 60,
buttonPadding: const EdgeInsets.only(left: 20, right: 10),
dropdownDecoration: BoxDecoration(
borderRadius: BorderRadius.circular(15),
),
items: countryItems
.map((item) => DropdownMenuItem<String>(
value: item,
child: Text(
item,
style: const TextStyle(
fontSize: 14,
),
),
))
.toList(),
validator: (valueCountry) {
if (valueCountry == null) {
return 'Please select country.';
}
return null;
},
value: selectedCountry,
onChanged: (String? valueCountry) {
selectedCountry = valueCountry;
setState(() {
valueCountry;
});
},
),
),
),
// ),
],
),
SizedBox(
height: 20,
),
Row(
children: [
Container(
child: Text(
"Language: ",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 22,
color: Colors.black.withOpacity(0.3),
),
),
),
SizedBox(
width: 80,
),
Container(
width: 300,
child: IgnorePointer(
ignoring: isIgnored,
child: DropdownButtonFormField2(
decoration: InputDecoration(
isDense: true,
contentPadding: EdgeInsets.zero,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(15),
),
),
isExpanded: true,
hint: const Text(
'Select Your Language',
style: TextStyle(fontSize: 14),
),
icon: const Icon(
Icons.arrow_drop_down,
color: Colors.black45,
),
iconSize: 30,
buttonHeight: 60,
buttonPadding: const EdgeInsets.only(left: 20, right: 10),
dropdownDecoration: BoxDecoration(
borderRadius: BorderRadius.circular(15),
),
items: languageItems
.map((item) => DropdownMenuItem<String>(
value: item,
child: Text(
item,
style: const TextStyle(
fontSize: 14,
),
),
))
.toList(),
value: selectedLanguage,
validator: (valueLanguage) {
if (valueLanguage == null) {
return 'Please select language.';
}
return null;
},
onChanged: (String? valueLanguage) {
selectedLanguage = valueLanguage;
setState(() {
valueLanguage;
});
},
),
),
),
// ),
],
),
Row()
],
),
SizedBox(
width: 120,
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Container(
child: Row(
children: [
Text(
"Receive notifications by: ",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 22,
color: Colors.black.withOpacity(0.3),
),
),
],
),
),
],
),
SizedBox(
height: 10,
),
Row(
children: [
Container(
width: 300,
child: CheckboxListTile(
enabled: emailIsEnabled,
title: Text("E-mail"),
value: emailIsChecked,
onChanged: (bool? newEmailValue) {
setState(() {
emailIsChecked = newEmailValue;
});
},
activeColor: Colors.green,
),
),
],
),
Row(
children: [
Container(
width: 300,
child: CheckboxListTile(
enabled: smsIsEnabled,
title: Text("SMS"),
value: smsisChecked,
onChanged: (bool? newSmsValue) {
setState(() {
smsisChecked = newSmsValue;
});
},
activeColor: Colors.green,
),
),
],
),
SizedBox(
height: 100,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Visibility(
visible: isVisible,
child: Row(
children: <Widget>[
ElevatedButton(
style: ButtonStyle(
backgroundColor:
MaterialStateProperty.all(Colors.red)),
onPressed: () {
setState(() {
cleanInputStates();
_formKey.currentState!.reset();
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ProfilePage()));
});
print("Cleaning states");
},
child: Text("Dismiss"),
),
SizedBox(
width: 100,
),
ElevatedButton(
style: ButtonStyle(
backgroundColor:
MaterialStateProperty.all(Colors.green)),
onPressed: () {
if (_formKey.currentState!.validate()) {
final userInfo = {
"_id": globals.signedInUser!.userId,
"firstName": firstnameTextController.text,
"lastName": lastnameTextController.text,
"email": emailTextController.text,
"phoneNumber": phoneNumberTextController.text,
"country": selectedCountry.toString(),
"language": selectedLanguage.toString(),
"notifications": [
{"type": "Email", "status": emailIsChecked},
{"type": "SMS", "status": smsisChecked}
]
};
globals.socketController.updateUser(userInfo);
Fluttertoast.showToast(
msg: "Applying changes.", // message
toastLength: Toast.LENGTH_LONG, // length
gravity: ToastGravity.BOTTOM_RIGHT, // location
timeInSecForIosWeb: 2,
webBgColor: "#4caf50",
);
}
print("DATA IS BEING SAVED");
setState(() {
if (_formKey.currentState!.validate()) {
globals.signedInUser!.email =
emailTextController.text;
globals.signedInUser!.phoneNumber =
phoneNumberTextController.text;
globals.signedInUser!.firstName =
firstnameTextController.text;
globals.signedInUser!.lastName =
lastnameTextController.text;
globals.signedInUser!.country =
selectedCountry as String;
globals.signedInUser!.language =
selectedLanguage as String;
cleanInputStates();
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ProfilePage()));
} else {
print("ingresando else");
}
});
},
child: Text("Save"),
),
],
),
)
],
)
],
),
],
),
),
),
],
), //Column ends here
),
),
],
),
),
);
}
}
Update: After some testings and workarounds, I found that the second issue was due to not assigning a new value prior to returning to the initState. To do that, I added the following code segment into the setState() of the submit button, which is the fetch of the notification parameters within the initState() but assigning the new checkbox values into the array. Additionally, I removed the cleanInputStates(); on the initState as #Paulo mentioned and everything else kept the same.
globals.signedInUser!.notifications.forEach(
(element) {
if ((element['type']) == 'Email') {
element['status'] = emailIsChecked;
}
if ((element['type']) == 'SMS') {
element['status'] = smsisChecked;
}
},
);
I have this error:
The following FileSystemException was thrown resolving an image codec:
Cannot open file, path = '/Users/todo/Library/Developer/CoreSimulator/Devices/82205CEC-3D83-4A29-BF17-01C5B0515F71/data/Containers/Data/Application/035B9913-BEC5-46BA-84A5-8C1FE3C4E671/tmp/image_picker_B8D488A3-2790-4D53-A5D8-52E57E2C4108-76094-000003172DF085D2.jpg' (OS Error: No such file or directory, errno = 2)
When the exception was thrown, this was the stack
only when use iphone simulator while android emulator no problem
import 'dart:convert';
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../app/utility.dart';
import '../db/aql_db.dart';
import '../globals.dart';
import '../menu_page.dart';
import '../model/aql_model.dart';
import '../widget/input_text.dart';
import 'dart:io';
import 'package:http/http.dart' as http;
var _current = resultsFld[0];
class AqlPg extends StatefulWidget {
const AqlPg({Key? key}) : super(key: key);
#override
State<AqlPg> createState() => _AqlPgState();
}
class _AqlPgState extends State<AqlPg> {
final List<TextEditingController> _criticalController = [];
final List<TextEditingController> _majorController = [];
final List<TextEditingController> _minorController = [];
final List<TextEditingController> _imgCommintControllers = [];
final _irController = TextEditingController();
bool clickedCentreFAB =
false; //boolean used to handle container animation which expands from the FAB
int selectedIndex =
0; //to handle which item is currently selected in the bottom app bar
//call this method on click of each bottom app bar item to update the screen
void updateTabSelection(int index, String buttonText) {
setState(() {
selectedIndex = index;
});
}
#override
Widget build(BuildContext context) {
//
_irController.text = aqltbl.ir ?? '';
String _current = aqltbl.result ?? resultsFld[0];
//
return Scaffold(
body: SingleChildScrollView(
scrollDirection: Axis.vertical,
child: Column(
children: [
//---- stack for FloatingActionButton
Stack(
children: <Widget>[
//this is the code for the widget container that comes from behind the floating action button (FAB)
Align(
alignment: FractionalOffset.bottomCenter,
child: AnimatedContainer(
child: const Text(
'Hello',
style: TextStyle(fontSize: 18, color: whiteColor),
),
duration: const Duration(milliseconds: 250),
//if clickedCentreFAB == true, the first parameter is used. If it's false, the second.
height: clickedCentreFAB
? MediaQuery.of(context).size.height
: 10.0,
width: clickedCentreFAB
? MediaQuery.of(context).size.height
: 10.0,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(
clickedCentreFAB ? 0.0 : 300.0),
color: Colors.blue),
),
),
],
),
// --- Top Page Title
const SizedBox(
height: 50,
),
const Center(
child: Text(
'Aql page',
style: TextStyle(
fontSize: 30,
fontWeight: FontWeight.bold,
color: medBlueColor),
),
),
Text(
'Shipment no:$shipmentId',
style: const TextStyle(color: medBlueColor),
),
//--- input container
SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
children: [
Container(
height: 270,
width: 300,
margin: const EdgeInsets.only(top: 5),
child: ListView.builder(
itemCount: (aqltbl.aql ?? []).length,
scrollDirection: Axis.horizontal,
itemBuilder: (context, index) {
//here
var _aqlList = aqltbl.aql![index];
//
if (aqltbl.aql!.length > _criticalController.length) {
_criticalController.add(TextEditingController());
_majorController.add(TextEditingController());
_minorController.add(TextEditingController());
}
//
_criticalController[index].text =
_aqlList.critical ?? '';
_majorController[index].text = _aqlList.major ?? '';
_minorController[index].text = _aqlList.minor ?? '';
//
return Column(
children: [
Container(
height: 260,
width: 200,
margin: const EdgeInsets.only(left: 10),
padding: const EdgeInsets.all(10),
// ignore: prefer_const_constructors
decoration: BoxDecoration(
color: lightBlue,
borderRadius: BorderRadius.circular(10),
),
child: Column(
children: [
Text(
(_aqlList.name ?? '').toString(),
style: const TextStyle(
color: medBlueColor,
fontSize: 13,
),
),
// ignore: prefer_const_constructors
MyInputField(
title: 'critical',
hint: 'write critical ',
borderColor: borderColor,
textColor: textColor,
hintColor: hintColor,
controller: _criticalController[index],
onSubmit: (value) {
setState(() {
aqltbl.aql![index].critical = value;
_save();
});
},
),
MyInputField(
title: 'majority',
hint: 'write majority ',
borderColor: borderColor,
textColor: textColor,
hintColor: hintColor,
controller: _majorController[index],
onSubmit: (value) {
setState(() {
aqltbl.aql![index].major = value;
_save();
});
},
),
MyInputField(
title: 'minority',
hint: 'write minority ',
borderColor: borderColor,
textColor: textColor,
hintColor: hintColor,
controller: _minorController[index],
onSubmit: (value) {
setState(() {
aqltbl.aql![index].minor = value;
_save();
});
},
),
],
),
),
],
);
}),
),
Container(
height: 270,
width: 300,
margin: const EdgeInsets.only(right: 10, left: 20),
padding: const EdgeInsets.only(
left: 10, bottom: 3, right: 10, top: 5),
decoration: const BoxDecoration(
color: lightBlue,
),
child: Column(
children: [
const Text(
'Summery results',
style: TextStyle(color: medBlueColor),
),
Container(
margin: const EdgeInsets.only(top: 10, bottom: 5),
alignment: Alignment.centerLeft,
child: const Text(
'Results',
style: TextStyle(color: medBlueColor),
),
),
Container(
padding: const EdgeInsets.only(right: 5, left: 5),
decoration: BoxDecoration(
color: whiteColor,
borderRadius: BorderRadius.circular(10),
border: Border.all(
color: borderColor,
)),
child: DropdownButtonHideUnderline(
child: DropdownButton<String>(
focusColor: whiteColor,
value: aqltbl.result,
hint: const Text('select result'),
isExpanded: true,
iconSize: 36,
icon: const Icon(Icons.arrow_drop_down),
items: resultsFld.map((res) {
return DropdownMenuItem<String>(
value: res,
child: Text(
res,
style: const TextStyle(
fontFamily: 'tajawal',
fontSize: 15,
color: medBlueColor),
),
);
}).toList(),
onChanged: (val) {
setState(() {
aqltbl.result = val;
});
_save();
},
),
),
),
// aqltbl.result = selRes;
MyInputField(
width: 300,
title: 'information remarks (ir)',
hint: '',
maxLines: 3,
borderColor: borderColor,
textColor: textColor,
hintColor: hintColor,
controller: _irController,
onSubmit: (value) {
aqltbl.ir = value;
_save();
},
),
],
),
),
],
),
),
//Images Container
Container(
height: 400,
padding: const EdgeInsets.all(0),
margin: const EdgeInsets.only(bottom: 10, left: 10),
decoration: const BoxDecoration(color: lightGrey),
child: (aqltbl.images ?? []).isEmpty
? Column(
children: [
Image.asset(
'images/empty-photo.jpg',
height: 300,
),
Container(
margin: const EdgeInsets.only(top: 10),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: const [
Text('Click'),
Text(
'Camera button',
style: TextStyle(fontWeight: FontWeight.bold),
),
Text(' to add new photo'),
],
)),
],
)
: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: (aqltbl.images ?? []).length,
itemBuilder: (context, imgIndex) {
String? _image =
(aqltbl.images ?? [])[imgIndex].name.toString();
inspect('aql image file');
File(_image).exists() == true
? inspect('image exist')
: inspect('not exist: ' + _image);
inspect('_image: ' + _image);
if (aqltbl.images!.length >
_imgCommintControllers.length) {
_imgCommintControllers.add(TextEditingController());
}
_imgCommintControllers[imgIndex].text =
aqltbl.images![imgIndex].imgComment!;
inspect(_imgCommintControllers.length);
return Container(
margin: const EdgeInsets.only(left: 5),
height: 300,
child: Column(
children: [
Stack(
children: [
Image.file(
File(_image),
height: 300,
),
Container(
decoration: const BoxDecoration(
color: medBlueColor,
),
child: IconButton(
onPressed: () {
inspect('clear');
String imgName =
aqltbl.images![imgIndex].name ??
'';
aqltbl.images!.removeAt(imgIndex);
// aqltbl.images!.removeWhere(
// (item) => item.name == imgName);
_imgCommintControllers
.removeAt(imgIndex);
setState(() {});
},
color: whiteColor,
icon: const Icon(Icons.clear)),
)
],
),
MyInputField(
title: 'Write remarks about image',
hint: '',
controller: _imgCommintControllers[imgIndex],
onSubmit: (value) {
aqltbl.images![imgIndex].imgComment = value;
aqltbl.images![imgIndex].name = _image;
_save();
},
),
],
));
}),
),
],
),
),
// --- FloatingActionButton
floatingActionButtonLocation: FloatingActionButtonLocation
.centerDocked, //specify the location of the FAB
floatingActionButton: FloatingActionButton(
backgroundColor: medBlueColor,
onPressed: () {
inspect(aqltbl);
setState(() {
clickedCentreFAB =
!clickedCentreFAB; //to update the animated container
});
},
tooltip: "Centre FAB",
child: Container(
margin: const EdgeInsets.all(15.0),
child: const Icon(Icons.send),
),
elevation: 4.0,
),
// --- bottom action bar
bottomNavigationBar: BottomAppBar(
child: Container(
margin: const EdgeInsets.only(left: 12.0, right: 12.0),
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
//to leave space in between the bottom app bar items and below the FAB
IconButton(
//update the bottom app bar view each time an item is clicked
onPressed: () {
// updateTabSelection(0, "Home");
Get.to(const MainMenu());
},
iconSize: 27.0,
icon: Image.asset(
'images/logo.png',
color: medBlueColor,
),
),
const SizedBox(
width: 50.0,
),
IconButton(
onPressed: () async {
// updateTabSelection(2, "Incoming");
await _takeImage('gallery');
},
iconSize: 27.0,
icon: const Icon(
Icons.image_outlined,
color: medBlueColor,
),
),
IconButton(
onPressed: () async {
// updateTabSelection(1, "Outgoing");
await _takeImage('camera');
},
iconSize: 27.0,
icon: const Icon(
Icons.camera_alt,
color: medBlueColor,
),
),
],
),
),
//to add a space between the FAB and BottomAppBar
shape: const CircularNotchedRectangle(),
//color of the BottomAppBar
color: Colors.white,
),
);
}
_save() {
inspect('submit');
saveAql(shipmentId, aqltbl);
box.write('aql'+shipmentId.toString(), aqltbl);
}
_takeImage(method) async {
String _imgPath = await imageFromDevice(method);
if (_imgPath != empty) {
ImagesModel imgMdl = ImagesModel();
imgMdl.name = _imgPath;
imgMdl.imgComment = '';
if (aqltbl.images != null) {
// _saveLocaly(close: 0);
setState(() {
aqltbl.images!.add(imgMdl);
_save();
});
}
}
}
Future _sendAqlToServer() async {
try {
var response = await http.post(urlSendProductPhoto, body: {
'aql': json.encode(aqltbl).toString(),
'id': shipmentId.toString(),
});
if (response.statusCode == 200) {
Get.snackbar('Success', 'Image successfully uploaded');
return response.body;
} else {
Get.snackbar('Fail', 'Image not uploaded');
inspect('Request failed with status: ${response.statusCode}.');
return 'empty';
}
} catch (socketException) {
Get.snackbar('warning', 'Image not uploaded');
return 'empty';
}
}
}
Try following the path that it is saying it cannot find in your computer, I had a similar issue, I tried opening an Iphone 12 instead of an Iphone 13 and it worked out the issue, my problem was I inadvertently deleted a few files I shouldn't have.
On my UI screen, I have 2 textfields in a column. If textFormFieldEntr is empty, hide textFormFiel. If there is a value in the textFormFieldEntr, let the other textfield be visible. After I set the bool active variable to false in the Controller class, I checked the value in the textFormFieldEntr in the showText class. I'm wrong using obx on the UI screen. The textfields are listed in the _formTextField method. Can you answer by explaining the correct obx usage on the code I shared?
class WordController extends GetxController {
TextEditingController controllerInput1 = TextEditingController();
TextEditingController controllerInput2 = TextEditingController();
bool active = false.obs();
final translator = GoogleTranslator();
RxList data = [].obs;
#override
void onInit() {
getir();
super.onInit();
}
void showText() {
if (!controllerInput1.text.isEmpty) {
active = true;
}
}
ekle(Word word) async {
var val = await WordRepo().add(word);
showDilog("Kayıt Başarılı");
update();
return val;
}
updateWord(Word word) async {
var val = await WordRepo().update(word);
showDilog("Kayıt Başarılı");
return val;
}
deleteWord(int? id) async {
var val = await WordRepo().deleteById(id!);
return val;
}
getir() async {
//here read all data from database
data.value = await WordRepo().getAll();
print(data);
return data;
}
translateLanguage(String newValue) async {
if (newValue == null || newValue.length == 0) {
return;
}
List list = ["I", "i"];
if (newValue.length == 1 && !list.contains(newValue)) {
return;
}
var translate = await translator.translate(newValue, from: 'en', to: 'tr');
controllerInput2.text = translate.toString();
//addNote();
return translate;
}
showDilog(String message) {
Get.defaultDialog(title: "Bilgi", middleText: message);
}
addNote() async {
var word =
Word(wordEn: controllerInput1.text, wordTr: controllerInput2.text);
await ekle(word);
getir();
clear();
}
clear() {
controllerInput2.clear();
controllerInput1.clear();
}
updateNote() async {
var word =
Word(wordEn: controllerInput1.text, wordTr: controllerInput2.text);
await updateWord(word);
await getir();
update();
}
}
UI:
class MainPage extends StatelessWidget {
bool _active=false.obs();
String _firstLanguage = "English";
String _secondLanguage = "Turkish";
WordController controller = Get.put(WordController());
final _formKey = GlobalKey<FormState>();
#override
Widget build(BuildContext context) {
controller.getir();
return Scaffold(
drawer: _drawer,
backgroundColor: Colors.blueAccent,
appBar: _appbar,
body: _bodyScaffold,
floatingActionButton: _floattingActionButton,
);
}
SingleChildScrollView get _bodyScaffold {
return SingleChildScrollView(
child: Column(
children: [
chooseLanguage,
translateTextView,
],
),
);
}
AppBar get _appbar {
return AppBar(
backgroundColor: Colors.blueAccent,
centerTitle: true,
title: Text("TRANSLATE"),
elevation: 0.0,
);
}
get chooseLanguage => Container(
height: 55.0,
decoration: buildBoxDecoration,
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
firstChooseLanguage,
changeLanguageButton,
secondChooseLanguage,
],
),
);
get buildBoxDecoration {
return BoxDecoration(
color: Colors.white,
border: Border(
bottom: BorderSide(
width: 3.5,
color: Colors.grey,
),
),
);
}
refreshList() {
controller.getir();
}
get changeLanguageButton {
return Material(
color: Colors.white,
child: IconButton(
icon: Icon(
Icons.wifi_protected_setup_rounded,
color: Colors.indigo,
size: 30.0,
),
onPressed: () {},
),
);
}
get secondChooseLanguage {
return Expanded(
child: Material(
color: Colors.white,
child: InkWell(
onTap: () {},
child: Center(
child: Text(
this._secondLanguage,
style: TextStyle(
color: Colors.blue[600],
fontSize: 22.0,
),
),
),
),
),
);
}
get firstChooseLanguage {
return Expanded(
child: Material(
color: Colors.white,
child: InkWell(
onTap: () {},
child: Center(
child: Text(
this._firstLanguage,
style: TextStyle(
color: Colors.blue[600],
fontSize: 22.0,
),
),
),
),
),
);
}
get translateTextView => Column(
children: [
Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(8.0)),
),
margin: EdgeInsets.only(left: 2.0, right: 2.0, top: 2.0),
child: _formTextField,
),
Container(
height: Get.height/1.6,
child: Obx(() {
return ListView.builder(
itemCount: controller.data.length,
itemBuilder: (context, index) {
return Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(5.0)),
),
margin: EdgeInsets.only(left: 2.0, right: 2.0, top: 0.8),
child: Container(
color: Colors.white30,
height: 70.0,
padding:
EdgeInsets.only(left: 8.0, top: 8.0, bottom: 8.0),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
firstText(controller.data, index),
secondText(controller.data, index),
],
),
historyIconbutton,
],
),
),
);
},
);
}),
)
],
);
get _formTextField {
return Form(
key: _formKey,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
color: Colors.white30,
height: 120.0,
padding: EdgeInsets.only(left: 16.0, top: 8.0, bottom: 8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
textFormFieldEntr,
favoriIconButton,
],
),
),
textFormField //burası kapandı
],
),
);
}
get textFormFieldEntr {
return Flexible(
child: Container(
child: TextFormField(
onTap: () {
showMaterialBanner();
},
// onChanged: (text) {
// controller.translateLanguage(text);
// },
controller: controller.controllerInput1,
maxLines: 6,
validator: (controllerInput1) {
if (controllerInput1!.isEmpty) {
return "lütfen bir değer giriniz";
} else if (controllerInput1.length > 22) {
return "en fazla 22 karakter girebilirsiniz";
}
return null;
},
decoration: InputDecoration(
hintText: "Enter",
contentPadding: const EdgeInsets.symmetric(vertical: 5.0),
),
),
),
);
}
void showMaterialBanner() {
ScaffoldMessenger.of(Get.context!).showMaterialBanner(MaterialBanner(
backgroundColor: Colors.red,
content: Padding(
padding: const EdgeInsets.only(top: 30.0),
child: Column(
children: [
TextFormField(
controller: controller.controllerInput1,
maxLines: 6,
onChanged: (text) {
controller.translateLanguage(text);
controller.showText();
},
validator: (controllerInput2) {
if (controllerInput2!.length > 22) {
return "en fazla 22 karakter girebilirsiniz";
}
return null;
},
decoration: InputDecoration(
suffixIcon: IconButton(onPressed: () {
FocusScope.of(Get.context!).unfocus();
closeBanner();
}, icon: Icon(Icons.clear),),
contentPadding: const EdgeInsets.symmetric(vertical: 5.0),
),
),
SizedBox(height: 80.0),
TextFormField(
controller: controller.controllerInput2,
maxLines: 6,
validator: (controllerInput2) {
if (controllerInput2!.length > 22) {
return "en fazla 22 karakter girebilirsiniz";
}
return null;
},
decoration: InputDecoration(
contentPadding: const EdgeInsets.symmetric(vertical: 5.0),
),
),
],
),
),
actions: [
IconButton(
onPressed: () {
closeBanner();
},
icon: Icon(
Icons.arrow_forward_outlined,
color: Colors.indigo,
size: 36,
),
),
]));
}
void closeBanner() {
ScaffoldMessenger.of(Get.context!).hideCurrentMaterialBanner();
}
// } controller.controllerInput1.text==""?_active=false: _active=true;
get textFormField {
return Visibility(
visible: controller.active,
child: Container(
color: Colors.white30,
height: 120.0,
padding: EdgeInsets.only(left: 16.0, right: 42.0, top: 8.0, bottom: 8.0),
child: Container(
child: TextFormField(
controller: controller.controllerInput2,
maxLines: 6,
validator: (controllerInput2) {
if (controllerInput2!.length > 22) {
return "en fazla 22 karakter girebilirsiniz";
}
return null;
},
decoration: InputDecoration(
contentPadding: const EdgeInsets.symmetric(vertical: 5.0),
),
),
),
),
);
}
FutureBuilder<dynamic> get historyWordList {
return FutureBuilder(
future: controller.getir(),
builder: (context, AsyncSnapshot snapShot) {
if (snapShot.hasData) {
var wordList = snapShot.data;
return ListView.builder(
itemCount: wordList.length,
itemBuilder: (context, index) {
return Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(5.0)),
),
margin: EdgeInsets.only(left: 8.0, right: 8.0, top: 0.8),
child: Container(
color: Colors.white30,
height: 70.0,
padding: EdgeInsets.only(left: 8.0, top: 8.0, bottom: 8.0),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
firstText(wordList, index),
secondText(wordList, index),
],
),
historyIconbutton,
],
),
),
);
},
);
} else {
return Center();
}
},
);
}
IconButton get historyIconbutton {
return IconButton(
onPressed: () {},
icon: Icon(Icons.history),
iconSize: 30.0,
);
}
Text firstText(wordList, int index) {
return Text(
"İngilizce: ${wordList[index].wordEn ?? ""}",
style: TextStyle(
fontWeight: FontWeight.w600,
),
maxLines: 1,
overflow: TextOverflow.ellipsis,
);
}
Text secondText(wordList, int index) {
return Text(
"Türkçe: ${wordList[index].wordTr ?? ""}",
style: TextStyle(
fontWeight: FontWeight.w400,
),
maxLines: 1,
overflow: TextOverflow.ellipsis,
);
}
get favoriIconButton {
return IconButton(
alignment: Alignment.topRight,
onPressed: () async {
bool validatorKontrol = _formKey.currentState!.validate();
if (validatorKontrol) {
String val1 = controller.controllerInput1.text;
String val2 = controller.controllerInput2.text;
print("$val1 $val2");
await controller.addNote();
await refreshList();
}
await Obx(() => textFormField(
controller: controller.controllerInput2,
));
await Obx(() => textFormField(
controller: controller.controllerInput1,
));
},
icon: Icon(
Icons.forward,
color: Colors.blueGrey,
size: 36.0,
),
);
}
FloatingActionButton get _floattingActionButton {
return FloatingActionButton(
onPressed: () {
Get.to(WordListPage());
},
child: Icon(
Icons.app_registration,
size: 30,
),
);
}
Drawer get _drawer {
return Drawer(
child: ListView(
// Important: Remove any padding from the ListView.
padding: EdgeInsets.zero,
children: <Widget>[
userAccountsDrawerHeader,
drawerFavorilerim,
drawersettings,
drawerContacts,
],
),
);
}
ListTile get drawerContacts {
return ListTile(
leading: Icon(Icons.contacts),
title: Text("Contact Us"),
onTap: () {
Get.back();
},
);
}
ListTile get drawersettings {
return ListTile(
leading: Icon(Icons.settings),
title: Text("Settings"),
onTap: () {
Get.back();
},
);
}
ListTile get drawerFavorilerim {
return ListTile(
leading: Icon(
Icons.star,
color: Colors.yellow,
),
title: Text("Favorilerim"),
onTap: () {
Get.to(FavoriListPage());
},
);
}
UserAccountsDrawerHeader get userAccountsDrawerHeader {
return UserAccountsDrawerHeader(
accountName: Text("UserName"),
accountEmail: Text("E-mail"),
currentAccountPicture: CircleAvatar(
backgroundColor: Colors.grey,
child: Text(
"",
style: TextStyle(fontSize: 40.0),
),
),
);
}
}
You can simple do it like this
class ControllerSample extends GetxController{
final active = false.obs
functionPass(){
active(!active.value);
}
}
on page
final sampleController = Get.put(ControllerSample());
Obx(
()=> Form(
key: yourkeyState,
child: Column(
children: [
TextFormField(
//some other needed
//put the function on onChanged
onChanged:(value){
if(value.isEmpty){
sampleController.functionPass();
}else{
sampleController.functionPass();
}
}
),
Visibility(
visible: sampleController.active.value,
child: TextFormField(
//some other info
)
),
]
)
)
)
Im using table_calendar package in my project, but ive faced two problems so far :
The calendar doesnt load todays events below the calendar, i would love to hear some ideas how to get this one done.
Even if i put (code below) in tables parameters, it doesnt allow to switch calendar modes.
code for swiching calendar modes for 2nd bullet point of my problems:
availableCalendarFormats: const {
CalendarFormat.month: '',
CalendarFormat.week: '',
},
Just in case, here is the whole code for page which has problems :
class Lecture_graph extends StatefulWidget {
Lecture_graph({Key key}) : super(key: key);
#override
State<Lecture_graph> createState() => myLectureGraph();
}
class myLectureGraph extends State<Lecture_graph>
with TickerProviderStateMixin {
List _selectedEvents;
DateTime _selectedDate = DateTime.now();
Map<DateTime, List<Lecture>> _events;
CalendarController _calendarController;
AnimationController _animationController;
List<Lecture> _lectures;
String coursecode = "";
bool isJoin, isBreaks = false;
bool isLoading = true;
final Map<DateTime, List> _holidays = {
// DateTime(2021, 1, 1): ['New Year\'s Day'],
// DateTime(2021, 2, 14): ['Valentine\'s Day'],
// DateTime(2021, 3, 8): ['Woman\'s Day'],
};
Future<Map<DateTime, List>> getLectures(DateTime _selectedDate) async {
print("getLectures started.");
setState(() {
isLoading = true;
});
Map<DateTime, List<Lecture>> mapFetch = {};
//get saved course
if (coursecode == "" || coursecode == null) {
coursecode = await _checkSavedCourse();
//debug
print('courscode recieved from sharedprefs');
}
//build request URL
var requestURL =
'https://lekcijas.va.lv/lekcijas_android/getMonthLectures.php?date=' +
DateFormat('yyyy-MM').format(_selectedDate) +
(isBreaks ? "&breaks" : "") +
(isJoin ? "&join" : "") +
"&program=" +
coursecode +
"&lang=" +
AppLocalizations.of(context).translate('request_language');
print("Lecture request url : $requestURL");
//wait for response
var response = await http.get(Uri.parse(requestURL));
var data = json.decode(response.body)["result"];
//clear array after each request
if (_lectures != null) _lectures.clear();
try {
//create lectures from json response
_lectures = List<Lecture>.from(data.map((x) => Lecture.fromJson(x)));
} on Exception catch (_) {
print("Error occured getting lectures");
}
_lectures.forEach((element) {
if (mapFetch[element.lecture_date] != null) {
mapFetch[element.lecture_date] += [element];
} else {
mapFetch[element.lecture_date] = [element];
}
});
setState(() {
isLoading = false;
});
print("getLectures finished.");
return mapFetch;
}
Future<void> _saveVales(String key, bool value) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
print("Sharedpref $key is set to $value now");
prefs.setBool(key, value);
}
Future<void> _checkSavedParameters() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
isBreaks = prefs.getBool('lectures_breaks') == null
? false
: prefs.getBool('lectures_breaks');
isJoin = prefs.getBool('lectures_join') == null
? false
: prefs.getBool('lectures_join');
}
Future<String> _checkSavedCourse() async {
//check saved parameters for lecture requests too
await _checkSavedParameters();
SharedPreferences prefs = await SharedPreferences.getInstance();
String _coursecode = prefs.getString('savedCourse');
if (_coursecode == "" || _coursecode == null) {
Navigator.pop(context);
Navigator.push(
context,
MaterialPageRoute(builder: (context) => CourseSelectionPage()),
);
return null;
} else {
return _coursecode;
}
}
void _onDaySelected(DateTime day, List events) {
print('CALLBACK: _onDaySelected');
setState(() {
_selectedEvents = events;
});
}
#override
void initState() {
super.initState();
//enable portrait only mode
SystemChrome.setPreferredOrientations([
DeviceOrientation.portraitUp,
DeviceOrientation.portraitDown,
]);
_selectedEvents = [];
_calendarController = CalendarController();
_animationController = AnimationController(
vsync: this,
duration: const Duration(milliseconds: 400),
);
_animationController.forward();
WidgetsBinding.instance.addPostFrameCallback((_) {
getLectures(_selectedDate).then((val) => setState(() {
_events = val;
}));
});
}
#override
void dispose() {
_calendarController.dispose();
//unlock orientation mode
SystemChrome.setPreferredOrientations([
DeviceOrientation.landscapeRight,
DeviceOrientation.landscapeLeft,
DeviceOrientation.portraitUp,
DeviceOrientation.portraitDown,
]);
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(coursecode +
" | " +
AppLocalizations.of(context).translate('lectures_title')),
actions: <Widget>[
IconButton(
icon: Icon(
Icons.settings,
color: Colors.white,
),
onPressed: () {
showDialog(
context: context,
builder: (context) {
return StatefulBuilder(
builder: (context, setState) {
return AlertDialog(
title: Text(
AppLocalizations.of(context).translate('settings')),
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
Row(
children: [
CupertinoSwitch(
value: isJoin,
onChanged: (bool value) {
_saveVales('lectures_join', value);
isJoin = value;
WidgetsBinding.instance
.addPostFrameCallback((_) {
getLectures(_selectedDate)
.then((val) => setState(() {
_events = val;
}));
});
},
),
Text(AppLocalizations.of(context)
.translate('join_lectures'))
],
),
SizedBox(height: 10),
Row(
children: [
CupertinoSwitch(
value: isBreaks,
onChanged: (bool value) {
_saveVales('lectures_breaks', value);
isBreaks = value;
WidgetsBinding.instance
.addPostFrameCallback((_) {
getLectures(_selectedDate)
.then((val) => setState(() {
_events = val;
}));
});
},
),
Text(AppLocalizations.of(context)
.translate('show_breaks'))
],
),
SizedBox(height: 10),
SizedBox(
width: double.infinity,
child: OutlinedButton(
onPressed: () {
//close popup
Navigator.pop(context);
//close page
Navigator.pop(context);
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
CourseSelectionPage()),
);
},
child: Text(
AppLocalizations.of(context)
.translate('select_course'),
style: TextStyle(color: Colors.lime),
)),
)
],
),
actions: <Widget>[
FlatButton(
onPressed: () => Navigator.pop(context),
child: Text(AppLocalizations.of(context)
.translate('close')),
),
],
);
},
);
},
);
},
)
],
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
isLoading
? Expanded(child: Center(child: CircularProgressIndicator()))
: _buildTableCalendarWithBuilders(),
const SizedBox(height: 2.0),
Expanded(child: _buildEventList()),
],
),
),
);
}
Widget _buildTableCalendarWithBuilders() {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Card(
color: Colors.white,
margin: const EdgeInsets.all(8.0),
clipBehavior: Clip.antiAlias,
child: TableCalendar(
locale:
AppLocalizations.of(context).translate('request_language') ==
'lv'
? "lv_LV"
: "en_US",
initialSelectedDay: _selectedDate,
calendarController: _calendarController,
events: _events,
holidays: _holidays,
initialCalendarFormat: CalendarFormat.month,
formatAnimation: FormatAnimation.scale,
startingDayOfWeek: StartingDayOfWeek.monday,
availableGestures: AvailableGestures.all,
availableCalendarFormats: const {
CalendarFormat.month: '',
CalendarFormat.week: '',
},
calendarStyle: CalendarStyle(
outsideDaysVisible: false,
weekendStyle: TextStyle().copyWith(color: Colors.blue[800]),
holidayStyle: TextStyle().copyWith(color: Colors.blue[800]),
),
daysOfWeekStyle: DaysOfWeekStyle(
weekendStyle: TextStyle().copyWith(color: Colors.blue[600]),
),
headerStyle: HeaderStyle(
centerHeaderTitle: true,
formatButtonVisible: false,
),
builders: CalendarBuilders(
selectedDayBuilder: (context, date, _) {
return FadeTransition(
opacity:
Tween(begin: 0.0, end: 1.0).animate(_animationController),
child: Container(
margin: const EdgeInsets.all(4.0),
padding: const EdgeInsets.only(top: 5.0, left: 6.0),
color: Colors.deepOrange[300],
width: 100,
height: 100,
child: Text(
'${date.day}',
style: TextStyle().copyWith(fontSize: 16.0),
),
),
);
},
todayDayBuilder: (context, date, _) {
return Container(
margin: const EdgeInsets.all(4.0),
padding: const EdgeInsets.only(top: 5.0, left: 6.0),
color: Colors.amber[400],
width: 100,
height: 100,
child: Text(
'${date.day}',
style: TextStyle().copyWith(fontSize: 16.0),
),
);
},
markersBuilder: (context, date, events, holidays) {
final children = <Widget>[];
if (events.isNotEmpty) {
children.add(
Positioned(
right: 1,
bottom: 1,
child: _buildEventsMarker(date, events),
),
);
}
if (holidays.isNotEmpty) {
children.add(
Positioned(
right: -2,
top: -2,
child: _buildHolidaysMarker(),
),
);
}
return children;
},
),
onDaySelected: (date, events, holidays) {
_onDaySelected(date, events);
_animationController.forward(from: 0.0);
},
onVisibleDaysChanged: _onVisibleDaysChanged,
),
),
],
);
}
void _onVisibleDaysChanged(
DateTime first, DateTime last, CalendarFormat format) {
_selectedDate = first;
WidgetsBinding.instance.addPostFrameCallback((_) {
getLectures(_selectedDate).then((val) => setState(() {
_events = val;
}));
});
print('CALLBACK: _onVisibleDaysChanged');
}
Widget _buildEventsMarker(DateTime date, List events) {
return AnimatedContainer(
duration: const Duration(milliseconds: 300),
decoration: BoxDecoration(
shape: BoxShape.circle,
color: _calendarController.isSelected(date)
? Colors.brown[500]
: _calendarController.isToday(date)
? Colors.brown[300]
: Colors.green[400],
),
width: 18.0,
height: 18.0,
child: Center(
child: Text(
'${events.length}',
style: TextStyle().copyWith(
color: Colors.white, fontSize: 12.0, fontWeight: FontWeight.w900),
),
),
);
}
Widget _buildHolidaysMarker() {
return Icon(
Icons.add_box,
size: 20.0,
color: Colors.blueGrey[800],
);
}
Widget _buildEventList() {
return ListView(
children: _selectedEvents.reversed
.map((lecture) => Container(
decoration: BoxDecoration(
border: Border.all(width: 0.1),
// borderRadius: BorderRadius.circular(2.0),
color: hexToColor(lecture.color),
),
margin:
const EdgeInsets.symmetric(horizontal: 6.0, vertical: 1.5),
child: ListTile(
title: Column(
children: [
Align(
alignment: Alignment.centerLeft,
child: Text(
lecture.start + " - " + lecture.end,
style: new TextStyle(
fontSize: 12.0,
color: Colors.black,
),
),
),
Align(
alignment: Alignment.centerLeft,
child: Text(lecture.lecture,
style: new TextStyle(
fontSize: 16.0,
color: Colors.black,
)),
),
],
),
onTap: () => displayDialog(lecture, context),
),
))
.toList(),
);
}
void displayDialog(Lecture selectedLecture, BuildContext ctx) {
//if selected lecture is a break
if (!selectedLecture.lecturer.isEmpty &&
!selectedLecture.classroom.isEmpty &&
!selectedLecture.programs.isEmpty) {
showDialog(
barrierDismissible: true,
context: ctx,
builder: (BuildContext context) => new AlertDialog(
title: new Text(AppLocalizations.of(context).translate('info_title')),
content: new Wrap(
runSpacing: 5,
children: [
Align(
alignment: Alignment.centerLeft,
child: Text(
AppLocalizations.of(context).translate('info_time') +
selectedLecture.start +
" - " +
selectedLecture.end),
),
Align(
alignment: Alignment.centerLeft,
child: Text(
AppLocalizations.of(context).translate('info_lecturer') +
selectedLecture.lecturer),
),
Align(
alignment: Alignment.centerLeft,
child: Text(
AppLocalizations.of(context).translate('info_classroom') +
selectedLecture.classroom),
),
Align(
alignment: Alignment.centerLeft,
child: Text(
AppLocalizations.of(context).translate('info_lecture') +
selectedLecture.lecture),
),
Align(
alignment: Alignment.centerLeft,
child: Text(
AppLocalizations.of(context).translate('info_date') +
DateFormat('yyyy-MM-dd')
.format(selectedLecture.lecture_date)
.toString()),
),
Align(
alignment: Alignment.centerLeft,
child: Text(
AppLocalizations.of(context).translate('info_programs') +
selectedLecture.programs),
),
],
),
actions: [
new TextButton(
child: Text(AppLocalizations.of(context).translate('close')),
onPressed: () => Navigator.pop(context, true),
),
],
),
);
}
}
}
In case someone wants to see JSON request results, here is the link for that.
So i got this fixed, adding this to TableCalendar() parameters:
(i called selectedEvents variable update once calendar finished building (because im showing CircularProgressIndicator instead of it while i recieve data from http request) )
onCalendarCreated: (d1, d2, cf){WidgetsBinding.instance
.addPostFrameCallback((_) => _onDaySelected(_selectedDate, _events[_selectedDate]));},
changed _onDaySelected method to:
(here i change selectedday variable to day recieved from calendar click and change state of selectedEvents, replacing them with total_events_map[key_which_is_selectedDay])
void _onDaySelected(DateTime day, List events) {
print('CALLBACK: _onDaySelected');
//dates are used with nulled time
_selectedDate = DateTime(day.year, day.month, day.day, 0, 0, 0);
setState(() {
_selectedEvents = _events[_selectedDate];
});
}
and changed _buildEventList() to this :
(so if selectedEvents are empty, it tells user so, if not, generates a list of items from selectedEvents)
Widget _buildEventList() {
if(_selectedEvents == null)
return ListView(
children: [
Card(
clipBehavior: Clip.antiAlias,
margin: const EdgeInsets.all(8.0),
child: ListTile(
title: Column(
children: [
Align(
alignment: Alignment.centerLeft,
child: Text(tr('nothing_planned'),
style: new TextStyle(
fontSize: 16.0,
color: Colors.black,
)),
),
],
),
),
),
],
);
else return ListView(
children: _selectedEvents.reversed
.map((lecture) => Container(
decoration: BoxDecoration(
border: Border.all(width: 0.1),
// borderRadius: BorderRadius.circular(2.0),
color: hexToColor(lecture.color),
),
margin:
const EdgeInsets.symmetric(horizontal: 6.0, vertical: 1.5),
child: ListTile(
title: Column(
children: [
Align(
alignment: Alignment.centerLeft,
child: Text(
lecture.start + " - " + lecture.end,
style: new TextStyle(
fontSize: 12.0,
color: Colors.black,
),
),
),
Align(
alignment: Alignment.centerLeft,
child: Text(lecture.lecture,
style: new TextStyle(
fontSize: 16.0,
color: Colors.black,
)),
),
],
),
onTap: () => displayDialog(lecture, context),
),
))
.toList(),
);
}
This is the code for the Createpoll module of my Polling app. I want to generate just 4 dynamic text fields, but the below code generates unlimited text fields. I'm not able to figure out which part to edit to fit my needs.
Create Poll Screenshot
I'm also unable to make changes to the hint text in the text field, It keeps repeating "Option 1", I want it to go like Option1, Option2.....so on.
import 'package:flutter/material.dart';
import 'package:justpoll/Constants.dart';
import 'package:justpoll/screens/create_poll/create_poll2.dart';
import 'package:justpoll/widgets/custom_input.dart';
class CreatePoll extends StatefulWidget {
#override
_CreatePollState createState() => _CreatePollState();
}
class _CreatePollState extends State<CreatePoll> {
final _formKey = GlobalKey<FormState>();
TextEditingController _nameController;
static List<String> friendsList = [null];
String emoji_id;
List<String> emoji = [
"❤️",
"🤩",
"✌️",
"😂",
"😡",
];
#override
void initState() {
super.initState();
_nameController = TextEditingController();
}
#override
void dispose() {
_nameController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
backgroundColor: MyColors.white,
appBar: AppBar(
title: Padding(
padding: const EdgeInsets.all(75.0),
child: Text('New Poll'),
),
leading: GestureDetector(
onTap: () {
Navigator.pop(context);
},
child: Icon(
Icons.close,
),
),
backgroundColor: Colors.black87,
),
body: ListView(
children: [
Form(
key: _formKey,
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// name textfield
Center(
child: Padding(
padding: const EdgeInsets.all(6.0),
child: Text("1/4"),
),
),
Padding(
padding: const EdgeInsets.only(right: 32.0),
child: CustomInput(
textEditingController: _nameController,
labletext: 'Question?*',
decoration: InputDecoration(hintText: 'Question*'),
validator: (v) {
if (v.trim().isEmpty) return 'Please enter something';
return null;
},
),
),
SizedBox(
height: 20,
),
// Text(
// 'Options',
// style: TextStyle(fontWeight: FontWeight.w700, fontSize: 16),
// ),
// Padding(
// padding: const EdgeInsets.only(right: 2.0),
// child: Row(
// children: [
// Expanded(
// flex: 2,
// child: Padding(
// padding: const EdgeInsets.only(right: 20),
// child: CustomInput(
// textEditingController: _nameController,
// labletext: 'Option 1*',
// decoration: InputDecoration(hintText: 'Option'),
// validator: (v) {
// if (v.trim().isEmpty)
// return 'Please enter something';
// return null;
// },
// ),
// ),
// ),
// Expanded(
// flex: 1,
// child: Padding(
// padding: const EdgeInsets.only(right: 30),
// child: Container(
// padding: EdgeInsets.only(left: 10, right: 16),
// decoration: BoxDecoration(
// border: Border.all(
// color: MyColors.black, width: 1.5),
// borderRadius: BorderRadius.circular(10)),
// child: DropdownButton(
// hint: Text('❤️'),
// value: emoji_id,
// icon: Icon(Icons.arrow_drop_down),
// iconSize: 36,
// isExpanded: true,
// underline: SizedBox(),
// style: TextType.regularDarkText,
// onChanged: (newValue) {
// setState(() {
// emoji_id = newValue;
// });
// },
// items: emoji.map((emoji_id) {
// return DropdownMenuItem(
// value: emoji_id,
// child: Text(emoji_id),
// );
// }).toList(),
// ),
// ),
// ),
// ),
// ],
// ),
// ),
..._getOptions(),
SizedBox(
height: 30,
),
Align(
alignment: Alignment.bottomRight,
child: MaterialButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => CreatePoll2(),
),
);
},
color: Colors.black,
textColor: Colors.white,
child: Icon(
Icons.arrow_forward,
size: 24,
),
padding: EdgeInsets.all(16),
shape: CircleBorder(),
),
),
],
),
),
),
],
),
),
);
}
/// get friends text-fields
List<Widget> _getOptions() {
List<Widget> friendsTextFields = [];
for (int i = 0; i < friendsList.length; i++) {
friendsTextFields.add(Padding(
padding: const EdgeInsets.symmetric(vertical: 16.0),
child: Row(
children: [
Expanded(child: FriendTextFields(i)),
SizedBox(
width: 5,
),
// we need add button at last friends row
_addRemoveButton(i == friendsList.length - 1, i),
],
),
));
}
return friendsTextFields;
}
/// add / remove button
Widget _addRemoveButton(bool add, int index) {
return InkWell(
onTap: () {
if (add) {
// add new text-fields at the top of all friends textfields
friendsList.insert(0, null);
} else
friendsList.removeAt(index);
setState(() {});
},
child: Container(
width: 26,
height: 26,
decoration: BoxDecoration(
color: (add) ? Colors.black : Colors.red,
borderRadius: BorderRadius.circular(20),
),
child: Icon(
(add) ? Icons.add : Icons.remove,
color: Colors.white,
),
),
);
}
}
class FriendTextFields extends StatefulWidget {
final int index;
FriendTextFields(this.index);
#override
_FriendTextFieldsState createState() => _FriendTextFieldsState();
}
class _FriendTextFieldsState extends State<FriendTextFields> {
TextEditingController _nameController;
#override
void initState() {
super.initState();
_nameController = TextEditingController();
}
#override
void dispose() {
_nameController.dispose();
super.dispose();
}
String emoji_id;
List<String> emoji = [
"❤️",
"🤩",
"✌️",
"😂",
"😡",
];
#override
Widget build(BuildContext context) {
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
_nameController.text = _CreatePollState.friendsList[widget.index] ?? '';
});
return Row(
children: [
Expanded(
flex: 2,
child: CustomInput(
textEditingController: _nameController,
labletext: 'Option 1*',
decoration: InputDecoration(hintText: 'Option'),
validator: (v) {
if (v.trim().isEmpty) return 'Please enter something';
return null;
},
),
),
Expanded(
flex: 1,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
padding: EdgeInsets.only(left: 10, right: 16),
decoration: BoxDecoration(
border: Border.all(color: MyColors.black, width: 1.5),
borderRadius: BorderRadius.circular(10)),
child: DropdownButton(
hint: Text('❤️'),
value: emoji_id,
icon: Icon(Icons.arrow_drop_down),
iconSize: 36,
isExpanded: true,
underline: SizedBox(),
style: TextType.regularDarkText,
onChanged: (newValue) {
setState(() {
emoji_id = newValue;
});
},
items: emoji.map((emoji_id) {
return DropdownMenuItem(
value: emoji_id,
child: Text(emoji_id),
);
}).toList(),
),
),
),
),
],
);
}
}
Firstly, If you want to limit it to just 4 dynamic fields then please replace this line
_addRemoveButton(i == friendsList.length - 1, i)
with this
_addRemoveButton(i < 3 ? i == friendsList.length - 1 : false, i),
This will make sure that the add button is not shown on the 4th field. Instead it will show the remove button for the 4th field.
Secondly, to have it show each field as Option 1, Option 2, Option 3 etc, replace the line
labletext: 'Option 1*',
with
labletext: 'Option ${widget.index + 1}',