i'm trying to use customTextField
this the file which contain the Widget
import 'package:flutter/material.dart';
Widget defaultFormField({
required TextEditingController controller,
required TextInputType type,
required Function validate,
Function? onSubmitted,
Function? onChange,
Function? onTap,
required String label,
required IconData prefix,
}) =>
Form(
child: TextFormField(
controller: controller,
validator: (value) => validate(value),
// validator: validate(),
onFieldSubmitted: onSubmitted!(),
onChanged: onChange!(),
onTap: onTap!(),
keyboardType: type,
decoration: InputDecoration(
labelText:label,
prefixIcon: Icon(prefix),
border: const OutlineInputBorder(),
),
),
);
and this how i call it
in my home page
#override
Widget build(BuildContext context) {
return Scaffold(
key: scaffoldKey,
appBar: AppBar(
backgroundColor: Colors.red,
title: Text(titles[currentIndex]),
),
floatingActionButton: FloatingActionButton(
backgroundColor: Colors.redAccent,
onPressed: () {
if (isBottomSheet) {
Navigator.pop(context);
isBottomSheet = false;
setState(() {
fabIcon = Icons.edit;
});
} else {
scaffoldKey.currentState?.showBottomSheet(
(context) => Column(mainAxisSize: MainAxisSize.min, children: [
Form(
key: formdKey,
child: defaultFormField(
controller: titleController,
type: TextInputType.text,
validate: (String value) {
if (value.isEmpty) {
return 'title must not be empty';
}
return null;
},
label: 'Title Task',
prefix: Icons.title),
),
]));
isBottomSheet = true;
setState(() {
fabIcon = Icons.add_task;
});
}
},
child: Icon(fabIcon),
),
bottomNavigationBar: BottomNavigationBar(
selectedItemColor: Colors.white,
unselectedItemColor: Colors.black54,
backgroundColor: Colors.red,
type: BottomNavigationBarType.fixed,
currentIndex: currentIndex,
onTap: (value) {
setState(() {
currentIndex = value;
});
},
items: const [
BottomNavigationBarItem(
icon: Icon(Icons.new_label), label: 'Tasks'),
BottomNavigationBarItem(
icon: Icon(Icons.check_circle), label: 'Done'),
BottomNavigationBarItem(
icon: Icon(Icons.archive), label: 'Archive'),
]),
body: screens[currentIndex],
);
}
You have to use a class instead of that code, your code is wrong.
This is one of my custom TextFormField.
This contains own another class but anyway you can use this:
import 'package:flutter/material.dart';
import 'package:plasco/config/textfield_validator.dart';
import 'package:plasco/utils/colors.dart';
class PlascoTextFormFild extends StatefulWidget {
final String? text;
final FontWeight? fontWeight;
final double? fontSize;
final double? counterFontSize;
final TextAlign? textAlign;
final TextInputType? keyboardType;
final int? maxLength;
final String? hint;
final int? maxLines;
final Color? color;
final TextEditingController? controller;
final bool? enabled;
final Validator? validator;
final bool publicValidator;
const PlascoTextFormFild(
{Key? key,
this.text,
this.fontWeight,
this.publicValidator = false,
this.fontSize,
this.color = Colors.transparent,
this.counterFontSize,
required this.textAlign,
this.keyboardType,
this.maxLength = 800,
this.hint,
this.maxLines,
this.controller,
this.enabled = true,
this.validator})
: super(key: key);
#override
_PlascoTextFormFildState createState() => _PlascoTextFormFildState();
}
class _PlascoTextFormFildState extends State<PlascoTextFormFild> {
bool _focused = false;
bool _hasError = false;
String _error = '';
late FocusNode? _keyboardFocus;
#override
void initState() {
_keyboardFocus = FocusNode();
// TODO: implement initState
super.initState();
}
#override
Widget build(BuildContext context) {
_keyboardFocus!.addListener(() {
setState(() {
if (!_keyboardFocus!.hasPrimaryFocus) {
_focused = false;
}
});
});
return Directionality(
textDirection: TextDirection.rtl,
child: Container(
decoration: BoxDecoration(
color: widget.color,
borderRadius: BorderRadius.circular(5),
),
child: TextFormField(
controller: widget.controller,
enabled: widget.enabled,
cursorHeight: 20,
textDirection: TextDirection.rtl,
focusNode: _keyboardFocus,
maxLines: widget.maxLines,
maxLength: widget.maxLength,
textAlign: widget.textAlign!,
keyboardType: widget.keyboardType,
validator: (text) {
if (widget.validator == null) {
if (widget.publicValidator) {
var a = PublicValidator(text!, widget.text!);
if (a) {
return "";
} else {
return null;
}
} else {
return null;
}
} else {
if (widget.validator!.hasError(text!)) {
setState(() => _hasError = true);
_error = widget.validator!.getError();
return '';
} else {
setState(() => _hasError = false);
return null;
}
}
},
style: TextStyle(
color: PlascoColor.Black1,
fontFamily: 'IRANSansMobile',
fontSize: widget.fontSize,
letterSpacing: 0,
fontWeight: widget.fontWeight,
height: widget.maxLines != null ? 2 : 1),
decoration: InputDecoration(
counterText: "",
labelStyle: TextStyle(
color: _hasError
? PlascoColor.Red1
: _focused
? PlascoColor.Yellow1
: PlascoColor.Gray1,
fontFamily: 'IRANSansMobile',
fontSize: widget.fontSize,
letterSpacing: 0,
fontWeight: widget.fontWeight,
height: 1,
),
hintStyle: TextStyle(
color: PlascoColor.Gray2,
fontFamily: 'IRANSansMobile',
fontSize: widget.fontSize,
letterSpacing:
0 /*percentages not used in flutter. defaulting to zero*/,
fontWeight: widget.fontWeight,
height: 1),
counterStyle: TextStyle(
color: PlascoColor.Gray1,
fontFamily: 'IRANSansMobile',
fontSize: widget.counterFontSize,
letterSpacing: 0,
fontWeight: widget.fontWeight,
height: 1),
floatingLabelBehavior: FloatingLabelBehavior.always,
// border: OutlineInputBorder(),
disabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(4.0),
borderSide: const BorderSide(
color: PlascoColor.Gray2,
width: 1.0,
)),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(4.0),
borderSide: const BorderSide(
color: PlascoColor.Gray2,
width: 1.0,
)),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(4.0),
borderSide: const BorderSide(
color: PlascoColor.Yellow1,
width: 1.0,
)),
focusedErrorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(4.0),
borderSide: const BorderSide(
color: PlascoColor.Red1,
width: 1.0,
)),
errorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(4.0),
borderSide: const BorderSide(
color: PlascoColor.Red1,
width: 1.0,
)),
labelText: _hasError ? _error : widget.text,
hintText: widget.hint,
contentPadding: EdgeInsets.fromLTRB(8, 8, 8, 8),
),
// autofocus: false,
),
),
);
}
}
Related
I have mu custom DropDown Widget.
class DropDownMenuField extends StatefulWidget {
String title;
final InputDecoration decoration;
final String Function(String) validator;
final void Function(dynamic value) onSelectionDone;
final String initialValue;
final Color selectedItemColor;
final DropMenuMode menuMode;
int selectvalueindex;
final Function(String) onChanged;
var model;
DropDownMenuField(
{Key key,
this.title,
this.decoration,
this.validator,
this.onSelectionDone,
this.initialValue,
this.selectedItemColor,
this.model,
this.menuMode,
this.selectvalueindex,
this.onChanged})
: super(key: key);
#override
State<DropDownMenuField> createState() => _DropDownMenuFieldState();
}
class _DropDownMenuFieldState extends State<DropDownMenuField> {
final TextEditingController _controller = TextEditingController();
void _popUpModalBottomSheet(BuildContext context) async {
List<String> finalDataList = [];
List<dynamic> dataMap = await apiRegistrationDataList(widget.menuMode);
finalDataList = parseMap(dataMap);
final result = await showModalBottomSheet(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(9.0),
),
isScrollControlled: true,
context: context,
builder: (context) => DialogMenu(
title: widget.title,
data: finalDataList,
));
if (result == null) {
widget.title = widget.title;
_controller.text = widget.title;
} else {
// widget.title = result ?? widget.title;
// lab
labStyle = checkedLableStyle;
lable = result;
_controller.text = result;
widget.onSelectionDone(result);
widget.validator(result);
setState(() {});
}
SetGlobalRequaerData(result, dataMap);
}
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () => _popUpModalBottomSheet(context),
child: TextFormField(
controller: _controller,
readOnly: true,
enabled: false,
autovalidateMode: AutovalidateMode.onUserInteraction,
validator: widget.validator,
onChanged: widget.onChanged,
style: const TextStyle(
fontSize: 16,
color: Color(0xFF3C3C43),
),
decoration: InputDecoration(
labelStyle: labStyle,
hintStyle: TextStyle(
fontFamily: 'FiraSans',
color: GeneralStyles.greyColor,
),
fillColor: Colors.white,
filled: true,
contentPadding: const EdgeInsets.fromLTRB(16, 0, 0, 0),
errorStyle: const TextStyle(
color: Colors.red,
fontFamily: 'FiraSans',
fontWeight: FontWeight.w400,
fontSize: 13),
border: OutlineInputBorder(
borderRadius: const BorderRadius.all(Radius.circular(4)),
borderSide: BorderSide(
color: GeneralStyles.greyColor.withOpacity(0.5),
width: .5)),
enabledBorder: const OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(4)),
borderSide: BorderSide(color: Color(0xFF707070), width: .5)),
disabledBorder: OutlineInputBorder(
borderRadius: const BorderRadius.all(Radius.circular(4)),
borderSide:
BorderSide(color: GeneralStyles.greyColor, width: .5)),
focusedBorder: OutlineInputBorder(
borderRadius: const BorderRadius.all(Radius.circular(4)),
borderSide:
BorderSide(color: GeneralStyles.blackColor, width: 1)),
errorBorder: const OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(4)),
borderSide: BorderSide(color: Colors.red, width: .5),
),
labelText: lable,
hintText: widget.title,
suffixIcon: Icon(
Icons.keyboard_arrow_down,
color: GeneralStyles.greyColor,
),
),
));
}
}
And i call it on my registration page.
DropDownMenuField(
title: "Anrede",
model: widget.model,
menuMode: DropMenuMode.genders,
selectvalueindex: 0,
onSelectionDone: (value){
print(value);
},
validator: (value){
if(widget.model.selectedDropMenu[0].isEmpty){
return 'Bitte fülle das Feld aus';
}
return null;
},
),
When i click button when DropDownMenuField selectedValue is empty validator is work but when i select value widget don't call validator and don't change color from red. How call validator after change value. I read that when texteditingcontroller is changed, calling validator after him. i add it but not work.
I have implemented a login screen using flutter. the screen is fully functional and working properly with validations. I want this screen to be scrollable and responsive to other devices. how can I do that? below I have added my full login screen code. appreciate your help on this.
how to scroll the screen
how to implement responsive screen
class LoginScreen extends StatefulWidget {
const LoginScreen({Key? key}) : super(key: key);
#override
_LoginScreenState createState() => _LoginScreenState();
}
class _LoginScreenState extends State<LoginScreen> {
#override
Widget build(BuildContext context) {
final Size = MediaQuery.of(context).size;
return GestureDetector(
onTap: () => FocusManager.instance.primaryFocus?.unfocus(),
child: Container(
decoration: const BoxDecoration(
gradient: LinearGradient(
colors: [Color.fromARGB(255, 3, 86, 124), Color(0xff141a3a)],
begin: Alignment.topRight,
end: Alignment.bottomLeft,
)),
child: Scaffold(
backgroundColor: Colors.transparent,
resizeToAvoidBottomInset: false,
body: Padding(
padding: const EdgeInsets.only(top: 40, left: 20, right: 20),
child: Column(
children: [
Expanded(
flex: 2,
child: Column(
children: [
// Spacer(flex: 1),
Image(
image: const AssetImage(
'assets/images/LogoVector.png',
),
height: Size.width / 2.9,
width: Size.width / 2.9,
),
SizedBox(height: 5),
Text(
"LOGIN",
textAlign: TextAlign.left,
style: TextStyle(
fontSize: 30,
color: textWhite,
fontFamily: "Roboto"),
),
],
),
),
// const Spacer(flex: 1),
const Expanded(flex: 3, child: Center(child: LoginForm())),
// Spacer(
// flex: 1,
// ),
],
),
),
),
),
);
}
}
class LoginForm extends StatefulWidget {
const LoginForm({Key? key}) : super(key: key);
#override
_LoginFormState createState() => _LoginFormState();
}
Map<String, String> loginUserData = {
'email': '',
'password': '',
'id': '',
'userName': '',
'token': '',
'userStatus': '',
};
class _LoginFormState extends State<LoginForm> {
TextEditingController emailEditingController = new TextEditingController();
TextEditingController passwordEditingController = new TextEditingController();
final _formKey = GlobalKey<FormState>();
String email = "";
String password = "";
String username = "";
bool isLoading = false;
bool typing = true;
bool _isObscure = true;
// bool newValue = true;
bool checkedValue = true;
//String fcmToken = '';
Future LoginData() async {
setState(() {
isLoading = true;
typing = false;
});
try {
var response = await Dio().post(BASE_API + 'user/login',
data: {"username": email, "password": password});
if (response.data["status"] == "LoginSuccess") {
setState(() {
isLoading = false;
});
Get.snackbar(
"success",
"logged in successfully",
backgroundColor: buttontext.withOpacity(0.5),
colorText: textWhite,
borderWidth: 1,
borderColor: Colors.grey,
);
Get.to(BottomNavigation());
} else {
setState(() {
isLoading = false;
typing = true;
});
Get.snackbar(
"error",
"No User Found",
backgroundColor: buttontext.withOpacity(0.5),
colorText: textWhite,
borderWidth: 1,
borderColor: Colors.grey,
);
}
print("res: $response");
setState(() {
isLoading = false;
typing = true;
});
} catch (e) {
setState(() {
isLoading = false;
typing = true;
});
Get.snackbar("Error", "Something went wrong.Please contact admin",
backgroundColor: buttontext.withOpacity(0.5),
borderWidth: 1,
borderColor: Colors.grey,
colorText: Colors.white,
icon: Icon(
Icons.error_outline_outlined,
color: Colors.red,
size: 30,
));
print(e);
}
}
#override
Widget build(BuildContext context) {
final Size = MediaQuery.of(context).size;
return Form(
key: _formKey,
autovalidateMode: AutovalidateMode.disabled,
child: Column(
children: [
TextFormField(
controller: emailEditingController,
enabled: true,
decoration: InputDecoration(
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(30.0),
borderSide: const BorderSide(
color: textWhite,
),
// borderSide: BorderSide.none
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(30.0),
borderSide: const BorderSide(color: textWhite),
),
errorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(30.0),
borderSide: const BorderSide(color: Colors.red),
),
focusedErrorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(30.0),
borderSide: const BorderSide(color: Colors.red),
),
isDense: true,
contentPadding: EdgeInsets.fromLTRB(10, 30, 10, 0),
hintText: "Email/ Username",
hintStyle: TextStyle(
color: textWhite, fontFamily: "Roboto", fontSize: 14),
),
style: TextStyle(color: textWhite),
validator: (String? UserName) {
if (UserName != null && UserName.isEmpty) {
return "Email can't be empty";
}
return null;
},
onChanged: (String? text) {
email = text!;
// print(email);
},
onSaved: (value) {
loginUserData['email'] = value!;
},
),
SizedBox(
height: 10,
),
TextFormField(
controller: passwordEditingController,
obscureText: _isObscure,
enabled: true,
decoration: InputDecoration(
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(30.0),
borderSide: const BorderSide(color: textWhite),
// borderSide: BorderSide.none
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(30.0),
borderSide: const BorderSide(color: textWhite),
),
errorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(30),
borderSide: const BorderSide(color: Colors.red),
),
focusedErrorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(30),
borderSide: const BorderSide(color: Colors.red),
),
isDense: true,
contentPadding: EdgeInsets.fromLTRB(10, 10, 10, 0),
suffixIcon: IconButton(
icon: Icon(
_isObscure ? Icons.visibility : Icons.visibility_off),
color: textWhite,
onPressed: () {
setState(() {
_isObscure = !_isObscure;
});
}),
hintText: "Password",
hintStyle: TextStyle(
color: textWhite,
fontFamily: "Roboto",
fontSize: 14,
)),
style: TextStyle(color: textWhite),
validator: (String? Password) {
if (Password != null && Password.isEmpty) {
return "Password can't be empty";
}
return null;
},
onChanged: (String? text) {
password = text!;
print(password);
},
onSaved: (value) {
loginUserData['password'] = value!;
},
),
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Expanded(
child: CheckboxListTile(
title: const Text(
"Remember Me",
style: TextStyle(
color: textWhite, fontFamily: "Roboto", fontSize: 14),
),
activeColor: buttontext,
// tileColor: buttontext,
value: checkedValue,
onChanged: (newValue) {
FocusManager.instance.primaryFocus?.unfocus();
setState(() {
if (isLoading != true) {
checkedValue = newValue!;
print(newValue);
}
});
},
contentPadding: EdgeInsets.only(left: 0, top: 0),
controlAffinity:
ListTileControlAffinity.leading, // <-- leading Checkbox
),
),
TextButton(
child: Text(
"Forget Password",
style: TextStyle(
color: textWhite, fontFamily: "Roboto", fontSize: 14),
),
onPressed: () {
Get.to(() => Forget_Screen());
},
)
],
),
SizedBox(height: 40),
isLoading
? SpinKitDualRing(
color: textWhite,
size: 40,
)
: GestureDetector(
child: MainButton("Login"),
onTap: () async {
FocusManager.instance.primaryFocus?.unfocus();
if (_formKey.currentState!.validate()) {
_formKey.currentState!.save();
await LoginData();
// Get.to(BottomNavigation());
}
},
),
SizedBox(height: 15),
Container(
width: 275.0,
height: 40.0,
child: OutlinedButton(
onPressed: () {
Get.to(() => const Signup_Screen());
},
child: const Text(
'Signup',
style: TextStyle(
fontSize: 15, fontFamily: "Roboto", color: textWhite
//fontWeight: FontWeight.w500,
// color: Colors.black,
),
),
style: OutlinedButton.styleFrom(
side: const BorderSide(
width: 1.0,
color: textWhite,
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(18.0),
// side: BorderSide(width: 2, color: Colors.green),
),
),
),
)
],
),
);
}
}
How to scroll the screen? Use SingleChildScrollView wrap your Column, remember to ristrict the content size to avoid error.
How to implement responsive screen? Simplest is use LayoutBuilder widget that provide constrains as a props. This constrains can provide maxHeight, maxWidth,... You can then rely on it to determine how you build your application (responsive).
Example:
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: LayoutBuilder(
builder: (context, constrains){
final maxw = constrains.maxWidth;
String text = '';
if(maxw < 420) {text = 'Smaller than 420';}
else {text = 'Bigger than 420';}
return Center(child: Text('Width is: $maxw, $text'));
}
),
);
}
I am design a screen in which I need to opening a drop down list when user click on textfield till now I am using CupertinoActionSheetAction sheet which is correctly working now I need to replace it with DropdownButton but when I am doing it is not displaying on screen I don't know why.
Here is my code focus on line number 136 (function for CupertinoActionSheetAction is working code) and line 138 where (function for drop not working code) according to me may be it due to build context but I m not sure how to use 'build context' in this context can any one help me out to fix that.
Thanks in advance, And any suggestion for making my code more reusable will be helpful as well :)
import 'dart:ffi';
import 'package:fleet_management/AppContants/Contants.dart';
import 'package:fleet_management/Controllers/NewFuelExpenseController.dart';
import 'package:fleet_management/Models/NewFuelExpenseModel.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
class AddFuelView extends StatefulWidget {
const AddFuelView({Key? key}) : super(key: key);
#override
_AddFuelView createState() {
return _AddFuelView();
}
}
// MyTripHistoryView
class _AddFuelView extends State<AddFuelView> {
NewFuelExpenseModel fuelExpense =
NewFuelExpenseController().getNewFuelExpense();
DateTime _selectedDate = DateTime.now();
String dropdownvalue = 'Item 1';
// List of items in our dropdown menu
var items = [
'Item 1',
'Item 2',
'Item 3',
'Item 4',
'Item 5',
];
TextStyle _titleTextStyle = const TextStyle();
TextStyle _valueTextStyle = const TextStyle();
final GlobalKey newFuelExpenseFormField = GlobalKey<FormState>();
final TextEditingController _dateEditingController = TextEditingController();
final TextEditingController _priceTextEditingController =
TextEditingController();
final TextEditingController _gallonsTextEditingController =
TextEditingController();
final TextEditingController _totalTextEditingController =
TextEditingController();
final TextEditingController _odometerTextEditingController =
TextEditingController();
final TextEditingController _fuelTypeTextEditingController =
TextEditingController();
final TextEditingController _vendorTextEditingController =
TextEditingController();
#override
void initState() {
super.initState();
_titleTextStyle =
const TextStyle(fontSize: 16, fontWeight: FontWeight.w600);
_valueTextStyle = const TextStyle(
fontSize: 16, fontWeight: FontWeight.w600, color: Colors.black38);
_dateEditingController.text =
"${_selectedDate.day}-${_selectedDate.month}-${_selectedDate.year}";
}
#override
Widget build(BuildContext context) {
var scaffold = Scaffold(
appBar: AppBar(
title: Text(StringsConstants.newFuelExpense),
backgroundColor: AppColorsConstants.primaryColor,
actions: <Widget>[
FlatButton(
textColor: Colors.white,
onPressed: () {
print("SAVE Button Clicked");
},
child: Text("Save", style: _titleTextStyle),
),
],
),
body: SafeArea(
child: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(16),
child: Form(
key: newFuelExpenseFormField,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
showDateRow(context),
addTextFieldInput(
StringsConstants.priceGallon,
"\u{20B9}0.00",
false,
_priceTextEditingController,
TextInputType.datetime,
null,
null),
addTextFieldInput(
StringsConstants.gallons,
"",
false,
_gallonsTextEditingController,
TextInputType.number,
null,
null),
addTextFieldInput(
StringsConstants.total,
"\u{20B9}0.00",
false,
_totalTextEditingController,
TextInputType.number,
null,
null),
addTextFieldInput(
StringsConstants.odometer,
"",
false,
_odometerTextEditingController,
TextInputType.number,
null,
null),
// show action sheet
addTextFieldInput(
StringsConstants.fuelType,
"",
true,
_fuelTypeTextEditingController,
TextInputType.none,
null, () {
// Working. - >>>> HERE <<<<<
showActionSheet(context);
// Not Working >>>> HERE <<<<< Uncomment following function before
// showDropDown();
}),
addTextFieldInput(
StringsConstants.vendor,
"",
false,
_vendorTextEditingController,
TextInputType.text,
null,
null),
const SizedBox(
height: 50,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
ElevatedButton(
onPressed: () {
print("Submit button pressed!");
},
style: ElevatedButton.styleFrom(
padding: const EdgeInsets.symmetric(horizontal: 24),
primary: AppColorsConstants.primaryColor,
textStyle:
const TextStyle(fontWeight: FontWeight.bold),
),
child: Text(StringsConstants.submit)),
ElevatedButton(
onPressed: () {
print("Cancel button pressed!");
},
style: ElevatedButton.styleFrom(
padding: const EdgeInsets.symmetric(horizontal: 24),
primary: AppColorsConstants.primaryColor,
textStyle:
const TextStyle(fontWeight: FontWeight.bold),
),
child: Text(StringsConstants.cancel))
],
)
],
),
),
),
),
),
);
return scaffold;
}
void showDropDown() {
DropdownButton<String>(
items: <String>['A', 'B', 'C', 'D'].map((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
onChanged: (_) {},
);
}
Future<dynamic> showActionSheet(BuildContext context) {
return showCupertinoModalPopup(
context: context,
builder: (BuildContext context) => CupertinoActionSheet(
title: const Text('Choose Options'),
actions: <Widget>[
CupertinoActionSheetAction(
child: const Text('Oil'),
onPressed: () {
_fuelTypeTextEditingController.text = "Oil";
Navigator.pop(context, 'Oil');
},
),
CupertinoActionSheetAction(
child: const Text('Petrol'),
onPressed: () {
_fuelTypeTextEditingController.text = "Petrol";
Navigator.pop(context, 'Petrol');
},
),
CupertinoActionSheetAction(
child: const Text('diesel'),
onPressed: () {
_fuelTypeTextEditingController.text = "diesel";
Navigator.pop(context, 'diesel');
},
)
],
cancelButton: CupertinoActionSheetAction(
child: const Text('Cancel'),
isDefaultAction: true,
onPressed: () {
Navigator.pop(context, 'Cancel');
},
)),
);
}
Container addTextFieldInput(
String title,
String initialValue,
bool isEditable,
TextEditingController textfieldController,
TextInputType keyboardType,
FormFieldValidator<String>? validator,
GestureTapCallback? tabCallback,
) {
return Container(
padding: const EdgeInsets.fromLTRB(0, 16, 0, 8),
child: SizedBox(
child: TextFormField(
onTap: tabCallback,
keyboardType: keyboardType,
cursorHeight: 16,
cursorWidth: 1.4,
readOnly: isEditable,
controller: textfieldController,
validator: validator,
decoration: InputDecoration(
isDense: true,
floatingLabelStyle:
TextStyle(color: AppColorsConstants.primaryColor),
labelText: title,
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(
color: AppColorsConstants.primaryColor, width: 1.5),
),
enabledBorder: const OutlineInputBorder(
borderSide: BorderSide(color: Colors.black38, width: 1.5),
),
border: const OutlineInputBorder()),
style: const TextStyle(fontSize: 18),
cursorColor: Colors.black38,
showCursor: true,
autofocus: true,
),
),
);
}
Container showDateRow(BuildContext context) {
return Container(
child: TextFormField(
onTap: () => {_selectDate(context)},
cursorHeight: 16,
cursorWidth: 1.4,
readOnly: true,
enableInteractiveSelection: false,
controller: _dateEditingController,
decoration: InputDecoration(
isDense: true,
labelStyle: const TextStyle(color: Colors.orangeAccent),
labelText: StringsConstants.date,
focusedBorder: const OutlineInputBorder(
borderSide: BorderSide(color: Colors.orangeAccent, width: 1.5),
),
enabledBorder: const OutlineInputBorder(
borderSide: BorderSide(color: Colors.black38, width: 1.5),
),
border: const OutlineInputBorder()),
style: const TextStyle(fontSize: 18),
cursorColor: Colors.black38,
showCursor: true,
autofocus: true,
),
);
}
Future<void> _selectDate(BuildContext context) async {
final DateTime? picked = await showDatePicker(
context: context,
initialDate: _selectedDate,
firstDate: DateTime(1990),
lastDate: DateTime.now());
if (picked != null && picked != _selectedDate) {
setState(() {
_selectedDate = picked;
this._dateEditingController.text =
"${_selectedDate.day}-${_selectedDate.month}-${_selectedDate.year}";
});
}
}
}
For DropDown in flutter you need
an initail value,
a list to be shown just
String selectedvalue='myvalue';
/// be sure you add the variable value in the 0 index of you list other wise it will thrown error or exception..
List<String> myList=[
'myvalue',/// the value is same as variable value
'othe value', ....
];
DropDownButton(
onChanged: (resultValue){
/// you can get selected value from here
},
items: myList.map((e){
retrun DropdownMenuItem(
value: e,
child: Text(e));
}).toList(),
value: selectedvalue,
),
You can use DropdownButtonFormField in place of TextFormField and can make some style related changes per your requirement.
class MyWidget extends StatelessWidget {
String selectedValue = "USA";
List<DropdownMenuItem<String>> get dropdownItems{
List<DropdownMenuItem<String>> menuItems = [
DropdownMenuItem(child: Text("USA"),value: "USA"),
DropdownMenuItem(child: Text("Canada"),value: "Canada"),
DropdownMenuItem(child: Text("Brazil"),value: "Brazil"),
DropdownMenuItem(child: Text("England"),value: "England"),
];
return menuItems;
}
#override
Widget build(BuildContext context) {
return DropdownButtonFormField(
decoration: InputDecoration(
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.blue, width: 2),
borderRadius: BorderRadius.circular(20),
),
border: OutlineInputBorder(
borderSide: BorderSide(color: Colors.blue, width: 2),
borderRadius: BorderRadius.circular(20),
),
filled: true,
fillColor: Colors.blueAccent,
),
dropdownColor: Colors.blueAccent,
value: selectedValue,
onChanged: (String? newValue) {
selectedValue = newValue!;
},
items: dropdownItems);
}
}
I'm benninger in flutter and I need in my TextFormField a filter, if don't have at least one uppercase or lowercase letter, or a number, show error in a text in red with: "Should be have a number", for example.
This is my form (a part, with the relevant parts: textformfields and the voidinitState()):
class _RegisterState extends State<Register> {
bool showError = false;
bool isButtonActive = true;
String message = '';
String messagcell = '';
#override
void initState() {
super.initState();
correo.addListener(() {
final isButtonActive = correo.text.isNotEmpty;
setState(() => this.isButtonActive = isButtonActive);
});
celular.addListener(() {
final isButtonActive = correo.text.isNotEmpty;
setState(() => this.isButtonActive = isButtonActive);
});
passwd2.addListener(() {
setState(() {
showError = passwd2.text.isEmpty
? false
: passwd.text.trim() != passwd2.text.trim() ||
passwd2.text.length < 8;
});
final isButtonActive = correo.text.isNotEmpty;
setState(() => this.isButtonActive = isButtonActive);
});
passwd.addListener(() {
setState(() {
showError = passwd.text.isEmpty
? false
: passwd.text.trim() != passwd2.text.trim() ||
passwd.text.length < 8;
});
final isButtonActive = correo.text.isNotEmpty;
setState(() => this.isButtonActive = isButtonActive);
});
}
void validateEmail(String enteredEmail) {
if (EmailValidator.validate(enteredEmail)) {
setState(() {
message = '';
});
} else {
setState(() {
message = ('Por favor ingrese un correo válido');
});
}
}
void validateCell(String enteredCell) {
if (enteredCell.length >= 9 && enteredCell.length <= 15) {
setState(() {
messagcell = '';
});
} else if (enteredCell.length < 9) {
setState(() {
messagcell = ('Por favor ingrese un número válido');
});
}
}
TextEditingController correo = TextEditingController();
TextEditingController celular = TextEditingController();
TextEditingController passwd = TextEditingController();
TextEditingController passwd2 = TextEditingController();
#override
void dispose() {
correo.dispose();
passwd.dispose();
celular.dispose();
passwd2.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
height: 900,
child: Card(
color: Colors.blue[200],
child: Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
'Register',
style: TextStyle(fontSize: 25, fontWeight: FontWeight.bold),
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: TextFormField(
inputFormatters: <TextInputFormatter>[
FilteringTextInputFormatter.allow(
RegExp("[-#._0-9a-zA-Z]")),
new LengthLimitingTextInputFormatter(36),
],
decoration: InputDecoration(
labelText: 'Correo',
prefixIcon: Icon(Icons.mail),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide: BorderSide(color: Colors.blue, width: 2.0),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide:
BorderSide(color: Colors.blue[900], width: 2.0),
)),
onChanged: (enteredEmail) => validateEmail(enteredEmail),
controller: correo,
),
),
Text(
message,
style: TextStyle(color: Colors.red),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: TextFormField(
// maxLength: 12,
inputFormatters: <TextInputFormatter>[
FilteringTextInputFormatter.digitsOnly,
new LengthLimitingTextInputFormatter(15),
],
keyboardType: TextInputType.number,
validator: (value) {
final intNumber = int.tryParse(value);
if (intNumber != null && intNumber <= 9) {
return null;
}
return 'Ingrese un número válido';
},
decoration: InputDecoration(
labelText: 'Celular',
prefixIcon: Icon(Icons.person),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide: BorderSide(color: Colors.blue, width: 2.0),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide:
BorderSide(color: Colors.blue[900], width: 2.0),
),
),
onChanged: (enteredCell) => validateCell(enteredCell),
controller: celular,
textInputAction: TextInputAction.done,
),
),
Text(
messagcell,
style: TextStyle(color: Colors.red),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: TextFormField(
obscureText: true,
inputFormatters: <TextInputFormatter>[
FilteringTextInputFormatter.allow(RegExp("[-0-9a-zA-Z]")),
new LengthLimitingTextInputFormatter(16),
],
decoration: InputDecoration(
labelText: 'Contraseña',
prefixIcon: Icon(Icons.lock),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide: BorderSide(color: Colors.blue, width: 2.0),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide:
BorderSide(color: Colors.blue[900], width: 2.0),
),
),
controller: passwd,
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: TextFormField(
obscureText: true,
inputFormatters: <TextInputFormatter>[
FilteringTextInputFormatter.allow(RegExp("[-0-9a-zA-Z]")),
new LengthLimitingTextInputFormatter(16),
],
decoration: InputDecoration(
labelText: 'Repita contraseña',
prefixIcon: Icon(Icons.lock),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide: BorderSide(color: Colors.blue, width: 2.0),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide:
BorderSide(color: Colors.blue[900], width: 2.0),
),
),
controller: passwd2,
),
),
if (showError)
const Text(
"Las contraseñas no son válidas",
style: TextStyle(color: Colors.red),
),
Row(
children: <Widget>[
Expanded(
child: ElevatedButton(
style: ElevatedButton.styleFrom(
onSurface: Colors.blue,
),
child: Text('Register',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: Colors.white)),
onPressed: () => [
if (isButtonActive)
{
setState(() => isButtonActive = false),
}
else
{null},
register(), //REGISTER FUNCTION
setState(() {})
],
),
),
//LOGIN BUTTON
Expanded(
child: ElevatedButton(
// color: Colors.amber[100],
child: Text('Login',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: Colors.black)),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => MyHomePage(),
),
);
},
),
),
],
)
],
),
),
),
);
}
}
In my TextFormFields have inputFormatters, for example:
inputFormatters: <TextInputFormatter>[
FilteringTextInputFormatter.allow(
RegExp("[-#._0-9a-zA-Z]")),
new LengthLimitingTextInputFormatter(36),
],
I need a function for detect in realtime the absence of any letter in uppercase, lowercase or numeric character. I don't know how make it. Please help me, thanks.
You can use the validator parameter on TextFormField. Your TextFormField will need to be inside a Form widget for this to work. Pass a key to your Form widget and call formKey.currentState?.validate() in the onChanged callback of your TextFormField.
Try out this code below:
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(
theme: ThemeData.light(),
home: const Scaffold(
body: Center(
child: CustomForm(),
),
),
);
}
}
class CustomForm extends StatefulWidget {
const CustomForm({Key? key}) : super(key: key);
#override
_CustomFormState createState() => _CustomFormState();
}
class _CustomFormState extends State<CustomForm> {
final formKey = GlobalKey<FormState>();
#override
Widget build(BuildContext context) {
return Form(
key: formKey,
child: Padding(
padding: const EdgeInsets.all(50),
child: TextFormField(
onChanged: (v) => formKey.currentState?.validate(),
validator: (v) {
String? message;
if (!RegExp(".*[0-9].*").hasMatch(v ?? '')) {
message ??= '';
message += 'Input should contain a numeric value 1-9. ';
}
if (!RegExp('.*[a-z].*').hasMatch(v ?? '')) {
message ??= '';
message += 'Input should contain a lowercase letter a-z. ';
}
if (!RegExp('.*[A-Z].*').hasMatch(v ?? '')) {
message ??= '';
message += 'Input should contain an uppercase letter A-Z. ';
}
return message;
},
),
),
);
}
}
Edit: You can also use a key directly on the TextFormField, if you want to only validate that particular field.
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(
theme: ThemeData.light(),
home: const Scaffold(
body: Center(
child: CustomForm(),
),
),
);
}
}
class CustomForm extends StatefulWidget {
const CustomForm({Key? key}) : super(key: key);
#override
_CustomFormState createState() => _CustomFormState();
}
class _CustomFormState extends State<CustomForm> {
final formKey = GlobalKey<FormState>();
final passwordFieldKey = GlobalKey<FormFieldState>();
#override
Widget build(BuildContext context) {
return Form(
key: formKey,
child: Padding(
padding: const EdgeInsets.all(50),
child: TextFormField(
key: passwordFieldKey,
onChanged: (v) => passwordFieldKey.currentState?.validate(),
validator: (v) {
String? message;
if (!RegExp(".*[0-9].*").hasMatch(v ?? '')) {
message ??= '';
message += 'Input should contain a numeric value 1-9. ';
}
if (!RegExp('.*[a-z].*').hasMatch(v ?? '')) {
message ??= '';
message += 'Input should contain a lowercase letter a-z. ';
}
if (!RegExp('.*[A-Z].*').hasMatch(v ?? '')) {
message ??= '';
message += 'Input should contain an uppercase letter A-Z. ';
}
return message;
},
),
),
);
}
}
I am working on an Android application. I want users to comment on the application and on the test.dart page I get the error The argument type 'CommentBox' can't be assigned to the parameter type 'Widget'
I have a constructor called CommentBox. But it doesn't let me use it for test.dart.
This is the test.dart code:
import 'package:city_travel_guide/pages/comment/comment.dart';
import 'package:flutter/material.dart';
class TestMe extends StatefulWidget {
#override
_TestMeState createState() => _TestMeState();
}
class _TestMeState extends State<TestMe> {
final formKey = GlobalKey<FormState>();
final TextEditingController commentController = TextEditingController();
List filedata = [
{
'name': 'Adeleye Ayodeji',
'pic': 'https://picsum.photos/300/30',
'message': 'I love to code'
},
{
'name': 'Biggi Man',
'pic': 'https://picsum.photos/300/30',
'message': 'Very cool'
},
{
'name': 'Biggi Man',
'pic': 'https://picsum.photos/300/30',
'message': 'Very cool'
},
{
'name': 'Biggi Man',
'pic': 'https://picsum.photos/300/30',
'message': 'Very cool'
},
];
Widget commentChild(data) {
return ListView(
children: [
for (var i = 0; i < data.length; i++)
Padding(
padding: const EdgeInsets.fromLTRB(2.0, 8.0, 2.0, 0.0),
child: ListTile(
leading: GestureDetector(
onTap: () async {
// Display the image in large form.
print("Comment Clicked");
},
child: Container(
height: 50.0,
width: 50.0,
decoration: new BoxDecoration(
color: Colors.blue,
borderRadius: new BorderRadius.all(Radius.circular(50))),
child: CircleAvatar(
radius: 50,
backgroundImage: NetworkImage(data[i]['pic'] + "$i")),
),
),
title: Text(
data[i]['name'],
style: TextStyle(fontWeight: FontWeight.bold),
),
subtitle: Text(data[i]['message']),
),
)
],
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Comment Page"),
backgroundColor: Colors.pink,
),
body: Container(
child: CommentBox(
userImage:
"https://lh3.googleusercontent.com/a-/AOh14GjRHcaendrf6gU5fPIVd8GIl1OgblrMMvGUoCBj4g=s400",
child: commentChild(filedata),
labelText: 'Write a comment...',
withBorder: false,
errorText: 'Comment cannot be blank',
sendButtonMethod: () {
if (formKey.currentState.validate()) {
print(commentController.text);
setState(() {
var value = {
'name': 'New User',
'pic':
'https://lh3.googleusercontent.com/a-/AOh14GjRHcaendrf6gU5fPIVd8GIl1OgblrMMvGUoCBj4g=s400',
'message': commentController.text
};
filedata.insert(0, value);
});
commentController.clear();
FocusScope.of(context).unfocus();
} else {
print("Not validated");
}
},
formKey: formKey,
commentController: commentController,
backgroundColor: Colors.black,
textColor: Colors.white,
sendWidget: Icon(Icons.send_sharp, size: 30, color: Colors.white),
),
),
);
}
}
This is the comment.dart:
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
class CommentBox {
Widget child;
dynamic formKey;
dynamic sendButtonMethod;
dynamic commentController;
String userImage;
String labelText;
String errorText;
Widget sendWidget;
Color backgroundColor;
Color textColor;
bool withBorder;
//Constructor
CommentBox(
{this.child,
this.formKey,
this.sendButtonMethod,
this.commentController,
this.userImage,
this.labelText,
this.errorText,
this.sendWidget,
this.backgroundColor,
this.textColor,
this.withBorder});
Widget build(BuildContext context) {
return Column(
children: [
Expanded(child: child),
Divider(
height: 1,
),
ListTile(
tileColor: backgroundColor,
leading: Container(
height: 40.0,
width: 40.0,
decoration: new BoxDecoration(
color: Colors.blue,
borderRadius: new BorderRadius.all(Radius.circular(50))),
child: CircleAvatar(
radius: 50, backgroundImage: NetworkImage(userImage)),
),
title: Form(
key: formKey,
child: TextFormField(
maxLines: 4,
minLines: 1,
cursorColor: textColor,
style: TextStyle(color: textColor),
controller: commentController,
decoration: InputDecoration(
enabledBorder: UnderlineInputBorder(
borderSide: BorderSide(color: textColor),
),
focusedBorder: UnderlineInputBorder(
borderSide: BorderSide(color: textColor)),
border: UnderlineInputBorder(
borderSide: BorderSide(color: textColor)),
labelText: labelText,
focusColor: textColor,
fillColor: textColor,
labelStyle: TextStyle(color: textColor),
),
validator: (value) => value.isEmpty ? errorText : null,
),
),
trailing: OutlineButton(
highlightedBorderColor: Colors.orange,
onPressed: sendButtonMethod,
borderSide: BorderSide.none,
child: sendWidget,
),
),
],
);
}
}
You need to extend your CommentBox with StatelessWidget , make your fields final , and override build method , like this
import 'package:flutter/material.dart';
class CommentBox extends StatelessWidget {
final Widget child;
final dynamic formKey;
final dynamic sendButtonMethod;
final dynamic commentController;
final String userImage;
final String labelText;
final String errorText;
final Widget sendWidget;
final Color backgroundColor;
final Color textColor;
final bool withBorder;
//Constructor
CommentBox(
{this.child,
this.formKey,
this.sendButtonMethod,
this.commentController,
this.userImage,
this.labelText,
this.errorText,
this.sendWidget,
this.backgroundColor,
this.textColor,
this.withBorder});
#override
Widget build(BuildContext context) {
return Column(
children: [
Expanded(child: child),
Divider(
height: 1,
),
ListTile(
tileColor: backgroundColor,
leading: Container(
height: 40.0,
width: 40.0,
decoration: new BoxDecoration(
color: Colors.blue,
borderRadius: new BorderRadius.all(Radius.circular(50))),
child: CircleAvatar(
radius: 50, backgroundImage: NetworkImage(userImage)),
),
title: Form(
key: formKey,
child: TextFormField(
maxLines: 4,
minLines: 1,
cursorColor: textColor,
style: TextStyle(color: textColor),
controller: commentController,
decoration: InputDecoration(
enabledBorder: UnderlineInputBorder(
borderSide: BorderSide(color: textColor),
),
focusedBorder: UnderlineInputBorder(
borderSide: BorderSide(color: textColor)),
border: UnderlineInputBorder(
borderSide: BorderSide(color: textColor)),
labelText: labelText,
focusColor: textColor,
fillColor: textColor,
labelStyle: TextStyle(color: textColor),
),
validator: (value) => value.isEmpty ? errorText : null,
),
),
trailing: OutlineButton(
highlightedBorderColor: Colors.orange,
onPressed: sendButtonMethod,
borderSide: BorderSide.none,
child: sendWidget,
),
),
],
);
}
}
the previous message is not entirely correct, so:
import 'package:flutter/material.dart';
class CommentBox extends StatelessWidget {
final Widget child;
final dynamic formKey;
final dynamic sendButtonMethod;
final dynamic commentController;
final String userImage;
final String labelText;
final String errorText;
final Widget sendWidget;
final Color backgroundColor;
final Color textColor;
final bool withBorder;
//Constructor
CommentBox(
this.child,
this.formKey,
this.sendButtonMethod,
this.commentController,
this.userImage,
this.labelText,
this.errorText,
this.sendWidget,
this.backgroundColor,
this.textColor,
this.withBorder );
#override
Widget build(BuildContext context) {
return Column(
children: [
Expanded(child: child),
Divider(
height: 1,
),
ListTile(
tileColor: backgroundColor,
leading: Container(
height: 40.0,
width: 40.0,
decoration: new BoxDecoration(
color: Colors.blue,
borderRadius: new BorderRadius.all(Radius.circular(50))),
child: CircleAvatar(
radius: 50, backgroundImage: NetworkImage(userImage)),
),
title: Form(
key: formKey,
child: TextFormField(
maxLines: 4,
minLines: 1,
cursorColor: textColor,
style: TextStyle(color: textColor),
controller: commentController,
decoration: InputDecoration(
enabledBorder: UnderlineInputBorder(
borderSide: BorderSide(color: textColor),
),
focusedBorder: UnderlineInputBorder(
borderSide: BorderSide(color: textColor)),
border: UnderlineInputBorder(
borderSide: BorderSide(color: textColor)),
labelText: labelText,
focusColor: textColor,
fillColor: textColor,
labelStyle: TextStyle(color: textColor),
),
validator: (value) {if (value == null || value.isEmpty) {return "some text";} return null;},
),
),
trailing: OutlinedButton(
style: OutlinedButton.styleFrom(
side: BorderSide.none,),
child: sendWidget,
onPressed: sendButtonMethod,
),
),
],
);
}
}
you should use OutlinedButton, because OutlineButton is deprecated