How to properly dispose screens? - flutter

Currently I have the problem, that the screens are not being properly disposed by the TopNavigationBar.
How can I properly dispose them?
I tried to add navigatorKey.currentState.pop; before I navigate to a specific screen, which get selected at the TopNavigationBar. So the current screen will get disposed and after that I navigate to the selected screen from the TopNavigationBar.
But unfortunatly I still get a Duplicate GlobalKey detected in widget tree. error.
I think I am getting this error in the login screen, because the screens are not properly disposed (when I click 2 times on the TopNavigationBarItem "Login", then the error occurs). So I try to figure out, how I can properly dispose them.
What I am doing wrong? How can I properly dispose them?
I think, when I dispose the screens correctly, then my final GlobalKey<FormState> _formKeys will work as expected and the error will disappear.
Edit:
"Properly disposing screens" solved with the comment of Anees, but the problem is still not fixed.
I have 2 options:
-using the answer from Duplicate GlobalKey detected in widget tree and change my GlobalKey to final GlobalKey<FormState> _formKeys = GlobalKey<FormState>();
But then my keyboard on the smartphone is not working anymore (instantly disappearing after clicking on a Textfield).
or
-trying to find another solution for this problem without getting another problem.
navigation_service.dart code:
import 'package:flutter/material.dart';
class NavigationService {
final GlobalKey<NavigatorState> navigatorKey =
GlobalKey<NavigatorState>();
Future<dynamic> navigateTo(String routeName) {
// dispose of the current screen, then navigate to the new screen
navigatorKey.currentState.pop;
return navigatorKey.currentState.pushNamed(routeName);
}
void goBack() {
return navigatorKey.currentState.pop();
}
}
top_nav_item.dart code: (onTap function is doing the navigation in the TopNavigationbar)
import 'package:bestfitnesstrackereu/widgets/top_navbar_item/top_navbar_item_desktop.dart';
import 'package:bestfitnesstrackereu/widgets/top_navbar_item/top_navbar_item_mobile.dart';
import 'package:bestfitnesstrackereu/widgets/top_navbar_item/top_navbar_item_tablet.dart';
import 'package:flutter/material.dart';
import 'package:responsive_builder/responsive_builder.dart';
import '../../datamodels/navbar_item_model.dart';
import '../../locator.dart';
import '../../services/navigation_service.dart';
class TopNavBarItem extends StatelessWidget {
final String title;
final String navigationPath;
final IconData icon;
const TopNavBarItem(this.title, this.navigationPath, {this.icon});
#override
Widget build(BuildContext context) {
// every NavBarItem need to have this model
var model = NavBarItemModel(
title: title,
navigationPath: navigationPath,
iconData: icon,
);
return GestureDetector(
onTap: () {
locator<NavigationService>().navigateTo(navigationPath);
},
child: ScreenTypeLayout(
desktop: TopNavBarItemTabletDesktop(
model: model,
),
tablet: TopNavBarItemTablet(
model: model,
),
mobile: TopNavBarItemMobile(
model: model,
),
),
);
}
}
top_navigation_bar_user.dart code: (it's the TopNavigationBar)
class TopNavigationBarUserDesktop extends StatelessWidget {
const TopNavigationBarUserDesktop({Key key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Container(
height: 100,
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
SizedBox(width: 30,),
TopNavBarLogo(),
SizedBox(width: 30,),
Visibility(child: Text( "TheBestFitnessTracker", style: TextStyle(color: Colors.black, fontSize: 14, fontWeight: FontWeight.normal,))),
Spacer(), //Space between logo+text and widgets in the center of the row
TopNavBarItem('Informationen', InformationRoute, ),
SizedBox(width: 30,),
TopNavBarItem('Neuigkeiten', NeuigkeitenRoute),
SizedBox(width: 30,),
Spacer(), //Space between widgets in the center of the row and end of row
SizedBox(width: 30,),
TopNavBarItem('Login', AuthenticationPageRoute),
SizedBox(width: 30,),
TopNavBarItem('Teilehmer \n werden', RegristrationUserRoute),
SizedBox(width: 30,),
],
),
);
}
}
authentification.dart (login) code: (problems with the GlobalKey _formKeys, so form widget and TextFormFields)
import 'package:bestfitnesstrackereu/routing/route_names.dart';
import 'package:email_validator/email_validator.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../../provider/auth.dart';
import '../../widgets/loading_circle/loading_circle.dart';
//AuthenticationPage (Login page)
class AuthenticationPage extends StatefulWidget {
#override
State<AuthenticationPage> createState() => _AuthenticationPageState();
}
class _AuthenticationPageState extends State<AuthenticationPage> {
static final GlobalKey<FormState> _formKeys = GlobalKey<FormState>();
var userData;
#override
void dispose() {
super.dispose();
}
#override
Widget build(BuildContext context) {
final authProvider = Provider.of<AuthProvider>(context);
return Scaffold(
body: SingleChildScrollView(
child: Center(
// checks the authentication status, when it is Authenticating, then return loading, else show the page
child: authProvider.status == Status.Authenticating ? Loading() : Container(
constraints: BoxConstraints(maxWidth: 440),
padding: EdgeInsets.all(24),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Row(
children: [
Padding(
padding: EdgeInsets.only(right: 12),
child: Image.asset("assets/logo.png", width: 300,),
),
Expanded(child: Container()),
],
),
SizedBox(
height: 30,
),
Row(
children: [
Text("Login",
style: TextStyle(
fontSize: 30, fontWeight: FontWeight.bold
)),
],
),
SizedBox(height: 10,),
Row(
children: const [
Text(
"Wilkommen zurück zum Login",
style: TextStyle(
color: Colors.grey,))
],
),
SizedBox(height: 15,),
Form(
key: _formKeys,
//autovalidateMode: AutovalidateMode.always,
child: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
TextFormField(
//validator: (email) => EmailValidator.validate(email) ? null : "Bitte gib eine gültige E-Mail an.",
controller: authProvider.emailController,
decoration: InputDecoration(
labelText: "E-Mail",
hintText: "abc#domain.com",
suffixIcon: Icon(Icons.mail_outline,),
//isDense: true,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(20)
)
),
),
SizedBox(height: 15,),
TextFormField(
validator: (password) {
print(authProvider.validatePassword(password));
return authProvider.validatePassword(password);
},
controller: authProvider.passwordController,
obscureText: true,
decoration: InputDecoration(
labelText: "Passwort",
hintText: "******",
suffixIcon: Icon(Icons.lock_outline, color: Colors.grey,),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(20)
)
),
),
],
),
),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 25.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
GestureDetector(
onTap: () {
authProvider.clearController();
Navigator.of(context).pushNamed(ForgotPasswordRoute); // navigate to the forgot password page
},
child: Text(
'Passwort vergessen',
style: TextStyle(
color: Colors.blue[700],
fontWeight: FontWeight.bold,
),
),
)
],
),
),
SizedBox(height: 15,),
InkWell(
onTap: () async {
//check if email and password field is not empty
if(authProvider.emailController.text.trim().isEmpty || authProvider.passwordController.text.trim().isEmpty){
showDialog(context: context, builder: (BuildContext context){
return AlertDialog(
title: Text("Error: Bitte fülle das E-Mail- und Passwort-Feld aus."),
actions: [
TextButton(
child: Text("Ok"),
onPressed: () {
Navigator.of(context).pop();
},
)
],
);
});
} else {
//checking if the email and password is valid
if(_formKeys.currentState.validate()){
print('validate email okok');
// input is the authProvider.emailController, which provides the written email from the user
// output are all the user informations in a Map<String, dynamic>
// used to check the status and role of the user
Map<String, dynamic> mapUserinformations = {};
mapUserinformations = await authProvider.getUserByEmail();
// checking if the admin/scientist exist
if (mapUserinformations != null){
//status from user = locked
if(mapUserinformations['status'] == 'gesperrt'){
showDialog(context: context, builder: (BuildContext context){
return AlertDialog(
title: Text("Error: Dein Account ist gesperrt"),
actions: [
TextButton(
child: Text("Ok"),
onPressed: () {
Navigator.of(context).pop();
},
)
],
);
});
}
//status from user = deleted
if(mapUserinformations['status'] == 'gelöscht'){
showDialog(context: context, builder: (BuildContext context){
return AlertDialog(
title: Text("Error: Dein Account wurde gelöscht. Er existiert nicht mehr."),
actions: [
TextButton(
child: Text("Ok"),
onPressed: () {
Navigator.of(context).pop();
},
)
],
);
});
}
//status from user = active
if(mapUserinformations['status'] == 'aktiv') {
//role from user = admin
if (mapUserinformations['role'] == 'Admin') {
print('admin - am einloggen');
if(!await authProvider.signIn()){ //signIn failed, then return "Login failed"
showDialog(context: context, builder: (BuildContext context){
return AlertDialog(
title: Text("Error: Login fehlgeschlagen. Falsche Kombination aus E-Mail und Passwort."),
actions: [
TextButton(
child: Text("Ok"),
onPressed: () {
authProvider.clearController();
Navigator.of(context).pop();
},
)
],
);
});
}
else {
authProvider.clearController();
Navigator.of(context).pushNamed(UsersAdministrationRoute);
}
}
//role from user = scientist
if (mapUserinformations['role'] == 'Wissenschaftler') {
print('scientist - am einloggen');
if(!await authProvider.signIn()){ //signIn failed, then return "Login failed"
showDialog(context: context, builder: (BuildContext context){
return AlertDialog(
title: Text("Error: Error: Login fehlgeschlagen. Falsche Kombination aus E-Mail und Passwort."),
actions: [
TextButton(
child: Text("Ok"),
onPressed: () {
authProvider.clearController();
Navigator.of(context).pop();
},
)
],
);
});
}
else { //if signIn is success, then clear controller and navigate to User Scientist page
authProvider.clearController();
Navigator.of(context).pushNamed(UsersAdministrationRoute);
}
}
//role from user = user
if (mapUserinformations['role'] == 'User') {
print('user - kein zugriff');
showDialog(context: context, builder: (BuildContext context){
return AlertDialog(
title: Text("Error: Du hast keine Zugriffsberichtigung auf diesen Login."),
actions: [
TextButton(
child: Text("Ok"),
onPressed: () {
authProvider.clearController();
Navigator.of(context).pop();
},
)
],
);
});
}
}
}else {
showDialog(context: context, builder: (BuildContext context){
return AlertDialog(
title: Text("Error: Ein Benutzer mit dieser E-Mail existiert nicht."),
actions: [
TextButton(
child: Text("Ok"),
onPressed: () {
Navigator.of(context).pop();
},
)
],
);
});
}
}else{
print('validate email notgoodatall');
showDialog(context: context, builder: (BuildContext context){
return AlertDialog(
title: Text("Error: Bitte gebe eine gültige E-Mail an."),
actions: [
TextButton(
child: Text("Ok"),
onPressed: () {
Navigator.of(context).pop();
},
)
],
);
});
}}},
child: Container(
decoration: BoxDecoration(color: Colors.deepPurple,
borderRadius: BorderRadius.circular(20)),
alignment: Alignment.center,
width: double.maxFinite,
padding: EdgeInsets.symmetric(vertical: 16),
child: Text(
"Login",
style: TextStyle(
color: Colors.white,
),)
)
),
SizedBox(height: 15,),
Row(
children: [
Expanded(
child: Divider(
height: 50,
color: Colors.grey[500],
)
),
Padding(
padding: EdgeInsets.symmetric(horizontal: 20),
child: Text('Du bist noch nicht registriert?'),
),
Expanded(
child: Divider(
height: 50,
color: Colors.grey[500],
)
),
],
),
SizedBox(height: 15,),
InkWell(
onTap: (){
authProvider.clearController();
Navigator.of(context).pushNamed(RegristrationUserRoute); // navigation to the Registration page
},
child: Container(
decoration: BoxDecoration(color: Colors.deepPurple,
borderRadius: BorderRadius.circular(20)),
alignment: Alignment.center,
width: double.maxFinite,
padding: EdgeInsets.symmetric(vertical: 16),
child: Text(
"Teilnehmer werden",
style: TextStyle(
color: Colors.white,
),)
)
),
],
),
)
),
),
);
}
}

You should try like this
pushNamedAndRemoveUntil('/login', (Route route) => false);

Related

can someone explain to me why 1 positional argument expected but 0 found

I am new to Flutter. I'm trying to make another alert dialog window after I click Yes on first alert dialog, but there is an error. The error was at my showSecond(); The outcome somehow will be like this. It would be a pleasure if someone can explain to me ;( and show me the right one. Thank you so much!
This is my code.
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:smart_parking/features/home/homescreen.dart';
class MyBottomBar extends StatelessWidget {
const MyBottomBar({ Key? key }) : super(key: key);
#override
Widget build(BuildContext context) {
return Container(
height: 50,
width: double.maxFinite,
decoration: BoxDecoration(
color: Colors.grey.shade200
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget> [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('Total payment', style: TextStyle( fontSize: 15, decoration: TextDecoration.none, color: Colors.grey.shade800)),
SizedBox(height: 5),
Text('RM 46.00', style: TextStyle(color: Colors.black, fontWeight: FontWeight.bold, fontSize: 10, decoration: TextDecoration.none),)
],
),
SizedBox( width: 90),
Image.asset('boxP.png', height: 30, width: 50),
Spacer(),
Column(
children: [
Container( height: 50, width: 150, color: Colors.black,
child: Align(
alignment: Alignment.center,
child: TextButton(child: Text('PAY', style: TextStyle(color: Colors.white)),
onPressed: () {
showAlertDialog(context);
},),
),
)
],
),
]
),
);
}
}
void showAlertDialog(BuildContext context) {
showDialog(context: context,
builder: (BuildContext context)
{ return CupertinoAlertDialog(
title: Text("Payment Confirmation", style: TextStyle( fontWeight: FontWeight.bold),),
content: Text("Are you sure with your payment?"),
actions: [
CupertinoDialogAction(child: Text('Cancel'),
onPressed: () { Navigator.of(context).pop();
}
),
CupertinoDialogAction
(child: Text("Yes"),
onPressed: () {
Navigator.push(context,
MaterialPageRoute(builder: (context) => const HomeScreen()));
showSecond();
},
)
],
);
}, );
}
void showSecond( BuildContext context) {
showDialog(
context: context,
builder: (BuildContext context) => AlertDialog(
title: Text("Thank you for paying with us"),
content: Icon(Icons.check_circle_outline),
actions: [
TextButton(
onPressed: () {
Navigator.of(context).pop();
},
child: const Text('Okay'),
),
],
),
);
}
try this one bro
onPressed: () {
Navigator.push(context,
MaterialPageRoute(builder: (context) => const HomeScreen()));
showSecond(context);
},

Setstate() not working to update suffixIcon inside AlertDialog ? - Flutter

I'm trying to update the suffixIcon in Form for TextFormField's InputDecoration , to check the length of the giving String by onChange function ,but no update . In add I did test on Textcontroller to give it value when the length >= 8 it's worked ,I wish I give a good idea for the issue . thanks in advance for your solution .
import 'package:flutter/material.dart';
bulidDialogChangePass() {
return DialogPass();
}
class DialogPass extends StatefulWidget {
const DialogPass({Key? key}) : super(key: key);
#override
State<StatefulWidget> createState() {
return DialogPassState();
}
}
class DialogPassState extends State<DialogPass> {
TextEditingController _fPasswordValue = TextEditingController();
TextEditingController _sPasswordValue = TextEditingController();
final _formKey = GlobalKey<FormState>();
ValueChanged<String>? onChanged;
bool _showIcons = false;
bool _startValidateFPass = false;
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.only(bottom: 25.0),
child: Wrap(
children: [
Container(
child: Row(
children: [
Text("Password :"),
TextButton(
onPressed: () {
_showDialog(context);
},
child: Wrap(
direction: Axis.vertical,
alignment: WrapAlignment.end,
children: [Text("Change")],
),
)
],
),
),
],
),
);
}
_showDialog(BuildContext context) async {
var size = MediaQuery.of(context).size;
return await showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
content: Stack(
clipBehavior: Clip.none,
children: <Widget>[
Form(
key: _formKey,
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Padding(
padding: EdgeInsets.all(8.0),
child: TextFormField(
controller: _fPasswordValue,
onChanged: (value) {_onChange(_fPasswordValue.text);},
decoration: InputDecoration(
labelText: "New Password",
suffixIcon: _showIcons && _startValidateFPass ? _setIcon() :null,
),
),
),
Padding(
padding: EdgeInsets.all(8.0),
child: TextFormField(
controller: _sPasswordValue,
decoration: InputDecoration(
labelText: "Confirm Password",
suffixIcon: _showIcons && _startValidateFPass ? _setIcon() :null, // I will change to check aothers soon
),
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Wrap(
children: [
OutlinedButton(
style: OutlinedButton.styleFrom(
fixedSize: Size(size.width / 2 - 10, 20),
padding: EdgeInsets.symmetric(horizontal: 50),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20)),
),
onPressed: () {},
child: Text("CANCEL",
style: TextStyle(
fontSize: 14,
letterSpacing: 2.2,
color: Colors.black)),
),
OutlinedButton(
style: OutlinedButton.styleFrom(
fixedSize: Size(size.width / 2 - 10, 20),
backgroundColor: Colors.blue[400],
primary: Colors.black,
padding: EdgeInsets.symmetric(horizontal: 50),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20)),
),
onPressed: () {},
child: Text("Save",
style: TextStyle(
fontSize: 14,
letterSpacing: 2.2,
color: Colors.black)),
),
],
),
),
],
),
),
],
),
);
});
}
_onChange(String value) {
setState(() {
_startValidateFPass = true;
if (value.length >= 8) {
_sPasswordValue.text = "test"; // test to check setState
_showIcons = true;
}
});
}
Icon _setIcon() {
Icon icon;
if(_showIcons){
_sPasswordValue.text = "test"; // test to check setState
print('dfsdfsd');
icon = Icon(
Icons.done_all,
color: Colors.green,
);
}else{
icon = Icon(
Icons.highlight_off,
color: Colors.red,
);
}
return icon;
}
}
Make another stateful widget and make Alertdialog as its child or use stateful builder to accomplish this as
showDialog(
context: context,
builder: (context) {
String contentText = "Your Dialog";
return StatefulBuilder(
builder: (context, setState) {
return AlertDialog(
title: Text("Title"),
content: Text(contentText),
actions: <Widget>[
TextButton(
onPressed: () => Navigator.pop(context),
child: Text("Cancel"),
),
TextButton(
onPressed: () {
setState(() {
contentText = "Changed state";
});
},
child: Text("Change"),
),
],
);
},
);
},
);

Flutter General dialog box - set state not working

I have an issue with my General Dialog Box. I would like to display a star. Then I would like to change it state when the star is taped and replace the icon by a yellow Star.
But is does not work. The Dialog Box is not refreshed so the icon is not changing. Please, can you look at the source code below and point me into the right direction please?
Many thanks.
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:date_time_picker/date_time_picker.dart';
import 'package:gtd_official_sharped_focused/snackbar.dart';
String _isImportantInboxTask ;
String _isUrgentInboxTask ;
String inboxTaskDisplayed;
String isImportant = "false" ;
String isUrgent = "false" ;
String myProjectName ;
var taskSelectedID;
//---------------
//String _initialValue;
//_-----------------
var documentID;
var textController = TextEditingController();
var popUpTextController = TextEditingController();
class Inbox extends StatefulWidget {
Inbox({Key key}) : super(key: key);
#override
_InboxState createState() => _InboxState();
}
class _InboxState extends State<Inbox> {
GlobalKey<FormState> _captureFormKey = GlobalKey<FormState>();
bool isOn = true;
#override
Widget build(BuildContext context) {
void showAddNote() {
TextEditingController _noteField = new TextEditingController();
showDialog(
context: context,
builder: (BuildContext context) {
return CustomAlertDialog(
content: Container(
width: MediaQuery.of(context).size.width / 1.3,
height: MediaQuery.of(context).size.height / 4,
child: Column(
children: [
TextField(
controller: _noteField,
maxLines: 4,
decoration: InputDecoration(
border: const OutlineInputBorder(
borderSide:
const BorderSide(color: Colors.black, width: 1.0),
),
),
),
SizedBox(height: 10),
Material(
elevation: 5.0,
borderRadius: BorderRadius.circular(25.0),
color: Colors.white,
child: MaterialButton(
minWidth: MediaQuery.of(context).size.width / 1.5,
onPressed: () {
Navigator.of(context).pop();
CollectionReference users = FirebaseFirestore.instance
.collection('Users')
.doc(FirebaseAuth.instance.currentUser.uid)
.collection('allTasks');
users
.add({'task_Name': _noteField.text,'task_Status': 'Inbox' })
.then((value) => print("User Document Added"))
.catchError((error) =>
print("Failed to add user: $error"));
},
padding: EdgeInsets.fromLTRB(10.0, 15.0, 10.0, 15.0),
child: Text(
'Add Note',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 20.0,
color: Colors.black,
fontWeight: FontWeight.bold,
),
),
),
),
],
),
),
);
});
}
return Scaffold(
appBar: new AppBar(
title: new Text('Inbox Page'),
actions: <Widget>[
IconButton(
icon: Icon(
Icons.add_circle_outline,
color: Colors.white,
),
onPressed: () {
showAddNote();
// do something
},
),
],
),
drawer: MyMenu(),
backgroundColor: Colors.white,
body: Column(
//mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
height: MediaQuery.of(context).size.height / 1.4,
width: MediaQuery.of(context).size.width,
child: StreamBuilder(
stream: FirebaseFirestore.instance
.collection('Users')
.doc(FirebaseAuth.instance.currentUser.uid)
.collection('allTasks')
.where('task_Status', isEqualTo: 'Inbox')
.snapshots(),
builder: (BuildContext context,
AsyncSnapshot<QuerySnapshot> snapshot) {
if (!snapshot.hasData) {
return Center(
child: CircularProgressIndicator(),
);
}
return ListView(
children: snapshot.data.docs.map((document) {
return Wrap(
children: [Card(
child: SwipeActionCell(
key: ObjectKey(document.data()['task_Name']),
actions: <SwipeAction>[
SwipeAction(
title: "delete",
onTap: (CompletionHandler handler) {
CollectionReference users = FirebaseFirestore
.instance
.collection('Users')
.doc(
FirebaseAuth.instance.currentUser.uid)
.collection('allTasks');
users
.doc(document.id)
.delete()
.then((value) => print("Note Deleted"))
.catchError((error) => print(
"Failed to delete Task: $error"));
},
color: Colors.red),
],
child: Padding(
padding: const EdgeInsets.all(0.0),
child: ListTile(
leading: ConstrainedBox(
constraints: BoxConstraints(
minWidth: leadingIconMinSize,
minHeight: leadingIconMinSize,
maxWidth: leadingIconMaxSize,
maxHeight: leadingIconMaxSize,
),
child: Image.asset('assets/icons/inbox.png'),
),
title: GestureDetector(
child: Text(
//'task_Name' correspond au nom du champ dans la table
document.data()['task_Name'],
maxLines: 2,
overflow: TextOverflow.ellipsis,
),
// Pour editer task
onDoubleTap: (){
taskSelectedID = FirebaseFirestore
.instance
.collection('Users')
.doc(
FirebaseAuth.instance.currentUser.uid)
.collection('allTasks')
.doc(document.id);
//Dialog
return showGeneralDialog(
context: context,
barrierDismissible: true,
barrierLabel: MaterialLocalizations.of(context)
.modalBarrierDismissLabel,
barrierColor: Colors.black45,
transitionDuration: const Duration(milliseconds: 20),
pageBuilder: (BuildContext buildContext,
Animation animation,
Animation secondaryAnimation) {
return Scaffold(
appBar: AppBar(
title: Text ('Edit Task'),
leading: InkWell(
child: Icon(Icons.close),
onTap:(){Navigator.of(context).pop();}
),
actions: [Padding(
padding: const EdgeInsets.fromLTRB(0, 0,16.0,0),
child: InkWell(
child: Icon(Icons.save),
onTap: () {
final loFormInbox = _captureFormKey
.currentState;
if (loFormInbox.validate()) {
loFormInbox.save();
CollectionReference users = FirebaseFirestore
.instance
.collection(
'Users')
.doc(FirebaseAuth
.instance
.currentUser.uid)
.collection(
'allTasks');
users
.add({
'task_Name': _valueTaskNameSaved,
})
.then((value) =>
print(
"Task Created"))
.catchError((
error) =>
print(
"Failed to add task: $error"));
showSimpleFlushbar(
context,
'Task Saved',
_valueTaskNameSaved,
Icons
.mode_comment);
loFormInbox.reset();
isImportant = 'false';
isUrgent = 'false';
}
}
),
)],
),
body: Center(
child: Container(
width: MediaQuery.of(context).size.width - 10,
height: MediaQuery.of(context).size.height - 80,
padding: EdgeInsets.all(20),
color: Colors.white,
child: Column(
children: [
Theme(
data: ThemeData(
inputDecorationTheme: InputDecorationTheme(
border: InputBorder.none,
)
),
child: Padding(
padding: const EdgeInsets.fromLTRB(8.0, 0.0, 15.0, 1.0),
child: TextFormField(
initialValue: document.data()['task_Name'],
decoration: InputDecoration(hintText: "Task Name"),
maxLength: 70,
maxLines: 2,
onChanged: (valProjectName) => setState(() => _valueTaskNameChanged = valProjectName),
validator: (valProjectName) {
setState(() => _valueTaskNameToValidate = valProjectName);
return valProjectName.isEmpty? "Task name cannot be empty" : null;
},
onSaved: (valProjectName) => setState(() => _valueTaskNameSaved = valProjectName),
),
)),
//Test Energy et Time / Important /urgent
Material(
child:
Container(
// color: Colors.red,
alignment: Alignment.center,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children:[
//Important
FlatButton(
child:
InkWell(
child: Container(
// color: Colors.white,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
isImportant =="true" ? Icon(Icons.star,color: Colors.orange,) :
Icon(Icons.star_border, color: Colors.grey,),
// Icon(Icons.battery_charging_full),
Text('Important'),
],
)
),
onTap: () {
setState(() {
if (isImportant=='true'){
isImportant = 'false';}
else
{isImportant= 'true';
}
});
},
),
),
RaisedButton(
onPressed: () {
Navigator.of(context).pop();
},
child: Text(
"Close",
style: TextStyle(color: Colors.white),
),
color: const Color(0xFF1BC0C5),
)
//++++++++++++++++
],
),
),
),
);
});
},
),
),
),
),
),
),
]
);
}).toList(),
);
}),
),
],
),
bottomNavigationBar: MyBottomAppBar(), //PersistentBottomNavBar(),
);
}
}
#override
Widget build(BuildContext context){
return _widget();
}
}
Thanks to your solution, I am able to do what I was willing to do. But now, I have an other issue. In the version 1 of my code, I am using this code
Theme(
data: ThemeData(
inputDecorationTheme: InputDecorationTheme(
border: InputBorder.none,
)
),
child: Padding(
padding: const EdgeInsets.fromLTRB(8.0, 0.0, 15.0, 1.0),
child: TextFormField(
initialValue: document.data()['task_Name'],
decoration: InputDecoration(hintText: "Task Name"),
maxLength: 70,
maxLines: 2,
onChanged: (valProjectName) => setState(() => _valueTaskNameChanged = valProjectName),
validator: (valProjectName) {
setState(() => _valueTaskNameToValidate = valProjectName);
return valProjectName.isEmpty? "Task name cannot be empty" : null;
},
onSaved: (valProjectName) => setState(() => _valueTaskNameSaved = valProjectName),
),
)),
This part was working well. But after the modifications, I am getting an error. The error is about document.
Undefined name 'document'. Try correcting the name to one that is defined, or defining the name.
Please, can you help me with this so I can finalize this page. Thank you
So you want to change the color of icon on clicking it inside dialogBox,
but unfortunately you are using stateless widget Scaffold in return of showGeneralDialog builder so one thing that can possibly help is to make a separate StateFull Widget RatingDialogBox and use that in the builder.
Also instead of InkWell you can use IconButton
I will suggest you to use this package it is great
flutter_rating_bar
also feel free to comment is this doesn't satisfy your need

Need to change color of selected RadioListTile to green if user selects correct answer and red when wrong answer is selected

I am creating an multiple choice quiz app using flutter, currently when user selects an answer in radio list tile it, will check for correct answer and show a toast message.
Need to update the code to highlight selected answer with green color if answer is correct
and red if the answer is wrong.
If any idea please update the code and share the code. Thanks in advance.
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:mechanicalaptitude/quiz/models/category.dart';
import 'package:mechanicalaptitude/quiz/models/question.dart';
import 'package:mechanicalaptitude/quiz/ui/pages/quiz_finished.dart';
import 'package:html_unescape/html_unescape.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:admob_flutter/admob_flutter.dart';
class QuizPage extends StatefulWidget {
final List<Question> questions;
final Category category;
const QuizPage({Key key, #required this.questions, this.category})
: super(key: key);
#override
_QuizPageState createState() => _QuizPageState();
}
class _QuizPageState extends State<QuizPage> {
final TextStyle _questionStyle = TextStyle(
fontSize: 18.0, //font size of the questions
fontWeight: FontWeight.bold,
color: Colors.red);
int _currentIndex = 0;
int i = 0;
int hint_index = 0;
var option1;
final Map<int, dynamic> _answers = {};
final GlobalKey<ScaffoldState> _key = GlobalKey<ScaffoldState>();
#override
Widget build(BuildContext context) {
Question question = widget.questions[_currentIndex];
final List<dynamic> options = question.incorrectAnswers;
if (!options.contains(question.correctAnswer)) {
options.add(question.correctAnswer);
//options.shuffle();
}
return WillPopScope(
onWillPop: _onWillPop,
child: Scaffold(
key: _key,
appBar: AppBar(
title: Text("Question No. - " + "${_currentIndex + 1}"),
backgroundColor: Colors.indigoAccent,
elevation: 10,
),
body: Center(
child: ListView(
shrinkWrap: true,
padding: EdgeInsets.all(15.0),
children: <Widget>[
Center(
child: Card(
elevation: 0.0,
child: Container(
//padding: EdgeInsets.all(0.0),
width: double.infinity,
height: 900,
child: Column(
children: <Widget>[
Row(
children: <Widget>[
//SizedBox(width: 10.0),
Expanded(
child: Text(
HtmlUnescape().convert(
widget.questions[_currentIndex].question),
softWrap: true,
textAlign: TextAlign.justify,
style: _questionStyle,
),
),
],
),
Row(
children: <Widget>[
//SizedBox(width: 10.0),
Expanded(
child: Image.network(
HtmlUnescape().convert(
widget.questions[_currentIndex].qimgurl),
// width: 300,
fit: BoxFit.fitWidth,
loadingBuilder: (BuildContext context,
Widget child,
ImageChunkEvent loadingProgress) {
if (loadingProgress == null) return child;
return Center(
child: CircularProgressIndicator(
value: loadingProgress.expectedTotalBytes !=
null
? loadingProgress
.cumulativeBytesLoaded /
loadingProgress.expectedTotalBytes
: null,
),
);
},
)),
],
),
//SizedBox(height: 0.0),
Card(
//elevation: 10.0,
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
...options.map((option) => RadioListTile(
title: Text(
HtmlUnescape().convert("$option"),
style: TextStyle(color: Colors.black),
),
groupValue: _answers[_currentIndex],
value: option,
onChanged: (value) {
setState(() {
_answers[_currentIndex] = option;
if (i == 0) {
option1 = option;
}
if (option ==
widget.questions[_currentIndex]
.correctAnswer) {
i = 1;
Fluttertoast.cancel();
Fluttertoast.showToast(
msg: "Righ Answer",
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.BOTTOM,
timeInSecForIosWeb: 1,
backgroundColor: Colors.green,
textColor: Colors.white,
fontSize: 16.0);
} else {
i = 1;
Fluttertoast.cancel();
Fluttertoast.showToast(
msg: "Wrong Answer",
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.BOTTOM,
timeInSecForIosWeb: 1,
backgroundColor: Colors.red,
textColor: Colors.white,
fontSize: 16.0);
}
});
},
)),
],
),
),
Expanded(
child: Container(
alignment: Alignment.topCenter,
child: new Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
/* const SizedBox(height: 30),*/
/* RaisedButton(
child: Text('Hint'),
onPressed:_giveHint,
color:Colors.yellow, ),*/
const SizedBox(),
ButtonTheme(
minWidth: 200,
height: 50,
child: RaisedButton(
child: Text(_currentIndex ==
(widget.questions.length - 1)
? "Submit"
: "Next"),
onPressed: _nextSubmit,
color: Colors.yellow,
),
),
],
),
),
)
],
),
),
),
),
],
),
),
),
);
}
void _nextSubmit() {
if (_answers[_currentIndex] == null) {
_key.currentState.showSnackBar(SnackBar(
content: Text("You must select an answer to continue."),
));
return;
}
if (_currentIndex < (widget.questions.length - 1)) {
_answers[_currentIndex] = option1;
showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: Text('Answer is'),
content: Text(widget.questions[_currentIndex].correctAnswer),
actions: <Widget>[
FlatButton(
child: Text('Ok'),
onPressed: () {
Navigator.of(context).pop();
setState(() {
_currentIndex++;
i = 0;
});
},
),
],
);
});
} else {
Navigator.of(context).pushReplacement(MaterialPageRoute(
builder: (_) => QuizFinishedPage(
questions: widget.questions, answers: _answers)));
}
}
Future<bool> _onWillPop() async {
return showDialog<bool>(
context: context,
builder: (_) {
return AlertDialog(
content: Text(
"Are you sure you want to quit the quiz? All your progress will be lost."),
title: Text("Warning!"),
actions: <Widget>[
FlatButton(
child: Text("Yes"),
onPressed: () {
Navigator.pop(context, true);
},
),
FlatButton(
child: Text("No"),
onPressed: () {
Navigator.pop(context, false);
},
),
],
);
});
}
}
There is an activeColor property in RadioListTile which lets you change color of the tile when it's selected.You can add a condition using ternary operator as follows to do the work for you:
activeColor: (option ==
widget.questions[_currentIndex]
.correctAnswer) ? Colors.green : Colors.red,
Complete Code:
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:mechanicalaptitude/quiz/models/category.dart';
import 'package:mechanicalaptitude/quiz/models/question.dart';
import 'package:mechanicalaptitude/quiz/ui/pages/quiz_finished.dart';
import 'package:html_unescape/html_unescape.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:admob_flutter/admob_flutter.dart';
class QuizPage extends StatefulWidget {
final List<Question> questions;
final Category category;
const QuizPage({Key key, #required this.questions, this.category})
: super(key: key);
#override
_QuizPageState createState() => _QuizPageState();
}
class _QuizPageState extends State<QuizPage> {
final TextStyle _questionStyle = TextStyle(
fontSize: 18.0, //font size of the questions
fontWeight: FontWeight.bold,
color: Colors.red);
int _currentIndex = 0;
int i = 0;
int hint_index = 0;
var option1;
final Map<int, dynamic> _answers = {};
final GlobalKey<ScaffoldState> _key = GlobalKey<ScaffoldState>();
#override
Widget build(BuildContext context) {
Question question = widget.questions[_currentIndex];
final List<dynamic> options = question.incorrectAnswers;
if (!options.contains(question.correctAnswer)) {
options.add(question.correctAnswer);
//options.shuffle();
}
return WillPopScope(
onWillPop: _onWillPop,
child: Scaffold(
key: _key,
appBar: AppBar(
title: Text("Question No. - " + "${_currentIndex + 1}"),
backgroundColor: Colors.indigoAccent,
elevation: 10,
),
body: Center(
child: ListView(
shrinkWrap: true,
padding: EdgeInsets.all(15.0),
children: <Widget>[
Center(
child: Card(
elevation: 0.0,
child: Container(
//padding: EdgeInsets.all(0.0),
width: double.infinity,
height: 900,
child: Column(
children: <Widget>[
Row(
children: <Widget>[
//SizedBox(width: 10.0),
Expanded(
child: Text(
HtmlUnescape().convert(
widget.questions[_currentIndex].question),
softWrap: true,
textAlign: TextAlign.justify,
style: _questionStyle,
),
),
],
),
Row(
children: <Widget>[
//SizedBox(width: 10.0),
Expanded(
child: Image.network(
HtmlUnescape().convert(
widget.questions[_currentIndex].qimgurl),
// width: 300,
fit: BoxFit.fitWidth,
loadingBuilder: (BuildContext context,
Widget child,
ImageChunkEvent loadingProgress) {
if (loadingProgress == null) return child;
return Center(
child: CircularProgressIndicator(
value: loadingProgress.expectedTotalBytes !=
null
? loadingProgress
.cumulativeBytesLoaded /
loadingProgress.expectedTotalBytes
: null,
),
);
},
)),
],
),
//SizedBox(height: 0.0),
Card(
//elevation: 10.0,
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
...options.map((option) => RadioListTile(
title: Text(
HtmlUnescape().convert("$option"),
style: TextStyle(color: Colors.black),
),
activeColor: (option ==
widget.questions[_currentIndex]
.correctAnswer) ? Colors.green : Colors.red,
groupValue: _answers[_currentIndex],
value: option,
onChanged: (value) {
setState(() {
_answers[_currentIndex] = option;
if (i == 0) {
option1 = option;
}
if (option ==
widget.questions[_currentIndex]
.correctAnswer) {
i = 1;
Fluttertoast.cancel();
Fluttertoast.showToast(
msg: "Righ Answer",
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.BOTTOM,
timeInSecForIosWeb: 1,
backgroundColor: Colors.green,
textColor: Colors.white,
fontSize: 16.0);
} else {
i = 1;
Fluttertoast.cancel();
Fluttertoast.showToast(
msg: "Wrong Answer",
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.BOTTOM,
timeInSecForIosWeb: 1,
backgroundColor: Colors.red,
textColor: Colors.white,
fontSize: 16.0);
}
});
},
)),
],
),
),
Expanded(
child: Container(
alignment: Alignment.topCenter,
child: new Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
/* const SizedBox(height: 30),*/
/* RaisedButton(
child: Text('Hint'),
onPressed:_giveHint,
color:Colors.yellow, ),*/
const SizedBox(),
ButtonTheme(
minWidth: 200,
height: 50,
child: RaisedButton(
child: Text(_currentIndex ==
(widget.questions.length - 1)
? "Submit"
: "Next"),
onPressed: _nextSubmit,
color: Colors.yellow,
),
),
],
),
),
)
],
),
),
),
),
],
),
),
),
);
}
void _nextSubmit() {
if (_answers[_currentIndex] == null) {
_key.currentState.showSnackBar(SnackBar(
content: Text("You must select an answer to continue."),
));
return;
}
if (_currentIndex < (widget.questions.length - 1)) {
_answers[_currentIndex] = option1;
showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: Text('Answer is'),
content: Text(widget.questions[_currentIndex].correctAnswer),
actions: <Widget>[
FlatButton(
child: Text('Ok'),
onPressed: () {
Navigator.of(context).pop();
setState(() {
_currentIndex++;
i = 0;
});
},
),
],
);
});
} else {
Navigator.of(context).pushReplacement(MaterialPageRoute(
builder: (_) => QuizFinishedPage(
questions: widget.questions, answers: _answers)));
}
}
Future<bool> _onWillPop() async {
return showDialog<bool>(
context: context,
builder: (_) {
return AlertDialog(
content: Text(
"Are you sure you want to quit the quiz? All your progress will be lost."),
title: Text("Warning!"),
actions: <Widget>[
FlatButton(
child: Text("Yes"),
onPressed: () {
Navigator.pop(context, true);
},
),
FlatButton(
child: Text("No"),
onPressed: () {
Navigator.pop(context, false);
},
),
],
);
});
}
}

Prevent keyboard from appearing on Flutter

I made this very simple aplication but im having a problem with it.
On every action that i do (like deleting something) the keyboard opens automatically.
I want to avoid that, and open the keyboard only when i click on the text form field (line 178 on code).
How can i do that?
I know this is something very simple to make, i have tried some things using focusnode, trying to disable the autofocus, but i didnt could make it work the way i need.
import 'dart:convert';
import 'dart:ffi';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:path_provider/path_provider.dart';
import 'package:http/http.dart' as http;
void main() {
runApp(MaterialApp(
home: Pedidos(),
));
}
class Pedidos extends StatefulWidget {
#override
_PedidosState createState() => _PedidosState();
}
class _PedidosState extends State<Pedidos> with TickerProviderStateMixin {
TabController _tabController;
final _pecasController = TextEditingController();
List _pecasList = [];
var _firstPress = true;
#override
void initState() {
super.initState();
_tabController = new TabController(length: 3, vsync: this);
}
void _addPecas() {
if ((_pecasController.text.isEmpty) ||
((_pecasController.text.trimLeft() == ("")))) {
print("Campo Vazio");
} else {
setState(() {
Map<String, dynamic> newPeca = Map();
newPeca["title"] = _pecasController.text.trimLeft();
//newPeca["ok"] = false;
_pecasController.text = "";
_pecasList.add(newPeca);
// _saveData();
print(_pecasList);
});
}
}
void _enviar() {
if (_pecasList.length < 1) {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: new Text("Lista vazia"),
actions: <Widget>[
new FlatButton(
child: new Text("Fechar"),
onPressed: () {
Navigator.of(context).pop();
}),
]);
});
} else {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: new Text("Deseja enviar os itens?"),
actions: <Widget>[
new FlatButton(
child: new Text("Fechar"),
onPressed: () {
Navigator.of(context).pop();
}),
new FlatButton(
child: new Text("Enviar"),
onPressed: () async {
Map<String, String> headers = new Map<String, String>();
headers["Content-type"] = "application/json";
headers["Accept"] = "application/json";
//String str = '{"take":55, "skip":"0"}';
final resp = await http.post('http://172.16.14.109:5000/',
//body: str,
body: jsonEncode(_pecasList),
headers: headers);
if (resp.statusCode == 200) {
if (resp.body == "ok") {
setState(() {
print(_pecasList);
_pecasList.clear();
Navigator.of(context).pop();
});
} else {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: new Text(
"Erro: entre em contato com o suporte."),
actions: <Widget>[
new FlatButton(
child: new Text("Fechar"),
onPressed: () {
Navigator.of(context).pop();
Navigator.of(context).pop();
}),
]);
});
}
}
})
],
);
},
);
}
}
void _apagarTudo() {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: new Text("Deseja limpar a lista?"),
actions: <Widget>[
new FlatButton(
child: new Text("Fechar"),
onPressed: () {
Navigator.of(context).pop();
}),
new FlatButton(
child: new Text("Limpar"),
onPressed: () {
setState(() {
_pecasList.clear();
Navigator.of(context).pop();
});
}),
]);
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(
"Solicitação de Peças",
style: TextStyle(fontWeight: FontWeight.bold),
),
centerTitle: true,
backgroundColor: Colors.green,
),
body: Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: <Widget>[
Expanded(
flex: 8,
child: TextFormField(
controller: _pecasController,
keyboardType: TextInputType.text,
style: TextStyle(
color: Colors.black,
fontSize: 18,
),
decoration: InputDecoration(
hintText: ("Adicionar item"),
),
),
),
Padding(
padding: EdgeInsets.only(right: 15),
),
Expanded(
flex: 2,
child: RaisedButton(
child: Icon(Icons.add, color: Colors.amber),
color: Colors.green,
onPressed: _addPecas,
),
)
],
),
),
Divider(
height: 02.0,
),
Expanded(
child: ListView.builder(
itemCount: _pecasList.length,
itemBuilder: (context, index) {
return ListTile(
dense: true,
key:
Key(DateTime.now().millisecondsSinceEpoch.toString()),
title: Text(
_pecasList[index]["title"],
style: TextStyle(fontSize: 15.0),
),
trailing: Icon(
Icons.delete_forever,
color: Colors.redAccent,
),
onLongPress: () {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title:
new Text("Deseja remover o item da lista?"),
actions: <Widget>[
new FlatButton(
child: new Text("Fechar"),
onPressed: () {
Navigator.of(context).pop();
},
),
new FlatButton(
child: new Text("Excluir"),
onPressed: () {
_pecasList.removeAt(index);
setState(() {
Navigator.of(context).pop();
});
},
),
],
);
},
);
});
}),
),
Row(
mainAxisAlignment: (MainAxisAlignment.center),
children: <Widget>[
Padding(
padding: const EdgeInsets.all(10.0),
child: RaisedButton(
color: Colors.green,
padding: EdgeInsets.all(5.0),
child: Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Padding(
padding: const EdgeInsets.all(4.0),
child: Icon(
Icons.send,
color: Colors.white,
),
),
Padding(
padding: const EdgeInsets.all(2.0),
child: Text(
"Enviar",
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
),
),
),
],
),
onPressed: _enviar,
)),
Padding(
padding: const EdgeInsets.all(10.0),
child: RaisedButton(
color: Colors.redAccent,
padding: EdgeInsets.all(5.0),
child: Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Padding(
padding: const EdgeInsets.all(4.0),
child: Icon(
Icons.delete,
color: Colors.white,
),
),
Padding(
padding: const EdgeInsets.all(2.0),
child: Text(
"Limpar",
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
),
),
),
],
),
onPressed: () {
_apagarTudo();
}))
],
)
],
),
);
}
}
Try these changes.
I have controlled enabled field of TextFormField. The TextFormField is disabled when you click on RaisedButton to add the item to list. And TextFormField is enabled when you click on itself.
void _addPecas() {
disableTextFormField();
...
}
bool textFormFieldEnabled = true;
void enableTextFormField(){
setState(() {
textFormFieldEnabled = true;
});
}
void disableTextFormField(){
setState(() {
textFormFieldEnabled = false;
});
}
Widget build(BuildContext context) {
....
child: TextFormField(
controller: _pecasController,
keyboardType: TextInputType.text,
enabled: textFormFieldEnabled,
onTap: () => enableTextFormField(),
style: TextStyle(
color: Colors.black,
fontSize: 18,
),
decoration: InputDecoration(
hintText: ("Adicionar item"),
),
),
...
}