How to clear Flutter Text Field from parent widget - flutter

How to clear Flutter Text Field from parent widget
I am a newbie for flutter and dart. I am developing a calculator type application.
I want to clear the text field in the TextFieldContainer1 class from my parent widget Calculator method using method function.
This is the parent widget (Calculator) which contains reset function.
class Calculator extends StatefulWidget {
#override
_CalculatorState createState() => _CalculatorState();
}
class _CalculatorState extends State<Calculator> {
double soldPrice=0.00;
reset(){
soldPrice=0.00;
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: BgColor ,
bottomNavigationBar: Container(
decoration: BoxDecoration(
borderRadius:BorderRadius.only(topLeft: Radius.circular(10), topRight:Radius.circular(10) ),
color:YellowBg,
),
alignment: Alignment.center,
height: 50,
child: Text('RESET',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.w500,
letterSpacing: 5,
),
),
),
body: SafeArea(
child: Column(
children: <Widget>[
SizedBox(height:10),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
EcalLogo(logoSize: 30,),
],
),
SizedBox(height:10),
Padding(
padding:EdgeInsets.symmetric(horizontal:10.0),
child:FractionallySizedBox(
widthFactor: 0.9,
child: Container(
height:1.0,
width:130.0,
color:Colors.white,),
),),
SizedBox(height: 10,),
Expanded(
child:ListView(
children: <Widget>[
TextFieldContainer1(
title: 'SOLD PRICE',
tagLine: "SALE PRICE WITOHUT SHIPPING",
icon: Icons.check_circle,
onChange: (val) => setState(() {
soldPrice = double.parse(val);
})
),
],
))
],
),
)
);
}
}
This is the child widget class(TextFieldContainer1)
class TextFieldContainer1 extends StatefulWidget {
final String title;
final String tagLine;
final IconData icon;
final Function(String) onChange;
// Function displayFunction;
TextFieldContainer1({this.title,this.tagLine,this.icon,this.onChange});
#override
_TextFieldContainer1State createState() => _TextFieldContainer1State();
}
class _TextFieldContainer1State extends State<TextFieldContainer1> {
#override
Widget build(BuildContext context) {
return FractionallySizedBox(
widthFactor: 0.95,
child: Container(
padding: EdgeInsets.symmetric(horizontal:20, vertical:5),
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(10)),
color: tileBackground,
),
height: 57,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children:<Widget>[
Container(
child:Column(
children:<Widget>[
Row(
children:<Widget>[
Icon(widget.icon,
color:Color.fromRGBO(255, 255, 255, 0.7),
size:20
),
SizedBox(width:15),
Text(widget.title,
style: TextStyle(
fontSize: 20,
color:Colors.white,
fontWeight: FontWeight.w500
),
)
]
),
Text(widget.tagLine,
style: TextStyle(
color:Color.fromRGBO(255, 255, 255, 0.5),
fontSize: 12
),
)
]
)
),
Container(
padding: EdgeInsets.symmetric(horizontal: 15,vertical: 5),
decoration: BoxDecoration(
color: Color.fromRGBO(252, 205, 0, 0.2),
borderRadius: BorderRadius.all(Radius.circular(10)
)
),
height: 40,
width: 92,
child: TextField(
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.white,
fontSize: 20
),
autofocus: false,
decoration:InputDecoration(
focusColor: YellowBg,
fillColor: YellowBg,
hoverColor: YellowBg,
enabledBorder: UnderlineInputBorder(
borderSide: BorderSide(color: YellowBg),
),
focusedBorder: UnderlineInputBorder(
borderSide: BorderSide(color: YellowBg),)
) ,
keyboardType: TextInputType.number,
onChanged: widget.onChange,
),
)
],
),
),
);
}
}
How to clear the text field in the TextFieldContainer1 class from my parent widget Calculator using the reset function?

make your text field accept a controller:
class TextFieldContainer1 extends StatefulWidget {
final String title;
final String tagLine;
final IconData icon;
final Function(String) onChange;
final TextEditingController controller;
// Function displayFunction;
TextFieldContainer1({this.title,this.tagLine,this.icon,this.onChange,
this.controller});
#override
_TextFieldContainer1State createState() => _TextFieldContainer1State();
}
class _TextFieldContainer1State extends State<TextFieldContainer1> {
// also don't forget to dispose the controller
#override
void dispose() {
super.dispose();
_controller.dispose();
}
}
and use it in your widget like this:
class Calculator extends StatefulWidget {
#override
_CalculatorState createState() => _CalculatorState();
}
class _CalculatorState extends State<Calculator> {
final _controller = TextEditingController();
double soldPrice=0.00;
reset(){
soldPrice=0.00;
}
#override
Widget build(BuildContext context) {
// ....
TextFieldContainer1(
title: 'SOLD PRICE',
tagLine: "SALE PRICE WITOHUT SHIPPING",
icon: Icons.check_circle,
controller: _controller,
onChange: (val) => setState(() {
soldPrice = double.parse(val);
}),
),
],
))
void reset() => _controller.clear();
// ....

Related

Adding values from multiple textFields

I have a list of tiles created with the 'tolist' method, each has a textField and controller.I want to get the sum of the values of all textFields into a variable and display as text.``
here is my code: `
class MyHomePage extends StatefulWidget {
const MyHomePage({
Key? key,
}) : super(key: key);
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
List<String> myList = [
'Materials',
'Labour',
'Plant and Equipment',
'Subcontractor'
];
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
),
body: SingleChildScrollView(
child: Column(
children: [
ExpansionTile(
maintainState: true,
title: Row(mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: const [
Text('Test Code'),
Text('sum of all here',//sum of all values from each textfield here
style: TextStyle(fontSize: 16),),
],
),
children: myList.map((cost) {
return MyListTile(cost);
}).toList(),
),
],
),
));
}
}
and MyListTile code :``
class MyListTile extends StatefulWidget {
String title;
MyListTile(this.title) : super();
#override
State<MyListTile> createState() => _MyListTileState();
}
class _MyListTileState extends State<MyListTile> {
final TextEditingController _myController = TextEditingController();
double materialCost = 0.0;
#override
Widget build(BuildContext context) {
return ListTile(
subtitle: Row(
children: [
Container(
margin: const EdgeInsets.only(top: 5, bottom: 5, right: 0, left: 0),
child: SizedBox(
height: 35,
width: 150,
child: TextField(
textAlignVertical: TextAlignVertical.center,
controller: _myController,
showCursor: true,
keyboardType: TextInputType.number,
decoration: InputDecoration(
contentPadding: const EdgeInsets.only(left: 10),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(15)),
disabledBorder: const OutlineInputBorder(),
filled: true,
labelText: 'Cost sum',
labelStyle: TextStyle(color: Colors.grey[500]),
hintText: 'Enter Cost',
hintStyle: TextStyle(color: Colors.grey[500]),
suffixIcon: InkWell(
child: const Icon(
Icons.clear,
),
onTap: () {
_myController.clear();
},
),
// isCollapsed: true,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(15))),
),
),
),
Container(
margin: const EdgeInsets.all(3),
padding: const EdgeInsets.all(3),
decoration: BoxDecoration(
border: Border.all(color: Colors.white10, width: 1),
borderRadius: BorderRadius.circular(12)),
child: InkWell(
onTap: () {
setState(() {
materialCost = double.parse(_myController.text);
});
},
child: const Icon(
Icons.done,
),
),
)
],
),
trailing: Column(
children: [
Container(
margin: const EdgeInsets.all(3),
padding: const EdgeInsets.all(3),
decoration: BoxDecoration(
color: Colors.white, borderRadius: BorderRadius.circular(10)),
child: Text(
materialCost.toString(),
style: const TextStyle(
// color: mainColorShade,
fontSize: 14,
fontWeight: FontWeight.bold),
),
)
],
),
title: Text(
widget.title,
),
);
;
}
}
I have tried to find a solution from allover the internet and I can not get any
example
create textControllers for each of your textfields and pass it to your textfield inside your listTile:
class MyHomePage extends StatefulWidget {
...
}
class _MyHomePageState extends State<MyHomePage> {
List<String> myList = [
'Materials',
'Labour',
'Plant and Equipment',
'Subcontractor'
];
// look here: list of controllers for your need change it for your liking
List<TextEditingController> controllers = [
TextEditingController(),
TextEditingController(),
TextEditingController(),
TextEditingController(),
];
// look here: local state to store your sum of textfields
String sum = "";
#override
void initState() {
super.initState();
// look here: this will change sum value whenever either of the textfield's value changed
for (var i = 0; i < myList.length; i++) {
controllers[i].addListener(() {
setState(() {
sum = getSum(controllers);
});
});
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
),
body: SingleChildScrollView(
child: Column(
children: [
ExpansionTile(
maintainState: true,
title: Row(mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text('Test Code'),
// look here: this is your sum text
Text(sum,style: TextStyle(fontSize: 16),),
],
),
children: [
// look here: pass the controllers to your mylistTile widgets
for (var i = 0; i < myList.length; i++)
MyListTile(
title: cost,
controller: controllers[i],
),
],
),
],
),
));
}
// if you want to change the sum result, change it here
String getSum(List<TextEditingController> controllers) {
return controllers.map((e) => "${e.text} ").toString();
}
}
Don't forget to do this in your MyListTile widget, otherwise you can't pass the controllers
class MyListTile extends StatefulWidget {
MyListTile({
required this.title,
required this.controller
}) : super();
final String title;
final TextEditingController controller;
#override
State<MyListTile> createState() => _MyListTileState();
}
Use widget.controller in your MyListTile instead of _myController
class _MyListTileState extends State<MyListTile> {
final TextEditingController _myController = TextEditingController();
double materialCost = 0.0;
#override
Widget build(BuildContext context) {
return ListTile(
subtitle: Row(
children: [
Container(
margin: const EdgeInsets.only(top: 5, bottom: 5, right: 0, left: 0),
child: SizedBox(
height: 35,
width: 150,
child: TextField(
textAlignVertical: TextAlignVertical.center,
// look here:
controller: widget.controller,
...
// rest of your code here

How to manage a custom widget state in SingleChildScrollView Widget

I'm trying to design this view.
I already have the basic design of the cards, but i would like to know how to change the card's background color, the card's border color and add the little green square according to the width size of the current card when the user click one of them. It's important to know that only one card can be painted in green when the user clicked it.
Here is my code:
CategoryCardModel
class CategoryCardModel {
final String? categoryCardModelName;
CategoryCardModel(this.categoryCardModelName);
}
CategoryCard
import 'dart:ffi';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
class CategoryCard extends StatelessWidget {
final String? categoryCardName;
final Function()? wasPressed;
const CategoryCard({
super.key,
required this.categoryCardName,
this.wasPressed,
});
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: wasPressed,
child: Card(
shape: RoundedRectangleBorder(
side: const BorderSide(
color: Color.fromRGBO(212, 213, 215, 100),
width: 3,
),
borderRadius: BorderRadius.circular(20.0),
),
child: Container(
decoration: BoxDecoration(
color: const Color.fromRGBO(242, 243, 243, 100),
borderRadius: BorderRadius.circular(20.0)),
padding: const EdgeInsets.all(10),
child: Text(
categoryCardName ?? 'Todas',
style: const TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold,
color: Color.fromRGBO(91, 94, 99, 100)),
),
),
),
);
}
}
MyHomePage
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'category_card.dart';
import 'category_card_model.dart';
class MyHomePage extends StatefulWidget {
MyHomePage({super.key, required this.title});
final String title;
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
// List of models
final categoryCardModelList = <CategoryCardModel>[
CategoryCardModel("Todas"),
CategoryCardModel("Smartphones"),
CategoryCardModel("Accesorios para celular"),
CategoryCardModel("TV")
];
List<CategoryCardModel>? _categoryCardModelListOf;
#override
void initState() {
super.initState();
setState(() {
_categoryCardModelListOf = List.of(categoryCardModelList);
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: SingleChildScrollView(
scrollDirection: Axis.horizontal,
padding: const EdgeInsets.fromLTRB(10.0, 0.0, 10.0, 0.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: _categoryCardModelListOf!
.map<Widget>((categoryCardModel) => CategoryCard(
wasPressed: () {
print("Hello World");
setState(() {});
},
categoryCardName:
categoryCardModel.categoryCardModelName))
.toList())));
}
}
main
import 'package:flutter/material.dart';
import 'my_home_page.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: "Caregory Cards"),
);
}
}
Selected is needed for Card
class CategoryCard extends StatelessWidget {
final String? categoryCardName;
final Function()? wasPressed;
final bool isActive;
const CategoryCard(
{super.key,
required this.categoryCardName,
this.wasPressed,
this.isActive = false});
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: wasPressed,
child: Card(
shape: const StadiumBorder(),
child: Container(
decoration: BoxDecoration(
color: (isActive ? Colors.green : Colors.grey).withOpacity(.1),
borderRadius: BorderRadius.circular(24.0),
border: Border.all(
width: 2, color: isActive ? Colors.green : Colors.grey)),
padding: const EdgeInsets.all(10),
child: Text(
categoryCardName ?? 'Todas',
style: const TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold,
color: Color.fromRGBO(91, 94, 99, 100)),
),
),
),
);
}
}
Create a state variable for selected model
CategoryCardModel? activeTab;
And use
children: _categoryCardModelListOf!
.map<Widget>((categoryCardModel) => CategoryCard(
isActive: activeTab == categoryCardModel,
wasPressed: () {
activeTab = categoryCardModel;
setState(() {});
},
categoryCardName: categoryCardModel.categoryCardModelName))
.toList(),
),
Update your CategoryCard class like this, you may need to change the color according to your desire :
class CategoryCard extends StatelessWidget {
final String? categoryCardName;
final Function()? wasPressed;
final bool isSelected;
const CategoryCard({
super.key,
required this.categoryCardName,
this.wasPressed,
this.isSelected = false,
});
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: wasPressed,
child: Card(
shape: RoundedRectangleBorder(
side: BorderSide(
color: isSelected ? Colors.green : Color.fromRGBO(212, 213, 215, 100),
width: 3,
),
borderRadius: BorderRadius.circular(20.0),
),
child: Container(
decoration: BoxDecoration(
color: isSelected ? Colors.greenAccent : const Color.fromRGBO(242, 243, 243, 100),
borderRadius: BorderRadius.circular(20.0),
),
padding: const EdgeInsets.all(10),
child: Text(
categoryCardName ?? 'Todas',
style: const TextStyle(fontSize: 25, fontWeight: FontWeight.bold, color: Color.fromRGBO(91, 94, 99, 100)),
),
),
),
);
}
}
And then change your _MyHomePageState class to this :
class _MyHomePageState extends State<MyHomePage> {
// List of models
final categoryCardModelList = <CategoryCardModel>[
CategoryCardModel("Todas"),
CategoryCardModel("Smartphones"),
CategoryCardModel("Accesorios para celular"),
CategoryCardModel("TV")
];
List<CategoryCardModel>? _categoryCardModelListOf;
CategoryCardModel? _selectedCardModel;
#override
void initState() {
super.initState();
setState(() {
_categoryCardModelListOf = List.of(categoryCardModelList);
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: SingleChildScrollView(
scrollDirection: Axis.horizontal,
padding: const EdgeInsets.fromLTRB(10.0, 0.0, 10.0, 0.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: _categoryCardModelListOf!
.map<Widget>((categoryCardModel) => CategoryCard(
wasPressed: () {
print("Hello World");
setState(() {
_selectedCardModel = categoryCardModel;
});
},
categoryCardName: categoryCardModel.categoryCardModelName,
isSelected: _selectedCardModel == categoryCardModel,
))
.toList(),
),
),
);
}
}
Use above two answers for highlighting selected option...and here is what missing...
The underline below selected tab...
for that update your category card as below,
as u have mentioned underline width must be in size of tab width,
I have used ** IntrinsicWidth**
class CategoryCard extends StatelessWidget {
final String? categoryCardName;
final Function()? wasPressed;
final bool? isselected;
const CategoryCard({
super.key,
required this.categoryCardName,
this.wasPressed,
this.isselected=false
});
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: wasPressed,
child: IntrinsicWidth(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 10),
child: Column(children: [
Card(
shape: RoundedRectangleBorder(
side: BorderSide(
color:isselected==true?Colors.red: Color.fromRGBO(212, 213, 215, 100),
width: 3,
),
borderRadius: BorderRadius.circular(20.0),
),
child: Container(
decoration: BoxDecoration(
color: const Color.fromRGBO(242, 243, 243, 100),
borderRadius: BorderRadius.circular(20.0)),
padding: const EdgeInsets.all(10),
child: Text(
categoryCardName ?? 'Todas',
style: const TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold,
color: Color.fromRGBO(91, 94, 99, 100)),
),
),
),
if(isselected==true)
Padding(
padding: EdgeInsets.symmetric(horizontal: 20),
child: Container(
color: Colors.red[200],
height: 5,
),
),
],),
),
),
);
}
}

Pass Value between two class in Flutter

How can pass two String between two class? I have a Signin Class where i have two TextField for email and password. Then I have a Button class but I don't know how get email and password String.
I would not create a single class to keep tidy my code.
This is my code:
SigninClass
import 'package:cleverpot/Activity/home.dart';
import 'package:cleverpot/Helper/authelper.dart';
import 'package:cleverpot/signin/signout/Header.dart';
import 'package:cleverpot/signin/signout/InputField.dart';
import 'package:cleverpot/signin/signout/InputWrapper.dart';
import 'package:flutter/material.dart';
import 'package:firebase_auth/firebase_auth.dart';
class Signup extends StatefulWidget {
Signup({Key? key}) : super(key: key);
#override
_nameState createState() => _nameState();
}
class _nameState extends State<Signup> {
String email = "";
String password = "";
authHelper _helper = authHelper();
#override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: false,
body: Container(
width: double.infinity,
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
colors: [Colors.green, Colors.greenAccent])),
child: Column(
children: [
SizedBox(
height: 80,
),
Header(),
Expanded(
child: Container(
decoration: BoxDecoration(
color: Colors.green[300],
borderRadius: BorderRadius.only(
topLeft: Radius.circular(60),
topRight: Radius.circular(60))),
child: InputWrapper(),
))
],
),
),
);
}
}
InputWrapper Class:
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'Button.dart';
import 'InputField.dart';
class InputWrapper extends StatefulWidget {
InputWrapper({Key? key}) : super(key: key);
#override
_InputWrapperState createState() => _InputWrapperState();
}
class _InputWrapperState extends State<InputWrapper> {
String email = '';
String password = '';
#override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.all(30),
child: Column(
children: <Widget>[
SizedBox(
height: 20,
),
Container(
decoration: BoxDecoration(
color: Colors.white, borderRadius: BorderRadius.circular(10)),
child: InputField(),
),
SizedBox(
height: 20,
),
RichText(
text: TextSpan(
text: "Password dimenticata?",
style: TextStyle(color: Colors.grey),
recognizer: TapGestureRecognizer()
..onTap = () {
print("Cliccato");
})),
SizedBox(
height: 20,
),
Button(),
SizedBox(
height: 20,
),
Container(
decoration: BoxDecoration(
color: Colors.green[500],
borderRadius: BorderRadius.circular(50)),
child: RichText(
text: TextSpan(
text: "Non sei registrato? Clicca qua",
style: TextStyle(color: Colors.black),
recognizer: TapGestureRecognizer()
..onTap = () {
Navigator.of(context).push(PageRouteBuilder(
opaque: false,
pageBuilder: (BuildContext context, _, __) {
return Registration();
}));
print("Cliccato");
})),
),
],
),
);
}
InputField Class:
import 'package:flutter/material.dart';
class InputField extends StatefulWidget {
InputField({Key? key}) : super(key: key);
#override
_InputFieldState createState() => _InputFieldState();
}
class _InputFieldState extends State<InputField> {
String password = '';
String email = '';
String getil() {
return password;
}
#override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
Container(
padding: EdgeInsets.all(10),
decoration: BoxDecoration(
border: Border(bottom: BorderSide(color: Color(4294638330)))),
child: TextField(
decoration: InputDecoration(
hintText: "Enter your email",
hintStyle: TextStyle(color: Colors.grey),
border: InputBorder.none),
),
),
Container(
padding: EdgeInsets.all(10),
decoration: BoxDecoration(
border: Border(bottom: BorderSide(color: Color(4294638330)))),
child: TextField(
onChanged: (value) {
setState(() {
password = value;
print(password);
});
},
decoration: InputDecoration(
hintText: "Enter your password",
hintStyle: TextStyle(color: Colors.grey),
border: InputBorder.none),
),
),
],
);
;
}
}
And Button Class:
import 'package:cleverpot/Helper/authelper.dart';
import 'package:cleverpot/signin/signout/InputField.dart';
import 'package:flutter/material.dart';
class Button extends StatelessWidget {
authHelper _helper = authHelper();
#override
Widget build(BuildContext context) {
return Container(
height: 50,
margin: EdgeInsets.symmetric(horizontal: 50),
decoration: BoxDecoration(
color: Colors.cyan[500],
borderRadius: BorderRadius.circular(10),
),
child: Center(
child: ElevatedButton(
onPressed: () {
print(fieldState.getil());
},
child: Text(
"Accedi",
style: TextStyle(
color: Colors.white, fontSize: 15, fontWeight: FontWeight.bold),
),
),
),
);
}
}
I have to get Email and Password from InputField in InputWrapper and put inside Button Class in InputWrapper
You should Lift your state up. This is a general advice in flutter, the state variables should be contained in a stateful widget which is common to every widget you want to share the variables to.
In your case something like this:
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
class Signup extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: false,
body: Container(
width: double.infinity,
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter, colors: [Colors.green, Colors.greenAccent])),
child: Column(
children: [
SizedBox(
height: 80,
),
Header(),
Expanded(
child: Container(
decoration: BoxDecoration(
color: Colors.green[300],
borderRadius: BorderRadius.only(
topLeft: Radius.circular(60), topRight: Radius.circular(60))),
child: InputWrapper(),
),
),
],
),
),
);
}
}
class InputWrapper extends StatefulWidget {
InputWrapper({Key? key}) : super(key: key);
#override
_InputWrapperState createState() => _InputWrapperState();
}
class _InputWrapperState extends State<InputWrapper> {
String email = '';
String password = '';
#override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.all(30),
child: Column(
children: <Widget>[
SizedBox(
height: 20,
),
Container(
decoration:
BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(10)),
child: InputField(
email: email,
password: password,
onEmailChanged: (value) => setState(() => email = value),
onPasswordChanged: (value) => setState(() => password = value),
),
),
SizedBox(
height: 20,
),
RichText(
text: TextSpan(
text: "Password dimenticata?",
style: TextStyle(color: Colors.grey),
recognizer: TapGestureRecognizer()
..onTap = () {
print("Cliccato");
})),
SizedBox(
height: 20,
),
Button(password: password),
SizedBox(
height: 20,
),
Container(
decoration: BoxDecoration(
color: Colors.green[500], borderRadius: BorderRadius.circular(50)),
child: RichText(
text: TextSpan(
text: "Non sei registrato? Clicca qua",
style: TextStyle(color: Colors.black),
recognizer: TapGestureRecognizer()
..onTap = () {
Navigator.of(context).push(
PageRouteBuilder(
opaque: false,
pageBuilder: (BuildContext context, _, __) {
return Registration();
},
),
);
print("Cliccato");
},
),
),
),
],
),
);
}
}
class InputField extends StatelessWidget {
final String email;
final String password;
final void Function(String) onEmailChanged;
final void Function(String) onPasswordChanged;
const InputField({
Key? key,
required this.email,
required this.password,
required this.onEmailChanged,
required this.onPasswordChanged,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
Container(
padding: EdgeInsets.all(10),
decoration:
BoxDecoration(border: Border(bottom: BorderSide(color: Color(4294638330)))),
child: TextField(
onChanged: onEmailChanged,
decoration: InputDecoration(
hintText: "Enter your email",
hintStyle: TextStyle(color: Colors.grey),
border: InputBorder.none,
),
),
),
Container(
padding: EdgeInsets.all(10),
decoration:
BoxDecoration(border: Border(bottom: BorderSide(color: Color(4294638330)))),
child: TextField(
onChanged: onPasswordChanged,
decoration: InputDecoration(
hintText: "Enter your password",
hintStyle: TextStyle(color: Colors.grey),
border: InputBorder.none,
),
),
),
],
);
}
}
class Button extends StatelessWidget {
final String password;
const Button({
Key? key,
required this.password,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return Container(
height: 50,
margin: EdgeInsets.symmetric(horizontal: 50),
decoration: BoxDecoration(
color: Colors.cyan[500],
borderRadius: BorderRadius.circular(10),
),
child: Center(
child: ElevatedButton(
onPressed: () {
print(password);
},
child: Text(
"Accedi",
style: TextStyle(color: Colors.white, fontSize: 15, fontWeight: FontWeight.bold),
),
),
),
);
}
}

Flutter counter not counting up

I have made this scorekeeper app for basketball. I need to count the score and show it on the application. But its stuck on 0. It probably has something to do with the setState().
If possible don't change the code too much since I need to show and explain this to my teacher.
inputPage:
class InputPage extends StatefulWidget {
#override
_InputPageState createState() => _InputPageState();
}
class _InputPageState extends State<InputPage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('basketball counter'),
),
body: Column(
children: <Widget>[
Expanded(
child: Row(children: <Widget>[Expanded(child: HoopDesign()), Text(Counter.counter.toString())] ),
),
Expanded(
child: Row(
children: <Widget>[
Expanded(
child: CardDesign1(),
),
Expanded(
child: CardDesign3(),
),
Expanded(
child: CardDesign2(),
),
],
)),
Expanded(
child: Row(
children: <Widget>[
Expanded(
child: CardDesign6(),
),
Expanded(
child: CardDesign4(),
),
Expanded(
child: CardDesign5(),
),
],
),
),
Expanded(
child: Row(
children: <Widget>[
Expanded(
child: HoopDesign(),
),
],
),
),
],
),
);
}
}
Containers:
import 'package:flutter/material.dart';
import 'input_page.dart';
//#region Team1 cards
class CardDesign3 extends StatefulWidget {
#override
CardDesign3State createState() => CardDesign3State();
}
class CardDesign3State extends State<CardDesign3> {
#override
Widget build(BuildContext context) {
return InkWell(
onTap: () {
},
child: Container(
margin: EdgeInsets.all(15),
decoration: BoxDecoration(
color: Color(0xFFEF7F4D),
borderRadius: BorderRadius.circular(10),
),
child: Text(
'Vanaf de 3 punter lijn!',
textAlign: TextAlign.center,
style: TextStyle(
fontFamily: 'Bullpen3D',
fontSize: 20,
),
),
height: 100,
width: 100,
));
}
}
class CardDesign2 extends StatefulWidget {
#override
_CardDesign2State createState() => _CardDesign2State();
}
class _CardDesign2State extends State<CardDesign2> {
#override
Widget build(BuildContext context) {
return InkWell(
onTap: () {
setState(() => Counter.counter += 2);
},
child: Container(
margin: EdgeInsets.all(15),
decoration: BoxDecoration(
color: Color(0xFFEF7F4D),
borderRadius: BorderRadius.circular(10),
),
child: Text(
'Vanaf de 2 punter lijn',
textAlign: TextAlign.center,
style: TextStyle(
fontFamily: 'Bullpen3D',
fontSize: 20,
),
),
height: 100,
width: 100,
));
}
}
class CardDesign1 extends StatefulWidget {
#override
_CardDesign1State createState() => _CardDesign1State();
}
class _CardDesign1State extends State<CardDesign1> {
#override
Widget build(BuildContext context) {
return InkWell(
onTap: () {
setState(() => Counter.counter++);
},
child: Container(
margin: EdgeInsets.all(15),
decoration: BoxDecoration(
color: Color(0xFFEF7F4D),
borderRadius: BorderRadius.circular(10),
),
child: Text(
'Vanaf de 1 punter lijn',
textAlign: TextAlign.center,
style: TextStyle(
fontFamily: 'Bullpen3D',
fontSize: 20,
),
),
height: 100,
width: 100,
));
}
}
//#endregion
//#region Team2 cards
class CardDesign4 extends StatefulWidget {
#override
CardDesign4State createState() => CardDesign4State();
}
class CardDesign4State extends State<CardDesign4> {
#override
Widget build(BuildContext context) {
return InkWell(
onTap: () {
setState(() {
Counter2.counter += 3 ;
}
);
},
child: Container(
margin: EdgeInsets.all(15),
decoration: BoxDecoration(
color: Color(0xFFEF7F4D),
borderRadius: BorderRadius.circular(10),
),
child: Text(
'Vanaf de 3 punter lijn!',
textAlign: TextAlign.center,
style: TextStyle(
fontFamily: 'Bullpen3D',
fontSize: 20,
),
),
height: 100,
width: 100,
));
}
}
class CardDesign5 extends StatefulWidget {
#override
_CardDesign5State createState() => _CardDesign5State();
}
class _CardDesign5State extends State<CardDesign5> {
#override
Widget build(BuildContext context) {
return InkWell(
onTap: () {
setState(() {
Counter2.counter += 2;
});
},
child: Container(
margin: EdgeInsets.all(15),
decoration: BoxDecoration(
color: Color(0xFFEF7F4D),
borderRadius: BorderRadius.circular(10),
),
child: Text(
'Vanaf de 2 punter lijn',
textAlign: TextAlign.center,
style: TextStyle(
fontFamily: 'Bullpen3D',
fontSize: 20,
),
),
height: 100,
width: 100,
));
}
}
class CardDesign6 extends StatefulWidget {
#override
_CardDesign6State createState() => _CardDesign6State();
}
class _CardDesign6State extends State<CardDesign6> {
#override
Widget build(BuildContext context) {
return InkWell(
onTap: () {
setState(() {
Counter2.counter++;
});
},
child: Container(
margin: EdgeInsets.all(15),
decoration: BoxDecoration(
color: Color(0xFFEF7F4D),
borderRadius: BorderRadius.circular(10),
),
child: Text(
'Vanaf de 1 punter lijn',
textAlign: TextAlign.center,
style: TextStyle(
fontFamily: 'Bullpen3D',
fontSize: 20,
),
),
height: 100,
width: 100,
));
}
}
//#endregion
class HoopDesign extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
height: 100.0,
width: 100.0,
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('images/basketballhoop.jpg'),
),
shape: BoxShape.circle,
),
);
}
}
//#region Counters integers
class Counter {
static int counter = 0;
}
class Counter2 {
static int counter = 0;
}
//#endregion
Main:
import 'package:flutter/material.dart';
import 'input_page.dart';
void main() => runApp(BasketballCounter());
class BasketballCounter extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
primaryColor: Color(0xFFEE682D),
scaffoldBackgroundColor: Color(0xFFEE682D),
),
home: InputPage(),
);
}
}
What the app looks like:
(see the 0 on the side of the top hoop)
https://i.imgur.com/JwLnVaU.png
I appreciate the help :)
You need to re-render InputPage to get the new value of the counter.
Sample: (I refactored the code, refer to HalfCourt widget)
class InputPage extends StatelessWidget {
const InputPage({
Key? key,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('basketball counter'),
),
body: Column(
children: <Widget>[
const Expanded(child: HalfCourt()),
const Expanded(child: HalfCourt(isUpperSide: false)),
],
),
);
}
}
class HalfCourt extends StatefulWidget {
const HalfCourt({
this.isUpperSide = true,
Key? key,
}) : super(key: key);
final bool isUpperSide;
#override
_HalfCourtState createState() => _HalfCourtState();
}
class _HalfCourtState extends State<HalfCourt> {
int counter = 0;
#override
Widget build(BuildContext context) {
final Widget hoopAndScore = Expanded(
child: Row(
children: <Widget>[
const Expanded(child: HoopDesign()),
Text(counter.toString())
],
),
);
return Column(
children: <Widget>[
if (widget.isUpperSide) hoopAndScore,
Row(
children: <Widget>[
Expanded(
child: CardDesign(
onPressed: () => setState(() => counter++),
text: 'Vanaf de 1 punter lijn',
),
),
Expanded(
child: CardDesign(
onPressed: () => setState(() => counter += 3),
text: 'Vanaf de 3 punter lijn!',
),
),
Expanded(
child: CardDesign(
onPressed: () => setState(() => counter += 2),
text: 'Vanaf de 2 punter lijn',
),
),
],
),
if (!widget.isUpperSide) hoopAndScore
],
);
}
}
class CardDesign extends StatelessWidget {
CardDesign({
required this.onPressed,
required this.text,
Key? key,
}) : super(key: key);
final VoidCallback onPressed;
final String text;
#override
Widget build(BuildContext context) {
return InkWell(
onTap: onPressed,
child: Container(
height: 100,
width: 100,
margin: const EdgeInsets.all(15),
decoration: const BoxDecoration(
color: Color(0xFFEF7F4D),
borderRadius: BorderRadius.all(Radius.circular(10)),
),
child: Text(
text,
textAlign: TextAlign.center,
style: const TextStyle(
fontFamily: 'Bullpen3D',
fontSize: 20,
),
),
),
);
}
}
class HoopDesign extends StatelessWidget {
const HoopDesign({
Key? key,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return Container(
height: 100.0,
width: 100.0,
color: Colors.orange,
);
}
}

Flutter web, update navbar after authorization

I am trying to create a web application using flutter and I have a question. After I go through authorization, I need to change the "login" button in the navbar, as I understand it, I need to change the button text and call setState in my navbar, but in my implementation an exception is thrown.
AuthPage.dart
import 'package:flutter/material.dart';
import 'package:um/pages/home/app_color.dart';
import 'package:um/scripts/api_client.dart';
import 'package:um/scripts/locator.dart';
import 'NavBarDesktop.dart';
class AuthorizationPageDesktop extends StatefulWidget {
AuthorizationPageDesktop({Key key}) : super(key: key);
#override
_AuthorizationPageDesktopState createState() =>
_AuthorizationPageDesktopState();
}
class _AuthorizationPageDesktopState extends State<AuthorizationPageDesktop> {
TextEditingController _emailController = TextEditingController();
TextEditingController _passwordController = TextEditingController();
bool rememberMe = false;
ApiClient apiClient = ApiClient.getInstance();
ScrollController _scrollController = ScrollController();
PageController _pageController = PageController();
#override
Widget build(BuildContext context) {
return SingleChildScrollView(
child: Container(
child: Padding(
padding: EdgeInsets.only(top: 150, left: 0, right: 0),
child: Column(
children: <Widget>[
Text(
'Авторизация',
style: TextStyle(
fontWeight: FontWeight.w600,
fontSize: 28,
color: textPrimaryColor),
),
SizedBox(
height: 40,
),
_input(Icon(Icons.mail), 'Email', _emailController, false, 15),
SizedBox(
height: 15,
),
_input(Icon(Icons.lock), 'Password', _passwordController, true, 15),
SizedBox(
height: 5,
),
Container(
padding: EdgeInsets.only(left: 20, right: 20),
width: 460,
child: Theme(
data: ThemeData(
splashColor: Colors.transparent,
highlightColor: Colors.transparent,
hoverColor: Colors.transparent),
child: CheckboxListTile(
title: Text(
'Запомнить меня',
style: TextStyle(color: textPrimaryColor),
),
value: rememberMe,
onChanged: (bool value) {
setState(() {
rememberMe = value;
});
},
))),
SizedBox(
height: 5,
),
_button('Войти', auth, 15),
SizedBox(
height: 15,
),
Container(
width: 460,
child: Align(
alignment: Alignment.bottomCenter,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'Пройдите ',
style: TextStyle(color: Colors.white, fontSize: 12),
),
Text(
'регистрацию, ',
style: TextStyle(color: linkColor, fontSize: 12),
),
Text(
'если вы этого еще не сделали',
style: TextStyle(color: Colors.white, fontSize: 12),
),
],
)),
),
SizedBox(height: 50),
],
),
)));
}
Widget _input(Icon icon, String hint, TextEditingController controller,
bool obscure, double borderRadius) {
return Container(
width: 460,
height: 50,
padding: EdgeInsets.only(left: 20, right: 20),
child: TextField(
controller: controller,
obscureText: obscure,
style: TextStyle(fontSize: 16, color: Colors.white),
decoration: InputDecoration(
border: OutlineInputBorder(),
isDense: true, // Added this
contentPadding: EdgeInsets.all(8), //
hintStyle: TextStyle(
fontWeight: FontWeight.bold, fontSize: 16, color: Colors.white),
hintText: hint,
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(borderRadius),
borderSide: BorderSide(color: Colors.white, width: 2)),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(borderRadius),
borderSide: BorderSide(color: Colors.white54, width: 1)),
prefixIcon: Padding(
padding: EdgeInsets.only(left: 10, right: 10),
child: IconTheme(
data: IconThemeData(color: Colors.white),
child: icon,
),
)),
),
);
}
Widget _button(String label, void func(), double borderRadius) {
return Container(
width: 460,
padding: EdgeInsets.only(left: 20, right: 20),
child: RaisedButton(
onPressed: () {
apiClient
.authorization(_emailController.text, _passwordController.text)
.then((value) {
func();
});
},
highlightColor: Theme.of(context).primaryColor,
color: buttonPrimaryColor,
child: Text('Войти',
style: TextStyle(
fontWeight: FontWeight.bold,
color: textPrimaryColor,
fontSize: 16)),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(borderRadius)),
));
}
void auth() {
var state = navBar<NavBarDesktop>().navBarState;
state.update();
}
}
NavBar.dart
import 'package:flutter/material.dart';
import 'package:um/Widgets/Desktop/AuthPageDesktop.dart';
import 'package:um/Widgets/Desktop/HomePageDesktop.dart';
import 'package:um/Widgets/NavBarItem.dart';
import 'package:um/layout_template/layout_template.dart';
import 'package:um/pages/home/app_color.dart';
import 'package:um/scripts/api_client.dart';
import 'package:um/scripts/locator.dart';
class NavBarDesktop extends StatefulWidget {
NavBarDesktop({Key key}) : super(key: key);
GlobalKey<_NavBarDesktopState> navBarDesktop =
GlobalKey<_NavBarDesktopState>();
_NavBarDesktopState navBarState = new _NavBarDesktopState();
static _NavBarDesktopState of(BuildContext context) {
// print('_NavBarDesktopState -> ${context}');
assert(context != null);
final _NavBarDesktopState result =
// ignore: deprecated_member_use
context.ancestorStateOfType(const TypeMatcher<_NavBarDesktopState>());
// print('_NavBarDesktopState resutl -> ${result}');
return result;
}
#override
_NavBarDesktopState createState() => new _NavBarDesktopState();
}
class _NavBarDesktopState extends State<NavBarDesktop> {
String authButtonTitle = "Войти";
#override
void initState() {
print('call init state navbar ${ApiClient.username}');
if (ApiClient.username != null && ApiClient.username.length > 0)
authButtonTitle = ApiClient.username;
super.initState();
}
void update() {
setState(() {
authButtonTitle = ApiClient.username;
});
}
#override
Widget build(BuildContext context) {
return new Container(
color: primaryColor,
height: 50,
padding: EdgeInsets.only(left: 50, right: 50),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
GestureDetector(
onTap: () {
LayoutTemplate.of(context).change_page(HomePageDesktop());
},
child: Text(
'UM',
textAlign: TextAlign.center,
style: TextStyle(
color: textPrimaryColor,
fontWeight: FontWeight.w600,
fontSize: 40),
)),
NavBarItem(
authButtonTitle,
() => LayoutTemplate.of(context)
.change_page(AuthorizationPageDesktop())),
],
),
);
}
void auth_page_up(BuildContext context) {
LayoutTemplate.of(context).change_page(AuthorizationPageDesktop());
}
}
Exception
Error: setState() called in constructor: _NavBarDesktopState#5e1ee(lifecycle state: created, no widget, not mounted)
This happens when you call setState() on a State object for a widget that hasn't been inserted into the widget tree yet. It is not necessary to
call setState() in the constructor, since the state is already assumed to be dirty when it is initially created.
at Object.throw_ [as throw] (http://localhost:50572/dart_sdk.js:4334:11)
at http://localhost:50572/packages/flutter/src/widgets/widget_span.dart.lib.js:13615:23
at NavBarDesktop._NavBarDesktopState.new.setState (http://localhost:50572/packages/flutter/src/widgets/widget_span.dart.lib.js:13618:26)
at NavBarDesktop._NavBarDesktopState.new.update (http://localhost:50572/packages/um/scripts/router.dart.lib.js:1717:12)
at AuthPageDesktop._AuthorizationPageDesktopState.new.auth (http://localhost:50572/packages/um/scripts/router.dart.lib.js:1932:13)
at http://localhost:50572/packages/um/scripts/router.dart.lib.js:1926:15
at _RootZone.runUnary (http://localhost:50572/dart_sdk.js:37457:58)
at _FutureListener.then.handleValue (http://localhost:50572/dart_sdk.js:32441:29)
at handleValueCallback (http://localhost:50572/dart_sdk.js:32988:49)
at Function._propagateToListeners (http://localhost:50572/dart_sdk.js:33026:17)
at _Future.new.[_completeWithValue] (http://localhost:50572/dart_sdk.js:32869:23)
at async._AsyncCallbackEntry.new.callback (http://localhost:50572/dart_sdk.js:32891:35)
at Object._microtaskLoop (http://localhost:50572/dart_sdk.js:37718:13)
at _startMicrotaskLoop (http://localhost:50572/dart_sdk.js:37724:13)
at http://localhost:50572/dart_sdk.js:33243:9
Your _NavBarDesktopState global key needs to be initialized in your _NavBarDesktopState class., not the NavBarDesktop class. It's trying to set the global key before the state has even been created.
class NavBarDesktop extends StatefulWidget {
NavBarDesktop({Key key}) : super(key: key);
_NavBarDesktopState navBarState;
static _NavBarDesktopState of(BuildContext context) {
assert(context != null);
final _NavBarDesktopState result =
// ignore: deprecated_member_use
context.ancestorStateOfType(const TypeMatcher<_NavBarDesktopState>());
return result;
}
#override
_NavBarDesktopState createState() {
navBar.registerLazySingleton(() => this);
navBarState = _NavBarDesktopState();
return navBarState;
}
}