ValueNotifier<String>#97fe7(go to the gym) - flutter

Hi everyone : the problem is simple but i just cant find the solution
here is my code :
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:todoye_app_angela/models/task_data.dart';
class AddTaskScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
ValueNotifier<String> newTaskTitle = ValueNotifier("");
return Container(
color: Color(0xFF757575),
child: Container(
padding: EdgeInsets.all(20),
decoration: BoxDecoration(
color: Colors.limeAccent[400],
borderRadius: BorderRadius.only(
topLeft: Radius.circular(60),
topRight: Radius.circular(60),
),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text(
'Add Task',
textAlign: TextAlign.center,
style: TextStyle(fontSize: 30, color: Colors.brown[900]),
),
SizedBox(
height: 12,
),
TextField(
onChanged: (newText) {
newTaskTitle.value = newText;
},
autocorrect: false,
decoration: InputDecoration(
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Colors.brown[800]!,
width: 2,
),
borderRadius: BorderRadius.circular(30),
),
hintText: 'Type Your Task ...',
labelStyle: TextStyle(
color: Colors.green[900],
),
helperStyle: TextStyle(
color: Colors.brown[900],
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(60),
borderSide: BorderSide(
color: Colors.brown[900]!,
width: 2,
),
),
),
),
SizedBox(
height: 12,
),
ValueListenableBuilder<String>(
valueListenable: newTaskTitle,
builder: (context, taskt, child) {
return ElevatedButton(
onPressed: taskt.isEmpty
? null
: () {
Provider.of<TaskData>(context, listen: false)
.addTask(newTaskTitle.toString());
print(taskt);
Navigator.pop(context);
// Provider.of<TaskData>(context, listen: false)
// .addTask(newTaskTitle);
// Navigator.pop(context);
},
child: Text(
'Add',
style: TextStyle(color: Colors.brown[900]),
),
style: ButtonStyle(
backgroundColor: MaterialStateColor.resolveWith(
(states) => Colors.lightGreen),
elevation: MaterialStateProperty.resolveWith((states) => 6),
shadowColor: MaterialStateColor.resolveWith(
(states) => Colors.green),
minimumSize: MaterialStateProperty.resolveWith(
(states) => Size.square(40.67)),
),
);
},
),
],
),
),
);
}
}
im trying to add some tasks in my todo app . simply the user have to type something in the textfield and this value is passed to the addtask function in my taskdata class to notify the listeners about it . the problem was th newTaskTitle variable is of type ValueNotifier and the value of my input function is a String i tried to solve this problem by adding the toString method here:
Provider.of<TaskData>(context, listen: false)
.addTask(newTaskTitle.toString());
but it returns this : ValueNotifier#97fe7(go to the gym) on the screen .. i just want the pure String from user .
please help me solve this problem ...
I appreciate it inadvance.

Your are using ValueNotifier.
Use ValueNotifier.value , newTaskTitle.value in your case to get the String value.
code:
...
...
Provider.of<TaskData>(context, listen: false)
.addTask(newTaskTitle.value);
...

Related

How to get data in a Flutter-ListView?

I'm building a form for shipping and am able to add as many items as possible. (Adding a Widget in a ListView every time a button is pressed)
My question is, once the form widgets are created and filled, how do I get the information from each TextFormField in each Widget?
Once the information is retrieved I will send it to Firebase.
Here's the code I Have:
import 'package:flutter/material.dart';
import 'package:flutter_login_test/helpers/constants.dart';
class AddItemsToRequest extends StatefulWidget {
const AddItemsToRequest({Key? key}) : super(key: key);
#override
State<AddItemsToRequest> createState() => _AddItemsToRequestState();
}
class _AddItemsToRequestState extends State<AddItemsToRequest> {
List<TextEditingController> controllers = [];
List<Widget> fields = [];
RegExp regExp = RegExp('[aA-zZ]');
int quantity = 0;
double weight = 0;
double height = 0;
Widget itemForm() {
return Column(children: [
Container(
decoration:
BoxDecoration(color: grey, border: Border.all(color: black)),
width: double.infinity,
child: const Center(
child: Text('Package details',
style: TextStyle(
fontWeight: FontWeight.bold,
backgroundColor: grey,
fontSize: 24)),
)),
Row(
children: [
Flexible(
child: TextFormField(
onChanged: (value) {
quantity = value as int;
},
keyboardType: TextInputType.number,
validator: (value) => value!.isEmpty || value is int
? 'Quantity cannot be empty'
: null,
autovalidateMode: AutovalidateMode.onUserInteraction,
decoration: const InputDecoration(
errorStyle: TextStyle(color: Colors.redAccent),
border: OutlineInputBorder(
borderSide: BorderSide(),
borderRadius: BorderRadius.all(
Radius.circular(0.0),
),
),
fillColor: Color.fromARGB(255, 238, 238, 238),
filled: true,
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.blueAccent, width: 2.5),
),
hintText: "Quantity : "),
),
),
Flexible(
child: TextFormField(
onChanged: (value) {
weight = value as double;
},
keyboardType: TextInputType.number,
validator: (value) => value!.isEmpty || regExp.hasMatch(value)
? 'Weight cannot be empty'
: null,
autovalidateMode: AutovalidateMode.onUserInteraction,
decoration: const InputDecoration(
errorStyle: TextStyle(color: Colors.redAccent),
border: OutlineInputBorder(
borderSide: BorderSide(),
borderRadius: BorderRadius.all(
Radius.circular(0.0),
),
),
fillColor: Color.fromARGB(255, 238, 238, 238),
filled: true,
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.blueAccent, width: 2.5),
),
hintText: "Weight : "),
),
),
Flexible(
child: TextFormField(
onChanged: (value) {
height = value;
},
validator: (value) => value!.isEmpty ? 'Height cannot be empty' : null,
autovalidateMode: AutovalidateMode.onUserInteraction,
decoration: const InputDecoration(
errorStyle: TextStyle(color: Colors.redAccent),
border: OutlineInputBorder(
borderSide: BorderSide(),
borderRadius: BorderRadius.all(
Radius.circular(0.0),
),
),
fillColor: Color.fromARGB(255, 238, 238, 238),
filled: true,
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.blueAccent, width: 2.5),
),
hintText: "Height : "),
),
),
],
),
]);
}
Widget _addTile() {
return ElevatedButton(
child: const Icon(Icons.add),
onPressed: () async {
final controller = TextEditingController();
final field = itemForm();
setState(() {
controllers.add(controller);
fields.add(field);
});
});
}
Widget _listView() {
return ListView.builder(
scrollDirection: Axis.vertical,
shrinkWrap: true,
itemCount: fields.length,
itemBuilder: (context, index) {
final item = fields[index];
return Dismissible(
key: ObjectKey(item),
onDismissed: (direction) {
// Remove the item from the data source.
setState(() {
fields.removeAt(index);
});
ScaffoldMessenger.of(context)
.showSnackBar(const SnackBar(content: Text('Package removed')));
},
background: Container(
color: const Color.fromARGB(255, 210, 31, 19),
child: const Center(
child: Text(
'Remove ',
style: TextStyle(
color: white, fontWeight: FontWeight.bold, fontSize: 32),
),
)),
child: Container(
width: double.infinity,
margin: const EdgeInsets.all(5),
child: fields[index],
),
);
},
);
}
Widget _okButton() {
return ElevatedButton(
onPressed: () {
for (var element in fields) {
print(quantity);
}
Navigator.of(context).pop();
print('ok');
},
child: const Text("OK"),
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(backgroundColor: blue),
body: Column(
mainAxisSize: MainAxisSize.max,
children: [
Flexible(child: _addTile()),
SizedBox(
height: MediaQuery.of(context).size.height - 200,
child: _listView()),
Flexible(child: _okButton()),
],
),
);
}
}
I think you are expecting this answer. iterate your list of texteditingcontroller and get the text stored in that controllers one by one.
for (int i = 0; i < controllers.length; i++) {
var data = controllers[i].text;
//print or add data to any other list and insert to another list and save to database
}

Can i Select Multiple Accounts in a Banking app and pay them different amounts at the same time in flutter?

import 'package:flutter/material.dart';
import 'package:flutter_typeahead/flutter_typeahead.dart';
import 'package:keyboard_dismisser/keyboard_dismisser.dart';
import 'package:money_formatter/money_formatter.dart';
import 'package:shukela_app/api/banking_app_api.dart';
import 'package:shukela_app/screens/stokvel_detail.dart';
import 'package:shukela_app/screens/stokvels.dart';
import 'package:shukela_app/utils/constants.dart';
import 'package:shukela_app/utils/global_variables.dart';
import 'package:sizer/sizer.dart';
import 'package:shukela_app/model/bankingapp_model.dart';
import '../utils/user_preferences.dart';
class PayMultipleStokvelScreen extends StatefulWidget {
const PayMultipleStokvelScreen({Key? key}) : super(key: key);
#override
State<PayMultipleStokvelScreen> createState() =>
_PayMultipleStokvelScreenState();
}
TextEditingController txtSearch = TextEditingController();
TextEditingController txtAmount = TextEditingController();
class _PayMultipleStokvelScreenState extends State<PayMultipleStokvelScreen> {
String? selectedType;
bool hasText = false;
String buttonText = "PAY NOW";
bool isLoading = false;
Widget? showHideIcon() {
if (hasText) {
return IconButton(
icon: const Icon(
Icons.clear,
color: AppColors.primaryBlue,
),
onPressed: () {
txtSearch.clear();
setState(() {
hasText = false;
});
},
);
} else {
return null;
}
}
// void _showMultiSelectDialog(BuildContext context) async {
// await showDialog(
// context: context,
// builder: (ctx) {
// return MultiSelectDialog(
// items: _animals.map((e) => MultiSelectItem(e, e)).toList(),
// initialValue: _selectedAnimals,
// onConfirm: (values) {...},
// );
// },
// );
// }
double? balance;
final _formKey = GlobalKey<FormState>();
var selectedValue;
List<StokvelDetail> selectedStokvel = [];
#override
void initState() {
super.initState();
balance = double.parse(UserPreferences.getBalance() ?? '');
}
mf() {
MoneyFormatter mf = MoneyFormatter(amount: balance!);
return mf;
}
StokvelListState currentState = StokvelListState.showAllListState;
#override
Widget build(BuildContext context) => KeyboardDismisser(
gestures: const [GestureType.onTap],
child: SafeArea(
child: Scaffold(
backgroundColor: AppColors.secondaryColor,
appBar: AppBar(
backgroundColor: AppColors.secondaryColor,
elevation: 0,
title: const Text('Pay Multiple Stokvel',
style: screenTitleTextStyle),
leading: IconButton(
icon: const Icon(
Icons.arrow_back_ios,
color: AppColors.primaryBlue,
),
onPressed: () => Navigator.pop(context),
),
),
body: Form(
key: _formKey,
child: Column(
children: [
SizedBox(height: 5.h),
Container(
height: 6.h,
width: 98.w,
padding: const EdgeInsets.fromLTRB(10, 0, 10, 0),
child: TypeAheadFormField<Stokvel?>(
debounceDuration: const Duration(milliseconds: 500),
hideSuggestionsOnKeyboardHide: false,
suggestionsBoxDecoration: const SuggestionsBoxDecoration(
constraints: BoxConstraints(maxHeight: 450),
color: AppColors.secondaryColor,
borderRadius: BorderRadius.all(Radius.circular(10))),
textFieldConfiguration: TextFieldConfiguration(
style: const TextStyle(
color: AppColors.primaryBlue,
fontSize: 15.0,
fontWeight: FontWeight.bold,
),
controller: txtSearch,
onChanged: (value) {
setState(() {
hasText = true;
});
},
decoration: InputDecoration(
prefixIcon: const Icon(
Icons.search,
color: AppColors.primaryBlue,
),
suffixIcon: showHideIcon(),
hintText: 'Search Stokvel',
border: const OutlineInputBorder(
borderSide:
BorderSide(color: AppColors.primaryBlue),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(4.0),
borderSide:
const BorderSide(color: AppColors.primaryBlue),
),
),
),
validator: (val) {
if (val!.isEmpty) {
return "Please select stokvel";
}
return null;
},
suggestionsCallback: BankingAppApi.getStokvelSuggestions,
itemBuilder: (context, Stokvel? suggestion) {
final stokvel = suggestion!;
//
return ListTile(
trailing: SizedBox(
height: 20.0,
width: 20.0,
child: Container(
color: AppColors.primaryBlue,
),
),
title: Text(
stokvel.stokvelName!,
style: const TextStyle(
fontFamily: Fonts.primaryFont,
fontWeight: FontWeight.bold,
color: AppColors.primaryBlue,
),
),
subtitle: Text(
stokvel.stokvelType!,
style: const TextStyle(
fontFamily: Fonts.primaryFont,
fontWeight: FontWeight.bold,
color: AppColors.primaryBlue),
),
);
},
noItemsFoundBuilder: (context) => const SizedBox(
height: 60,
child: Center(
child: Text(
'No Stokvel Found.',
style: TextStyle(fontSize: 20),
),
),
),
onSuggestionSelected: (Stokvel? suggestion) {
final stokvel = suggestion!;
setState(() {
txtSearch.text = stokvel.stokvelName!;
hasText = true;
});
stokvelID = stokvel.stokvelID;
memberID = stokvel.memberID;
},
),
),
SizedBox(
height: 4.h,
),
SizedBox(height: 3.h),
Container(
height: 6.h,
width: 98.w,
padding: const EdgeInsets.fromLTRB(10, 0, 10, 0),
child: TextFormField(
controller: txtAmount,
decoration: const InputDecoration(
labelStyle: TextStyle(
color: AppColors.primaryBlue,
fontSize: 20.0,
fontWeight: FontWeight.bold,
),
suffixText: "ZAR",
border: OutlineInputBorder(
borderSide:
BorderSide(color: AppColors.primaryBlue)),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(4)),
borderSide: BorderSide(
width: 1, color: AppColors.primaryBlue),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(4)),
borderSide: BorderSide(
width: 1, color: AppColors.primaryBlue),
),
labelText: 'Amount',
contentPadding:
EdgeInsets.only(left: 20, right: 15, bottom: 8),
),
keyboardType: TextInputType.number,
style: const TextStyle(
fontSize: 20.0,
fontFamily: Fonts.primaryFont,
color: AppColors.primaryBlue),
validator: (val) {
if (val!.isEmpty) {
return "Please enter amount";
}
return null;
},
),
),
SizedBox(height: 3.h),
Container(
height: 6.h,
width: 98.w,
padding: const EdgeInsets.fromLTRB(10, 0, 10, 0),
child: TextField(
readOnly: true,
style: const TextStyle(
fontSize: 18.0, fontWeight: FontWeight.bold),
textAlign: TextAlign.center,
decoration: InputDecoration(
hintText: "Wallet Balance : R " + mf().output.nonSymbol,
border: const OutlineInputBorder(
borderSide:
BorderSide(color: AppColors.primaryBlue),
borderRadius: BorderRadius.horizontal()),
focusedBorder: const OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(4)),
borderSide: BorderSide(
width: 1, color: AppColors.primaryBlue),
),
enabledBorder: const OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(4)),
borderSide: BorderSide(
width: 1, color: AppColors.primaryBlue),
),
),
),
),
SizedBox(height: 3.h),
Container(
height: 50,
width: 400,
padding: const EdgeInsets.fromLTRB(10, 0, 10, 0),
child: ElevatedButton(
style: ButtonStyle(
backgroundColor:
MaterialStateProperty.all(Colors.white)),
child: isLoading
? Row(
mainAxisAlignment: MainAxisAlignment.center,
children: const [
CircularProgressIndicator(
color: AppColors.secondaryColor),
SizedBox(width: 24),
Text(
"Submitting payment...",
style: TextStyle(
color: AppColors.secondaryColor),
)
],
)
: Text(
buttonText,
style: const TextStyle(
fontFamily: Fonts.primaryFont,
fontWeight: FontWeight.bold,
color: AppColors.primaryBlue),
),
onPressed: () {
if (_formKey.currentState!.validate()) {
if (double.parse(txtAmount.text) <= balance!) {
setState(
() {
isLoading = true;
},
);
stokvelTransact.amount =
double.parse(txtAmount.text);
stokvelTransact.memberID = memberID;
stokvelTransact.stokvelID = stokvelID;
stokvelTransact.transactionTypeID = 1;
api
.stokvelDeposit(stokvelTransact,
"StokvelTransaction/StokvelTransact")
.then(
(value) => setState(
() {
Future.delayed(
const Duration(seconds: 3));
isLoading = false;
if (value == "Success") {
ScaffoldMessenger.of(context)
.showSnackBar(snackBar(
content:
'Payment made succesfully',
duration: 5));
} else {
ScaffoldMessenger.of(context)
.showSnackBar(snackBar(
content:
'We have encountered technical problems, Try again later',
duration: 5));
}
},
),
)
.catchError(
(err) {
setState(() {
isLoading = false;
});
ScaffoldMessenger.of(context).showSnackBar(
snackBar(
content: err.toString(), duration: 7));
},
);
} else {
ScaffoldMessenger.of(context).showSnackBar(snackBar(
content: "Insuficient funds!", duration: 7));
}
}
},
),
),
],
),
),
),
),
);
}
The above code is for the single page that I want to achieve this
This is what I want to achieve or any suggestions are accepted, I want to mark the Group of Stokvels I want to pay and pay them different accounts I don't know if it's possible please I'm new in flutter it a project I have to get it done as soon as possible this is the source code for my whole payment page, for now, I'm able to pay a single Stokvel Group but I want to select multiple
I highly suggest starting with formatting of the current code - its hard to read and with that hard to maintain.
The simple idea would be:
use List<StokvelDetail> selectedStokvel = []; you created to add the Stokvel's in every time you select Stokvel in SearchBar
Add Map<int,double> amounts = {}; <StokvelId, amount> to keep track of the amount you want to send to each Stokvel
Based on selectedStokvel build multiple 'amount window' widgets
Before submit verify walletBalance >= amounts.values.reduce((a,b)=> a + b)
For each selectedStokvel call api.stokvelDeposit(stokvelTransact, ...
I would primarly focus on spliting this code to multiple Widget classes, there are many schools but I like to have around 150 lines of code in single file at most.
From what i see your file can be easily split into:
Column(
children: [
SizedBox(),
SearchBar(),
SizedBox(),
AmountInput(), --> StokvelAmountInput() for each selectedStokvel
SizedBox(),
WalletBalance(),
SizedBox(),
SubmitButton(),
]),
```

Store textfield value in Map value

so i have this map of questions and have a textfield widget and i'm using a for loop to go through the questions and display them.
id love to store the textfield data in the right place in the map (something like: question 1 => answer 1 and so on)
here's the code:
import 'package:flutter/material.dart';
class CustomQuestionField extends StatefulWidget {
#override
State<CustomQuestionField> createState() => _CustomQuestionFieldState();
}
class _CustomQuestionFieldState extends State<CustomQuestionField> {
final Map<String, String> qna = {
"Everyone should read...": "",
"Two truths and a lie...": "",
"I can quote every line from...": "",
"If I didn't have to work I would...": "",
"People think I am...": "",
"Never have I ever...": "",
"Believe it or not, I...": "",
"I am amazing at...": "",
"My life as a movie...": "",
"My ultimate dinner party guest list...": "",
"The dorkiest thing about me is...": "",
"On the weekend you'll find me...": "",
};
#override
Widget build(
BuildContext context,
) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
for (var q in qna.keys) question(q),
RaisedButton(
shape:
RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)),
color: Colors.purple,
child: Padding(
padding: const EdgeInsets.all(10.0),
child: Text(
"Submit",
style: TextStyle(color: Colors.white, fontSize: 20),
),
),
onPressed: () {
print(qna.values);
}),
],
);
}
Widget question(String question) {
final myController = TextEditingController();
return Padding(
padding: const EdgeInsets.only(top: 15),
child: Stack(
children: [
Card(
elevation: 0,
shape: RoundedRectangleBorder(
side: BorderSide(width: 0.5, color: Colors.black),
borderRadius: BorderRadius.circular(
32,
)),
child: Padding(
padding: const EdgeInsets.all(20.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Padding(
padding: const EdgeInsets.only(bottom: 15, left: 10),
child: Text(
question,
style: TextStyle(
color: Colors.black,
fontSize: 18.0,
fontWeight: FontWeight.bold),
),
),
TextField(
onChanged: ((value) {
print(value);
}),
onSubmitted: (String ansr) {
setState(() {
});
},
controller: myController,
decoration: InputDecoration(
// filled: true,
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(20),
borderSide: BorderSide(
color: Color.fromARGB(255, 128, 124, 124),
),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(20),
borderSide: BorderSide(
color: Color.fromARGB(255, 128, 124, 124),
),
),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(20),
borderSide: BorderSide(
color: Color.fromARGB(255, 128, 124, 124),
),
),
),
),
],
),
),
),
Positioned(
top: -10,
right: -25,
child: RawMaterialButton(
onPressed: () {},
elevation: 2.0,
fillColor: Colors.white,
child: Text(
"X",
style:
TextStyle(color: Colors.black, fontWeight: FontWeight.bold),
),
shape: CircleBorder(),
),
),
],
),
);
}
}
here's a screenshot:
any ideas on how to do it?
just create a map to contain the answers:
final Map<String, String> answers = {};
then in your onSubmitted, add this line:
answers[question] = ansr;
You does not defined key in map, convert your map into this
final Map<String, String> qna = [
{"question" : "Everyone should read...", "answer":""},
{"question" :"Two truths and a lie...", "answer":""},
{"question" :"I can quote every line from...", "answer":""},
.
.
.
{"question" :"On the weekend you'll find me...", "answer":""},
];
**In Text Field setState**
TextField(
onChanged: ((value) {
print(value);
}),
onSubmitted: (String ansr) {
setState(() {
q[answer]=ansr;
});
},
--------------------------------------
RaisedButton(
shape:
RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)),
color: Colors.purple,
child: Padding(
padding: const EdgeInsets.all(10.0),
child: Text(
"Submit",
style: TextStyle(color: Colors.white, fontSize: 20),
),
),
onPressed: () {
print(qna["answer"]);
}),

Separate suffixIcon for password visibility

How to separate suffixIcon for password visibility? If I press icon on field password it also does the same thing on field confirm password.
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
#override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
bool isObsecure = false;
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AppBar(
title: const Text('Text Form Field'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
TextFormField(
obscureText: isObsecure,
decoration: InputDecoration(
hintText: 'Password',
suffixIcon: IconButton(
onPressed: () {
setState(() {
isObsecure = !isObsecure;
});
},
icon: Icon(
isObsecure ? Icons.visibility_off : Icons.visibility,
),
),
),
),
TextFormField(
obscureText: isObsecure,
decoration: InputDecoration(
hintText: 'Confirm Password',
suffixIcon: IconButton(
onPressed: () {
setState(() {
isObsecure = !isObsecure;
});
},
icon: Icon(
isObsecure ? Icons.visibility_off : Icons.visibility,
),
),
),
),
],
),
),
),
);
}
}
you have to define 2 flags. 1 for password visibility and 1 for confirm:
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
#override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
bool isObsecure = false;
bool isConfirmObsecure = false;
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AppBar(
title: const Text('Text Form Field'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
TextFormField(
obscureText: isObsecure,
decoration: InputDecoration(
hintText: 'Password',
suffixIcon: IconButton(
onPressed: () {
setState(() {
isObsecure = !isObsecure;
});
},
icon: Icon(
isObsecure ? Icons.visibility_off : Icons.visibility,
),
),
),
),
TextFormField(
obscureText: isConfirmObsecure,
decoration: InputDecoration(
hintText: 'Confirm Password',
suffixIcon: IconButton(
onPressed: () {
setState(() {
isConfirmObsecure = !isConfirmObsecure;
});
},
icon: Icon(
isConfirmObsecure
? Icons.visibility_off
: Icons.visibility,
),
),
),
),
],
),
),
),
);
}
}
///You can use the provider also to hide and visible the password icon. Hope this will work for you.
////This is my forgot password screen
import 'package:flutter/material.dart';
import 'package:form_field_validator/form_field_validator.dart';
import 'package:provider/provider.dart';
import 'package:traveling/Provider/common/ObscureTextState.dart';
import 'package:traveling/helpers/AppColors.dart';
import 'package:traveling/helpers/AppStrings.dart';
import 'package:traveling/screens/Employee/home/BottomNavBar.dart';
class ForgotPasswordA extends StatefulWidget {
#override
_ForgotPasswordAState createState() => _ForgotPasswordAState();
}
class _ForgotPasswordAState extends State<ForgotPasswordA> {
/// These variables are used for getting screen height and width
double? _height;
double? _width;
///controllers are used to get text which user enter in TextFiled
TextEditingController confirmPasswordController = TextEditingController();
TextEditingController passwordController = TextEditingController();
GlobalKey<FormState> _formkey = GlobalKey();
String? confirmPassword, password;
#override
void initState() {
// TODO: implement initState
super.initState();
}
///this widget is the main widget and it is used for building a UI in the app
#override
Widget build(BuildContext context) {
_height = MediaQuery.of(context).size.height;
_width = MediaQuery.of(context).size.width;
return Material(
child: Scaffold(
backgroundColor: AppColors.white,
body:Consumer<LoginProvider>(
builder:(context, obs, child) {
///Consumer is used to get value from the loginProvider class
return GestureDetector(
onTap: () {
FocusScope.of(context).unfocus();
},
child: Container(
height: _height,
width: _width,
margin: EdgeInsets.only(top: 70),
padding: EdgeInsets.only(bottom: 5),
child: SingleChildScrollView(
child: Column(
children: <Widget>[
SizedBox(height: _height! / 22),
appText(),
SizedBox(height: _height! / 18),
Container(
width: _width! * .85,
child: Form(
///define global key for validation
key: _formkey,
autovalidateMode: AutovalidateMode.onUserInteraction,
child: Column(
children: <Widget>[
SizedBox(height: _height! / 50),
TextFormField(
controller: passwordController,
validator: (value) {
if (value!.isEmpty) {
return "Please Enter Password!";
} else if (value.length < 6) {
return "Please Enter more than 6 digit .";
} else {
return null;
}
},
obscureText:
Provider.of<LoginProvider>(context, listen: false)
.isTrue,
keyboardType: TextInputType.emailAddress,
autofillHints: [AutofillHints.email],
cursorColor: AppColors.black,
style: TextStyle(
color: Color(0xff919AAA),
),
decoration: InputDecoration(
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(25.0),
borderSide: BorderSide(
color: AppColors.textFieldColor,
),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(25.0),
borderSide: BorderSide(
color: AppColors.textFieldColor,
),
),
errorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(25.0),
borderSide: BorderSide(
color: AppColors.red,
),
),
focusedErrorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(25.0),
borderSide: BorderSide(
color: AppColors.red,
),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(25.0),
borderSide: BorderSide(
color: AppColors.textFieldColor,
),
),
floatingLabelBehavior: FloatingLabelBehavior.never,
suffixIcon: IconButton(
onPressed: () {
Provider.of<LoginProvider>(context, listen: false)
.toggleObs();
},
icon: Provider.of<LoginProvider>(context,
listen: false)
.switchObsIcon,
),
labelText: 'Password',
errorStyle: TextStyle(color: AppColors.red),
hintStyle: TextStyle(
color: Color(0xff919AAA),
),
),
),
//passwordTextFormField(),
SizedBox(height: _height! / 30.0),
///password visibility handle by provider state management
TextFormField(
controller: confirmPasswordController,
validator: (value) {
if (value!.isEmpty) {
return "Please Enter Password!";
} else if (value.length < 6) {
return "Please Enter more than 6 digit .";
} else {
return null;
}
},
obscureText:
Provider.of<LoginProvider>(context, listen: false)
.isConfirmPassword,
keyboardType: TextInputType.emailAddress,
autofillHints: [AutofillHints.email],
cursorColor: AppColors.black,
style: TextStyle(
color: Color(0xff919AAA),
),
decoration: InputDecoration(
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(25.0),
borderSide: BorderSide(
color: AppColors.textFieldColor,
),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(25.0),
borderSide: BorderSide(
color: AppColors.textFieldColor,
),
),
errorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(25.0),
borderSide: BorderSide(
color: AppColors.red,
),
),
focusedErrorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(25.0),
borderSide: BorderSide(
color: AppColors.red,
),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(25.0),
borderSide: BorderSide(
color: AppColors.textFieldColor,
),
),
floatingLabelBehavior: FloatingLabelBehavior.never,
suffixIcon: IconButton(
onPressed: () {
Provider.of<LoginProvider>(context, listen: false)
.toggleObsData();
},
icon: Provider.of<LoginProvider>(context,
listen: false)
.switchObsIcons,
),
labelText: 'Confirm Password',
errorStyle: TextStyle(color: AppColors.red),
hintStyle: TextStyle(
color: Color(0xff919AAA),
),
),
),
],
),
),
),
SizedBox(height: _height! / 28),
SizedBox(height: _height! / 22),
submitButton(),
SizedBox(height: _height! / 35),
],
),
),
),
);}
),
),
);
}
///app-text Widget is used for app logo and icon in top side
Widget appText() {
return Container(
width: _width! * 0.90,
child: Column(
children: <Widget>[
Image.asset(
"assets/traveling-text-icon.png",
height: 60,
),
SizedBox(
height: 5,
),
],
),
);
}
///for validation we used a submit button
Widget submitButton() {
return Card(
elevation: 20.0,
shadowColor: Colors.blue[100],
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(20.0))),
child: Container(
height: 60,
width: _width! * .85,
decoration: BoxDecoration(
// boxShadow: [BoxShadow(color: AppColors.grey, blurRadius: 20.0)],
borderRadius: BorderRadius.circular(20.0),
gradient: LinearGradient(colors: [
AppColors.blue,
Colors.blue.shade900,
])),
child: MaterialButton(
onPressed: () {
if(passwordController.text==confirmPasswordController.text){
Navigator.pushReplacement(context,
MaterialPageRoute(builder: (context) => EmployeeBottomNavBar()));}
else{
print("password did not match");
}
},
child: Text(
AppStrings.submit,
style: TextStyle(
color: Colors.white, fontSize: 14, fontWeight: FontWeight.bold),
),
),
),
);
}
}
////provider class
import 'package:flutter/material.dart';
import 'package:traveling/helpers/AppColors.dart';
class LoginProvider extends ChangeNotifier {
bool _isTrue = true;
bool _isConfirmPassword = true;
bool get isTrue => _isTrue;
bool get isConfirmPassword => _isConfirmPassword;
get switchObsIcons {
return _isConfirmPassword ? Icon(Icons.visibility_off,color: AppColors.textFieldTextColor,) : Icon(Icons.visibility,color: AppColors.textFieldTextColor,);
}
get switchObsIcon {
return _isTrue ? Icon(Icons.visibility_off,color: AppColors.textFieldTextColor,) : Icon(Icons.visibility,color: AppColors.textFieldTextColor,);
}
void toggleObsData() {
_isConfirmPassword = !_isConfirmPassword;
notifyListeners();
}
void toggleObs() {
_isTrue = !_isTrue;
notifyListeners();
}
}

I cant even print a nullable value

basically the problem is clear :
here is my code :
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
class AddTaskScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
late String newTaskTitle;
return Container(
color: Color(0xFF757575),
child: Container(
padding: EdgeInsets.all(20),
decoration: BoxDecoration(
color: Colors.limeAccent[400],
borderRadius: BorderRadius.only(
topLeft: Radius.circular(60),
topRight: Radius.circular(60),
),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text(
'Add Task',
textAlign: TextAlign.center,
style: TextStyle(fontSize: 30, color: Colors.brown[900]),
),
SizedBox(
height: 12,
),
TextField(
onChanged: (newText) {
newTaskTitle = newText;
},
autocorrect: false,
decoration: InputDecoration(
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Colors.brown[800]!,
width: 2,
),
borderRadius: BorderRadius.circular(30),
),
hintText: 'Type Your Task ...',
labelStyle: TextStyle(
color: Colors.green[900],
),
helperStyle: TextStyle(
color: Colors.brown[900],
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(60),
borderSide: BorderSide(
color: Colors.brown[900]!,
width: 2,
),
),
),
),
SizedBox(
height: 12,
),
ElevatedButton(
onPressed: () {
// Provider.of<TaskData>(context, listen: false)
// .addTask(newTaskTitle);
// Navigator.pop(context);
print(newTaskTitle);
// Provider.of<TaskData>(context, listen: false)
// .addTask(newTaskTitle);
// Navigator.pop(context);
},
child: Text(
'Add',
style: TextStyle(color: Colors.brown[900]),
),
style: ButtonStyle(
backgroundColor: MaterialStateColor.resolveWith(
(states) => Colors.lightGreen),
elevation: MaterialStateProperty.resolveWith((states) => 6),
shadowColor:
MaterialStateColor.resolveWith((states) => Colors.green),
minimumSize: MaterialStateProperty.resolveWith(
(states) => Size.square(40.67)),
),
),
],
),
),
);
}
}
please help me ...at this stage I just want to print the value that the user enters in the text field in the console ...but it gives me error :
LateInitializationError: Local 'newTaskTitle' has not been initialized.
i have also changed it to a stateful widget to check if it works with setstate but it didnt ..
i also made it nullable like this => String? newTaskTitle; and Ofcourse it made to change a lot of things but at last the null value was passed ...there is a problem whithin the onChange callback of the textfield that doesnt assign the new value of user input to the variable i have created ...
How can I fixe this problem ?
change
late String newTaskTitle;
to
ValueNotifier<String> newTaskTitle = ValueNotifier("");
and put ElevatedButton inside ValueListenableBuilder
like this
ValueListenableBuilder<String>(
listenable : newTaskTitle,
builder : (ctx,taskt,_){
return ElevatedButton(
onPressed : taskt.isEmpty ? null : (){
// put you logic
}
.....
);
}
);
change onChanged of textField like this
onChanged: (newText) {
newTaskTitle.value = newText;
},