Flutter customize dropdown + TextFormField - flutter

How do I achieve the following look for a Row which consists of a dropdown and a TextFormField?
I am able to customize the TextFormField using the following code:
final phoneNumberBox = DecoratedBox(
decoration: const BoxDecoration(color: Color(0x2B8E8E93),
borderRadius:BorderRadius.only(
topRight: const Radius.circular(32),
bottomRight: const Radius.circular(32))),
child: phoneNumber,
);
final phoneNumber =
TextFormField(
keyboardType: TextInputType.phone,
autofocus: false,
controller: _phoneNumberController,
// validator: Validator.validateField,
decoration: InputDecoration(
contentPadding: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0),
border: OutlineInputBorder(borderRadius: new BorderRadius.only(
topRight: const Radius.circular(32),
bottomRight: const Radius.circular(32))),
),
);
However I cant figure out how to change the DropDown

far from perfect, but as an option
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(body: Content()),
);
}
}
class Content extends StatefulWidget {
#override
_ContentState createState() => _ContentState();
}
class _ContentState extends State<Content> {
final List<String> _items = ['+1', '+42', '+666', '+17', '+228'];
TextEditingController _phoneNumberController = TextEditingController();
String _value;
#override
void initState() {
super.initState();
_value = _items.first;
}
#override
Widget build(BuildContext context) {
return Center(
child: Container(
margin: const EdgeInsets.symmetric(horizontal: 32),
height: 56,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(28),
color: Colors.grey[200],
),
child: Row(
children: <Widget>[
DropdownButtonHideUnderline(
child: Container(
padding: const EdgeInsets.fromLTRB(32, 8, 16, 8),
child: DropdownButton<String>(
value: _value,
items: _items.map((value) {
return DropdownMenuItem<String>(child: Text(value), value: value);
}).toList(),
onChanged: _onDropDownChanged,
),
),
),
Container(width: 1, color: Colors.grey[300]),
Expanded(
child: TextFormField(
keyboardType: TextInputType.phone,
autofocus: false,
controller: _phoneNumberController,
decoration: InputDecoration(
contentPadding: const EdgeInsets.fromLTRB(16, 16, 8, 16),
border: InputBorder.none,
suffixIcon: Padding(
child: Icon(Icons.cancel, color: Colors.grey[400]),
padding: const EdgeInsets.only(right: 16),
),
),
),
),
],
),
),
);
}
void _onDropDownChanged(String value) {
setState(() {
_value = value;
});
}
}

Related

Validate Elevated Button in Flutter

I'm making an app using Flutter which calculates motor vehicle tax.
It calculates it perfectly fine when I enter the cost of vehicle.
But I want to add a validation to it. When I don't enter any cost of vehicle and keeps it empty and then click the calculate button, I want it show - please enter the cost.
How do I add this validation as this is not a form.
Here is the code of that part:
TextField(
controller: costController,
decoration: const InputDecoration(labelText: "Cost of Vehicle"),
keyboardType: TextInputType.number,
inputFormatters: <TextInputFormatter>[
FilteringTextInputFormatter.digitsOnly
],
),
const SizedBox(
height: 20,
),
ElevatedButton(
style: ElevatedButton.styleFrom(
primary: Theme.of(context).primaryColor,
),
onPressed: () {
setState(() {
toPrint = calc(
dropDownValue!,
int.parse(costController.text),
).toString();
});
},
child: const Text("Calculate")),
const SizedBox(
height: 20,
),
Container(
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5),
decoration: BoxDecoration(
color: Colors.lightGreenAccent[100],
border: const Border(
bottom: BorderSide(color: Colors.grey),
)),
child: Text("Tax : $toPrint "),
),
Wrap the column with a Form widget add avalidator to the textfield
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({super.key});
#override
Widget build(BuildContext context) {
const appTitle = 'Form Validation Demo';
return MaterialApp(
title: appTitle,
home: Scaffold(
appBar: AppBar(
title: const Text(appTitle),
),
body: const MyCustomForm(),
),
);
}
}
// Create a Form widget.
class MyCustomForm extends StatefulWidget {
const MyCustomForm({super.key});
#override
MyCustomFormState createState() {
return MyCustomFormState();
}
}
// Create a corresponding State class.
// This class holds data related to the form.
class MyCustomFormState extends State<MyCustomForm> {
// Create a global key that uniquely identifies the Form widget
// and allows validation of the form.
//
// Note: This is a GlobalKey<FormState>,
// not a GlobalKey<MyCustomFormState>.
final _formKey = GlobalKey<FormState>();
#override
Widget build(BuildContext context) {
// Build a Form widget using the _formKey created above.
return Form(
key: _formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
TextField(
controller: costController,
decoration: const InputDecoration(labelText: "Cost of Vehicle"),
keyboardType: TextInputType.number,
inputFormatters: <TextInputFormatter>[
FilteringTextInputFormatter.digitsOnly
],
// The validator receives the text that the user has entered.
validator: (value) {
if (value == null || value.isEmpty) {
return 'Please enter some text';
}
return null;
},
),
ElevatedButton(
style: ElevatedButton.styleFrom(
primary: Theme.of(context).primaryColor,
),
onPressed: () {
if (_formKey.currentState!.validate()) {
setState(() {
toPrint = calc(
dropDownValue!, int.parse(costController.text),
).toString();
});
}
},
child: const Text("Calculate")),
const SizedBox(
height: 20,
),
Container(
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5),
decoration: BoxDecoration(
color: Colors.lightGreenAccent[100],
border: const Border(
bottom: BorderSide(color: Colors.grey),
)),
child: Text("Tax : $toPrint "),
),
],
),
);
}
}
Use Form Widget and Convert TextField to TextFormField like that.
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
class FormWidget extends StatefulWidget {
const FormWidget({Key? key}) : super(key: key);
#override
State<FormWidget> createState() => _FormWidgetState();
}
class _FormWidgetState extends State<FormWidget> {
final TextEditingController costController = TextEditingController();
final _formKey = GlobalKey<FormState>();
#override
Widget build(BuildContext context) {
return Scaffold(
key: _formKey,
body: Column(
children: [
Form(
child: TextFormField(
validator: (value) {
if (value.isEmpty) {
return "Please enter the cost.";
}
return null;
},
controller: costController,
decoration: const InputDecoration(labelText: "Cost of Vehicle"),
keyboardType: TextInputType.number,
inputFormatters: <TextInputFormatter>[
FilteringTextInputFormatter.digitsOnly
],
),
),
const SizedBox(
height: 20,
),
ElevatedButton(
style: ElevatedButton.styleFrom(
primary: Theme.of(context).primaryColor,
),
onPressed: () {
if(_formKey.currentState.validate()){
//do your setState stuff
setState(() {
});
}
},
child: const Text("Calculate")),
const SizedBox(
height: 20,
),
Container(
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5),
decoration: BoxDecoration(
color: Colors.lightGreenAccent[100],
border: const Border(
bottom: BorderSide(color: Colors.grey),
)),
child: Text("Tax : "),
),
],
),
);
}
}

Using TextEditingControllers in AnimatedList to dynamically update data

I am implementing AnimatedList on my app with several TextEditingControllers. I would like to dynamically update, insert and remove data. I've read this question and an article on how to update data in an AnimatedList and this is how my code looks:
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
#override
State<StatefulWidget> createState() => _HomePage();
}
class _HomePage extends State<HomePage> {
List<Board> boards = [Board.empty()];
final GlobalKey<AnimatedListState> listKey = GlobalKey<AnimatedListState>();
void Function()? removeItemCallback(int index) {
if (boards.length <= 1) {
return null;
}
return (() {
FocusManager.instance.primaryFocus?.unfocus();
final removedBoard = boards.removeAt(index);
listKey.currentState!.removeItem(
index,
(context, animation) => SizeTransition(
axis: Axis.vertical,
sizeFactor: animation,
child: BoardListItem(
board: removedBoard,
index: index,
removeItemCallback: removeItemCallback(index),
),
),
duration: const Duration(milliseconds: 500));
setState(() {});
});
}
#override
Widget build(BuildContext context) {
return AnimatedList(
shrinkWrap: true,
physics: const ClampingScrollPhysics(),
key: listKey,
initialItemCount: boards.length,
itemBuilder: (context, index, animation) {
return SizeTransition(
axis: Axis.vertical,
sizeFactor: animation,
child: BoardListItem(
board: boards[index],
index: index,
removeItemCallback: removeItemCallback(index)));
},
);
}
}
class BoardListItem extends StatefulWidget {
const BoardListItem(
{Key? key,
required this.board,
required this.index,
required this.removeItemCallback})
: super(key: key);
final Board board;
final int index;
final void Function()? removeItemCallback;
#override
State<StatefulWidget> createState() => _BoardListItem();
}
class _BoardListItem extends State<BoardListItem> {
late final TextEditingController bigStakeController;
late final TextEditingController smallStakeController;
late final TextEditingController numberController;
#override
void initState() {
super.initState();
print('initing state');
bigStakeController =
TextEditingController(text: widget.board.bigStake.toString());
smallStakeController =
TextEditingController(text: widget.board.smallStake.toString());
numberController =
TextEditingController(text: widget.board.number.toString());
bigStakeController.addListener(() {
if (bigStakeController.text.isNotEmpty) {
widget.board.bigStake = int.parse(bigStakeController.text);
} else {
widget.board.bigStake = 0;
}
});
smallStakeController.addListener(() {
if (smallStakeController.text.isNotEmpty) {
widget.board.smallStake = int.parse(smallStakeController.text);
} else {
widget.board.smallStake = 0;
}
});
}
#override
void dispose() {
print('disposing these');
bigStakeController.dispose();
smallStakeController.dispose();
numberController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 5),
child: Container(
width: MediaQuery.of(context).size.width,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15),
border: Border.all(color: Colors.grey, width: 1.5)),
child: Column(children: [
Container(
decoration: const BoxDecoration(
border: Border(
bottom: BorderSide(width: 1.5, color: Colors.grey))),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
IconButton(
onPressed: (() {
numberController.text = '1234';
}),
icon: const Icon(Icons.shuffle)),
Text(
'Board ${widget.index + 1}',
style: const TextStyle(fontWeight: FontWeight.w500),
),
IconButton(
onPressed: widget.removeItemCallback,
icon: const Icon(Icons.delete_outline))
],
),
),
Container(
margin: const EdgeInsets.only(top: 15),
decoration: const BoxDecoration(
border: Border(
bottom: BorderSide(width: 1.5, color: Colors.grey))),
child: PinCodeTextField(
controller: numberController,
autoDisposeControllers: false,
autoUnfocus: false,
length: 4,
showCursor: true,
enablePinAutofill: false,
keyboardType: TextInputType.number,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
textStyle: const TextStyle(
fontSize: 20, fontWeight: FontWeight.w500),
inputFormatters: [
FilteringTextInputFormatter.allow(RegExp(r'[0-9]'))
],
animationType: AnimationType.scale,
//errorAnimationController: errorController,
appContext: context,
pinTheme: PinTheme(
shape: PinCodeFieldShape.box,
borderRadius: BorderRadius.circular(5),
fieldHeight: 50,
fieldWidth: 40,
selectedColor: const Color(0xFFB666D2),
inactiveColor: Colors.grey.shade400,
activeColor: const Color(0xFFB666D2)),
onChanged: (value) {
widget.board.number = value;
},
beforeTextPaste: (text) => false,
)),
IntrinsicHeight(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
SizedBox(
width: MediaQuery.of(context).size.width * 0.3,
child: Padding(
padding: const EdgeInsets.symmetric(
vertical: 5), //To manage vertical divider height
child: TextFormField(
controller: bigStakeController,
onTap: () {
if (widget.board.bigStake == 0) {
bigStakeController.clear();
}
},
onEditingComplete: () {
if (widget.board.bigStake == 0) {
bigStakeController.text = '0';
}
FocusManager.instance.primaryFocus?.unfocus();
},
enableInteractiveSelection: false,
inputFormatters: [
FilteringTextInputFormatter.allow(RegExp(r'[0-9]'))
],
keyboardType: TextInputType.number,
decoration: const InputDecoration(
floatingLabelBehavior: FloatingLabelBehavior.always,
border: InputBorder.none,
isDense: true,
label: Text('Big'),
),
)),
),
const VerticalDivider(
thickness: 1.5,
color: Colors.grey,
),
SizedBox(
width: MediaQuery.of(context).size.width * 0.3,
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 5.0),
child: TextFormField(
controller: smallStakeController,
onTap: () {
if (widget.board.smallStake == 0) {
smallStakeController.clear();
}
},
onEditingComplete: () {
if (widget.board.smallStake == 0) {
smallStakeController.text = '0';
}
FocusManager.instance.primaryFocus?.unfocus();
},
inputFormatters: [
FilteringTextInputFormatter.allow(RegExp(r'[0-9]'))
],
keyboardType: TextInputType.number,
enableInteractiveSelection: false,
decoration: const InputDecoration(
border: InputBorder.none,
isDense: true,
floatingLabelBehavior: FloatingLabelBehavior.always,
label: Text('Small'),
),
),
),
)
],
),
),
])),
);
}
}
When removing the first item, an unexpected behavior happens where the controller's text is sent to the second item. This does not happen when you remove the second item. (e.g Removing board 2).
Upon checking my data source for my second item, nothing was changed too.
Am I implementing TextEditingControllers into an AnimatedList wrongly? And if so, how do I properly implement it?

setState not updating the value in the screen using Flutter desktop

So I'm trying to update the value of the drop down list using the setState, but when I select a value from the list, the value on the screen won't be able to change
import 'package:demo_app_admin/Custom/custom_Font.dart';
import 'package:flutter/material.dart';
import '/Custom/Custom_Raised_Bottun.dart';
import '/Custom/Header.dart';
import '/Custom/inputField.dart';
class LoginView extends StatefulWidget {
#override
_LoginViewState createState() => _LoginViewState();
}
class _LoginViewState extends State<LoginView> {
#override
Widget build(BuildContext context) {
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final isKeyboard = MediaQuery.of(context).viewInsets.bottom != 0;
String _dropdownvalue = "Global admin";
List<String> _items = <String> ["Global admin", "Institution admin"];
return Scaffold(
body: Container(
width: double.infinity,
decoration: BoxDecoration(
gradient: LinearGradient(begin: Alignment.topCenter, colors: [
Colors.teal[700]!,
Colors.teal[200]!,
Colors.teal[400]!
]),
),
child: Column(
children: <Widget>[
const SizedBox(
height: 80,
),
if (!isKeyboard)
Header(
padding: const EdgeInsets.all(20),
crossAxisAlignment: CrossAxisAlignment.start,
head: "Welcome",
headTextStyle:
const TextStyle(color: Colors.white, fontSize: 40),
sizedBoxHeight: 10,
subtitle: "Sign In to Your Admin Account",
subtitleTextStyle:
const TextStyle(color: Colors.white, fontSize: 18),
),
Expanded(
child: Container(
decoration: const BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(60),
topRight: Radius.circular(60),
)),
child: Padding(
padding: const EdgeInsets.all(30),
child: SingleChildScrollView(
reverse: true,
padding: EdgeInsets.all(32),
child: Form(
key: _formKey,
child: Column(
children: <Widget>[
const SizedBox(
height: 40,
),
Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(10)),
child: Column(
children: <Widget>[
InputField(
labelText: 'Email',
padding: EdgeInsets.all(10),
borderSide: BorderSide(color: Colors.grey),
hintText: "Enter your email",
color: Colors.grey,
inputBorder: InputBorder.none,
obscureText: false,
enableSuggestion: true,
autoCorrect: true,
onSaved: (value) {},
// (value){controller.email = value!;},
validator: (value) {
if (value == null) {
print("ERROR");
}
},
),
InputField(
labelText: 'Password',
padding: EdgeInsets.all(10),
borderSide: BorderSide(color: Colors.grey),
hintText: "Enter your password",
color: Colors.grey,
inputBorder: InputBorder.none,
obscureText: true,
enableSuggestion: false,
autoCorrect: false,
onSaved: (value) {},
// (value){ controller.password = value!;},
validator: (value) {
if (value == null) {
print("ERROR");
}
},
),
],
),
),
const SizedBox(
height: 40,
),
here is the issue
DropdownButton<String>(
value: _dropdownvalue,
icon: Icon(Icons.keyboard_arrow_down),
items: _items.map((String _items) {
return DropdownMenuItem<String>(
value: _items,
child: CustomFont(text: _items),
);
}).toList(),
onChanged: (value) {
setState(() => _dropdownvalue = value!);
}),
const SizedBox(
height: 40,
),
CustomRaisedButton(
width: 200,
height: 50.0,
margin: const EdgeInsets.symmetric(horizontal: 50),
color: Colors.teal.shade500,
borderRadius: BorderRadius.circular(10),
text: "LOGIN",
textColor: Colors.white,
fontSize: 17,
fontWeight: FontWeight.bold,
function: () {}
// {
// _formKey.currentState?.save();
// if(_formKey.currentState?.validate() !=null){
// controller.signInWithEmailAndPassword();
// }
// },
),
SizedBox(
height: 10,
),
],
),
),
),
),
))
],
),
),
);
}
}
The issue is here, you are declaring variables inside build. Therefore, variables get reset to default value on every build. Means setState.
Declare variables outside the build method.
class _LoginViewState extends State<LoginView> {
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
String _dropdownvalue = "Global admin";
List<String> _items = <String>["Global admin", "Institution admin"];
#override
Widget build(BuildContext context) {
final isKeyboard = MediaQuery.of(context).viewInsets.bottom != 0;
return Scaffold(
More about StatefulWidget.

How to create contact list using Flutter?

I was create an dynamic contact list.
When I enter the number in add contact textfield. Automatically another text field will open. When I erase the text field the below the empty will delete automatically.
I tried several ways but id didn't work.
In my code I used text field on changed method when I enter the number it open the new contact field every number I added, I want only one contact field.
import 'package:flutter/material.dart';
class Contactadd extends StatefulWidget {
const Contactadd({Key? key}) : super(key: key);
#override
_ContactaddState createState() => _ContactaddState();
}
class _ContactaddState extends State<Contactadd> {
String dropdownValue = "Mobile";
List<Widget> cardList = [];
Widget card1() {
return Container(
margin: const EdgeInsets.all(10),
decoration: BoxDecoration(
color: const Color(0xFFE8DBDB),
borderRadius: BorderRadius.circular(20)),
child: Row(
children: [
const SizedBox(
width: 10,
),
dropdown(),
Container(
height: 40,
width: 200,
margin: const EdgeInsets.all(5),
child: TextField(
keyboardType: TextInputType.number,
// controller: dropdownController,
decoration: const InputDecoration(
contentPadding: EdgeInsets.only(left: 10),
border: InputBorder.none),
onChanged: (_) {
String dataa = _.toString();
if (dataa.length == 1) {
print(_ + "=================");
cardList.add(_card());
setState(() {});
} else if (dataa.length < 1) {
cardList.removeLast();
}
},
// addCardWidget,
),
),
],
),
);
}
Widget _card() {
return Container(
margin: const EdgeInsets.all(10),
decoration: BoxDecoration(
color: const Color(0xFFDE6868),
borderRadius: BorderRadius.circular(20)),
child: Row(
children: [
const SizedBox(
width: 10,
),
dropdown(),
Container(
height: 40,
width: 200,
margin: const EdgeInsets.all(5),
child: TextFormField(
keyboardType: TextInputType.number,
decoration: const InputDecoration(
contentPadding: EdgeInsets.only(left: 10),
border: InputBorder.none),
onChanged: (_) {
String dataa = _.toString();
if (dataa.isEmpty) {
print("true");
} else {
print("false");
}
if (dataa.length == 1 || dataa.length == 0) {
print(_ + "=================");
cardList.add(_card());
setState(() {});
} else {
cardList.removeLast();
}
})),
],
),
);
}
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
appBar: AppBar(
title: Text("Contact List"),
),
body: SingleChildScrollView(
child: Column(
children: [
card1(),
Container(
height: 430,
width: MediaQuery.of(context).size.width,
child: ListView.builder(
itemCount: cardList.length,
itemBuilder: (context, index) {
return _card();
}),
),
],
),
),
),
);
}
}
The complete code this will help you to create view like your requirment
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Contactadd(),
);
}
}
class Contactadd extends StatefulWidget {
#override
_ContactaddState createState() => _ContactaddState();
}
class _ContactaddState extends State<Contactadd> {
Map<int, dynamic> contactMap = new Map();
#override
void initState() {
contactMap.addAll(
{0: 1},
);
super.initState();
}
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
appBar: AppBar(
title: Text("Contact List"),
),
body: Column(
children: [
for (var i = 0; i < contactMap.length; i++) ...[
Container(
margin: EdgeInsets.all(10),
child: TextField(
onChanged: (value) {
if (value.toString().isEmpty) {
contactMap.removeWhere((key, value) => key == i + 1);
} else {
contactMap.addAll(
{i + 1: 1},
);
}
setState(() {});
},
keyboardType: TextInputType.number,
autocorrect: true,
decoration: InputDecoration(
hintStyle: TextStyle(color: Colors.grey),
filled: true,
contentPadding: EdgeInsets.only(bottom: 0.0, left: 8.0),
fillColor: Colors.white70,
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(4.0)),
borderSide:
BorderSide(color: Colors.lightBlueAccent, width: 1),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(4.0)),
borderSide: BorderSide(color: Colors.lightBlueAccent),
),
),
),
),
],
],
),
),
);
}
}

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),
),
),
),
);
}
}