How to limit the dynamic textfield to 4 in flutter? - flutter

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}',

Related

Fill width in single datacell in flutter

I'm trying to accomplished something like had been issued here : Flutter single `DataCell` color
I want to grey out the cell to let user know that was supposed to leave blank. Currently I manage to fill the height of datacell but the width.
my code snippet:
_data[i][newColumn] = Container(
width: double.infinity,
height: double.infinity,
color: Colors.grey,
child: Text(''));
Result: Last cell at the most right which fill up height space only:
full code :
import 'dart:convert';
import 'dart:ui';
import 'package:http/http.dart';
import 'package:flutter/material.dart';
class InspectionSheet extends StatefulWidget {
const InspectionSheet({Key? key}) : super(key: key);
#override
State<InspectionSheet> createState() => _InspectionSheetState();
}
class _InspectionSheetState extends State<InspectionSheet> {
GlobalKey<FormState> _formKey = new GlobalKey();
bool validate = false;
TextEditingController ctrlsampleSize = TextEditingController();
final List<Map<String, dynamic>> _data = [
{
//"checkitemID": "0",
"Ballooning No": "1",
"Datatype": "1",
"Specifications": ".325+-0.020",
"Tool": "CALIPER",
"LSL": "0.305",
"Target": "2",
"USL": "0.325",
"Tol-": "0.02",
"Tol+": "0.02",
"Image": "",
"WI": ""
},
{
//"checkitemID": "0",
"Ballooning No": "2",
"Datatype": "2",
"Specifications": ".325+-0.020",
"Tool": "CALIPER",
"LSL": "0.305",
"Target": "2",
"USL": "0.325",
"Tol-": "0.02",
"Tol+": "0.02",
"Image": "",
"WI": ""
},
];
late List<String> _columnNames;
//String _selectedValue = inputList.first;
String _selectedValue = 'PASS';
void startbutton() {
validateEmpty();
if (_formKey.currentState!.validate()) {
addDataCol();
}
}
void validateEmpty() {
//if (_formKey.currentState!.validate()) {
// // If the form is valid, display a snackbar. In the real world,
// // you'd often call a server or save the information in a database.
// ScaffoldMessenger.of(context).showSnackBar(
// const SnackBar(content: Text('Processing Data')),
// );
ctrlsampleSize.text.isEmpty ? validate = false : validate = true;
//}
}
void addDataCol() {
int colNo = int.parse(ctrlsampleSize.text);
if (colNo < 1) {
return;
}
setState(() {
for (var i = 1; i <= colNo; i++) {
_addColumn('Data $i');
}
});
}
void _addColumn(String newColumn) {
if (_columnNames.contains(newColumn)) {
return;
}
setState(() {
for (var i = 0; i <= _data.length - 1; i++) {
if (_data[i]['Datatype'] == '1') {
_data[i][newColumn] = TextFormField();
} else if (_data[i]['Datatype'] == '2') {
_data[i][newColumn] = DropdownButton<String>(
value: _selectedValue,
icon: const Icon(Icons.arrow_drop_down_circle_outlined),
elevation: 16,
underline: Container(
height: 2,
color: Colors.blue,
),
onChanged: (newValue) {
setState(() {
_selectedValue = newValue!;
});
},
items:
// inputList.map<DropdownMenuItem<String>>((String value) {
// return DropdownMenuItem<String>(
// value: value,
// child: Text(value),
// onTap: () {
// _selectedValue = value;
// },
// );
// }).toList(),
[
DropdownMenuItem(
value: 'PASS',
child: const Text('PASS'),
onTap: () {
_selectedValue = 'PASS';
},
),
DropdownMenuItem(
value: 'FAIL',
child: const Text('FAIL'),
onTap: () {
_selectedValue = 'FAIL';
},
),
DropdownMenuItem(
value: 'UAI',
child: const Text('UAI'),
onTap: () {
_selectedValue = 'UAI';
},
),
DropdownMenuItem(
value: 'NA',
child: const Text('NA'),
onTap: () {
_selectedValue = 'NA';
},
)
]);
} else if (_data[i]['Datatype'] == '3') {
if (newColumn == 'Data 1') {
_data[i][newColumn] = TextButton(
onPressed: () {
_displayTextInputDialog(context);
},
child: const Text('-'));
} else {
_data[i][newColumn] = Container(
width: double.infinity,
height: double.infinity,
color: Colors.grey,
child: Text(''));
}
} else {
_data[i][newColumn] = TextButton(
onPressed: () {
_displayTextInputDialog(context);
},
child: const Text('-'));
}
}
_columnNames.add(newColumn);
});
}
#override
void initState() {
dateInput.text = "";
_columnNames = _data[0].keys.toList();
//set the initial value of text field
super.initState();
//// Start listening to changes.
ctrlsampleSize.addListener(() {});
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: ListView(
children: [
Form(
child: Row(
children: [
Container(
width: MediaQuery.of(context).size.width,
height: 210,
child: Form(
key: _formKey,
child: ListView(
children: [
Row(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Container(
width: 200,
height: 200,
child: Column(
children: <Widget>[
TextFormField(
controller: ctrlsampleSize,
validator: ((value) {
if (value == null || value.isEmpty) {
return 'Please enter sample size';
}
return null;
}),
],
),
),
Padding(
padding: const EdgeInsets.fromLTRB(0, 5, 0, 0),
child: Container(
width: 400,
height: 200,
decoration: BoxDecoration(
border: Border.all(color: Colors.black),
image: DecorationImage(
image: AssetImage('images/Test1.jpg'),
fit: BoxFit.fill,
)),
),
),
],
),
],
),
),
Container(
child: Container(
child: Center(
child: Row(
// add Column
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Padding(
padding: const EdgeInsets.fromLTRB(15, 15, 860, 0),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: const [
Text(
"Total Parameter : 6",
textAlign: TextAlign.left,
style: TextStyle(
fontSize: 16, fontWeight: FontWeight.bold),
),
],
),
),
Padding(
padding: const EdgeInsets.fromLTRB(15, 15, 8, 0),
child: ElevatedButton(
onPressed: () => startbutton(),
child: const Text('Start'),
),
),
Padding(
padding: const EdgeInsets.fromLTRB(15, 15, 8, 0),
child: ElevatedButton(
onPressed: () {},
child: const Text('Reset'),
),
),
Padding(
padding: const EdgeInsets.fromLTRB(15, 15, 8, 0),
child: ElevatedButton(
onPressed: () {},
child: const Text('Save'),
),
),
],
),
),
)),
Padding(
padding: const EdgeInsets.all(8.0),
child:
//****uncomment if use Provider */
// Container(
// decoration: BoxDecoration(
// border: Border.all(color: Colors.black),
// ),
// child: ConstrainedBox(
// constraints: const BoxConstraints(
// maxHeight: 600,
// maxWidth: 813,
// ),
// child: Column(
// children: [
// Expanded(
// child: ChangeNotifierProvider<CheckItemProvider>(
// create: (context) => CheckItemProvider(),
// child: Consumer<CheckItemProvider>(
// builder: (context, provider, child) {
// provider.getData(context);
// return const Center(
// child: CircularProgressIndicator());
// // when we have the json loaded... let's put the data into a data table widget
// return
SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: SingleChildScrollView(
scrollDirection: Axis.vertical,
child: DataTable(
headingRowHeight: 30,
border: TableBorder.all(
color: Colors.grey,
),
headingRowColor: MaterialStateColor.resolveWith(
(states) => Colors.lightBlue),
headingTextStyle: const TextStyle(
color: Colors.white, fontWeight: FontWeight.w800),
columns: _columnNames.map((columnName) {
return DataColumn(
label: Text(
columnName,
// style: const TextStyle(
// fontSize: 18,
// fontWeight: FontWeight.w600,
// ),
),
);
}).toList(),
rows:
_data // Loops through dataColumnText, each iteration assigning the value to element
.map((row) {
return DataRow(
cells: row.values.map((cellValue) {
try {
return DataCell(
cellValue,
onTap: () {},
);
} catch (e) {
return DataCell(Text(cellValue));
}
;
}).toList());
}).toList(),
),
),
),
//},
// ),
// ),
// ),
// ],
// ),
// ),
// ),
),
],
),
);
}
}

add dynamic widgets on tap and save values flutter

I'm trying to add a new row of widgets (select gender and age from a drop-down menu ) when a user taps on adding a child and saves different data from each row also when deleting a child by index it should not affect the other values the user entered how can I achieve that?
this is the UI
UI
and here's the code
class ChildrenSection extends StatefulWidget {
const ChildrenSection({
Key? key,
}) : super(key: key);
#override
State<ChildrenSection> createState() => _ChildrenSectionState();
}
class _ChildrenSectionState extends State<ChildrenSection> {
int _count = 1;
List<String>? onGenderSelected;
#override
Widget build(BuildContext context) {
onGenderSelected = List<String>.filled(_count, '', growable: true);
return Row(
children: [
Text(
'Children',
style: NannyFinderTheme.createAdTextStyle,
),
SizedBox(
width: 10.w,
),
Expanded(
child: Column(
children: [
SizedBox(
height: (50 * _count).toDouble(),
child: ListView.builder(
itemCount: onGenderSelected?.length,
itemBuilder: (context, index) {
return _addChild(index);
}),
),
SizedBox(
height: 10.h,
),
InkWell(
onTap: () {
setState(() {
_count++;
});
},
child: Row(
children: [
const Icon(CupertinoIcons.person_badge_plus_fill),
SizedBox(
width: 10.w,
),
const Text(
'Add a child',
style: TextStyle(decoration: TextDecoration.underline),
)
],
),
)
],
),
),
],
);
}
Widget _addChild(int index) {
return Row(
children: [
InkWell(
onTap: () {
if (index != 0) {
setState(() {
_count--;
});
}
},
child: Icon(index == 0
? CupertinoIcons.person_fill
: CupertinoIcons.person_badge_minus_fill)),
SizedBox(
width: 10.w,
),
_children('Girl', index),
SizedBox(
width: 4.w,
),
_children('Boy', index),
//const Spacer(),
SizedBox(
width: 10.w,
),
Expanded(
child: CustomDropDownButton(
value: kListOfChildrenAge.first,
menuList: kListOfChildrenAge,
onChanged: (String? value) {},
),
)
],
);
}
Widget _children(String text, int index) {
return InkWell(
onTap: () {
setState(() {
onGenderSelected?[index] = text;
});
},
child: Container(
height: 30,
padding: EdgeInsets.symmetric(horizontal: 8.w),
decoration: BoxDecoration(
color: onGenderSelected?[index] == text
? NannyFinderTheme.ligtherPrimaryColor
: Colors.white,
borderRadius: BorderRadius.circular(4.r),
border: Border.all(width: 0.5, color: NannyFinderTheme.grayColor)),
child: Center(
child: Text(
text,
style: TextStyle(
color: onGenderSelected?[index] == text
? Colors.white
: Colors.black,
fontWeight: FontWeight.bold),
)),
),
);
}
}

only when use iphone simulator

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.

How to usage Obx() with getx in flutter?

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
)
),
]
)
)
)

Flutter : Type mismatch: inferred type is String? but String was expected

I am new to coding.I am using upi_pay package in my project to make UPI payments getting error as "Type mismatch: inferred type is String? but String was expected" when I tried the build the app
I followed this article https://dev.to/dsc_ciet/adding-upi-payment-gateway-in-flutter-376c
I am new to coding, don't mind if this was a easy thing.
Please go through the below code
Thanks in advance
class PaymentScreen extends StatefulWidget {
#override
_PaymentScreenState createState() => _PaymentScreenState();
}
class _PaymentScreenState extends State<PaymentScreen> {
String _upiAddrError;
final _upiAddressController = TextEditingController();
final _amountController = TextEditingController();
bool _isUpiEditable = false;
Future<List<ApplicationMeta>> _appsFuture;
#override
void initState() {
_amountController.text =
(Random.secure().nextDouble() * 10).toStringAsFixed(2);
_appsFuture = UpiPay.getInstalledUpiApplications();
super.initState();
}
void _generateAmount() {
setState(() {
_amountController.text =
(Random.secure().nextDouble() * 10).toStringAsFixed(2);
});
}
Future<void> _onTap(ApplicationMeta app) async {
final err = _validateUpiAddress(_upiAddressController.text);
if (err != null) {
setState(() {
_upiAddrError = err;
});
return;
}
setState(() {
_upiAddrError = null;
});
final transactionRef = Random.secure().nextInt(1 << 32).toString();
print("Starting transaction with is $transactionRef");
final a = await UpiPay.initiateTransaction(
amount: _amountController.text,
app: app.upiApplication,
receiverName: "Sharad",
receiverUpiAddress: _upiAddressController.text,
transactionRef: transactionRef,
merchantCode: '7372',
);
print(a);
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Container(
padding: EdgeInsets.symmetric(horizontal: 16),
child: ListView(
children: <Widget>[
Container(
margin: EdgeInsets.only(top: 32),
child: Row(
children: <Widget>[
Expanded(
child: TextFormField(
controller: _upiAddressController,
enabled: _isUpiEditable,
decoration: InputDecoration(
border: OutlineInputBorder(),
hintText: 'address#upi',
labelText: 'Receiving UPI Address',
),
),
),
Container(
margin: EdgeInsets.only(left: 8),
child: IconButton(
icon: Icon(
_isUpiEditable ? Icons.check : Icons.edit,
),
onPressed: () {
setState(() {
_isUpiEditable = !_isUpiEditable;
});
},
),
),
],
),
),
if (_upiAddrError != null)
Container(
margin: EdgeInsets.only(top: 4, left: 12),
child: Text(
_upiAddrError,
style: TextStyle(color: Colors.red),
),
),
Container(
margin: EdgeInsets.only(top: 32),
child: Row(
children: <Widget>[
Expanded(
child: TextField(
controller: _amountController,
readOnly: true,
enabled: false,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Amount',
),
),
),
Container(
margin: EdgeInsets.only(left: 8),
child: IconButton(
icon: Icon(Icons.loop),
onPressed: _generateAmount,
),
),
],
),
),
Container(
margin: EdgeInsets.only(top: 128, bottom: 32),
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Container(
margin: EdgeInsets.only(bottom: 12),
child: Text(
'Pay Using',
style: Theme.of(context).textTheme.caption,
),
),
FutureBuilder<List<ApplicationMeta>>(
future: _appsFuture,
builder: (context, snapshot) {
if (snapshot.connectionState != ConnectionState.done) {
return Container();
}
return GridView.count(
crossAxisCount: 2,
shrinkWrap: true,
mainAxisSpacing: 8,
crossAxisSpacing: 8,
childAspectRatio: 1.6,
physics: NeverScrollableScrollPhysics(),
children: snapshot.data
.map((it) => Material(
key: ObjectKey(it.upiApplication),
color: Colors.grey[200],
child: InkWell(
onTap: () => _onTap(it),
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment:
MainAxisAlignment.center,
children: <Widget>[
Image.memory(
it.icon,
width: 64,
height: 64,
),
Container(
margin: EdgeInsets.only(top: 4),
child: Text(
it.upiApplication.getAppName(),
),
),
],
),
),
))
.toList(),
);
},
),
],
),
)
],
),
),
),
);
}
}
String _validateUpiAddress(String value) {
if (value.isEmpty) {
return 'UPI Address is required.';
}
if (!UpiPay.checkIfUpiAddressIsValid(value)) {
return 'UPI Address is invalid.';
}
return null;
}
You're assigning null to _upiAddrError but it's a non-nullable String.
Declare that variable as String? _upiAddrError instead of String _upiAddrError to make it nullable.