Related
I want to align the price text as it is in the first image, I tried to do it as in the second image, but I could not.
I want to do:
The problem:
This is the code I wrote to try to build the design.
TextFormField(
controller: startController,
keyboardType: TextInputType.number,
textAlign: TextAlign.end,
decoration: const InputDecoration().copyWith(
border: const UnderlineInputBorder(borderSide: BorderSide(color: kPinCodeColor)),
enabledBorder: const UnderlineInputBorder(borderSide: BorderSide(color: kPinCodeColor)),
disabledBorder: const UnderlineInputBorder(borderSide: BorderSide(color: kPinCodeColor)),
suffix: Text('JOD', style:
Theme.of(context).textTheme.headline6!.copyWith(fontSize:
Sizes.textSize_22)),
),
style: Theme.of(context).textTheme.headline6!.copyWith(fontSize:
Sizes.textSize_34),
)
You have make custom widget for this purpose. I made StatefulWidget I hope it make sense for you.
FocusNode is for handling focus change and animate the line underneath the Text.
MouseRagion is for handling hovering events.
IntrinsicWidth is for making TextFormInput expandable while typing.
This is the code:
class TextCustom extends StatefulWidget {
const TextCustom({Key? key, this.textController, this.suffix})
: super(key: key);
final TextEditingController? textController;
final String? suffix;
#override
State<TextCustom> createState() => _TextCustomState();
}
class _TextCustomState extends State<TextCustom> {
bool _isHovering = false;
bool _isFocased = false;
FocusNode textFocus = FocusNode();
#override
void initState() {
textFocus.addListener(() {
setState(() {
_isFocased = textFocus.hasFocus;
});
});
super.initState();
}
#override
Widget build(BuildContext context) {
return SizedBox(
child: MouseRegion(
onEnter: (event) {
setState(() {
_isHovering = true;
});
},
onExit: (event) {
setState(() {
_isHovering = false;
});
},
child: GestureDetector(
onTap: () {
textFocus.requestFocus();
},
child: InputDecorator(
expands: false,
isFocused: _isFocased,
isHovering: _isHovering,
decoration: const InputDecoration(),
child: Row(
crossAxisAlignment: CrossAxisAlignment.baseline,
textBaseline: TextBaseline.alphabetic,
children: [
IntrinsicWidth(
child: TextFormField(
focusNode: textFocus,
controller: widget.textController,
decoration: const InputDecoration(
constraints: BoxConstraints(minWidth: 20),
isCollapsed: true,
border: UnderlineInputBorder(borderSide: BorderSide.none),
),
style: Theme.of(context)
.textTheme
.headline6!
.copyWith(fontSize: 34),
),
),
const SizedBox(width: 8),
(widget.suffix != null)
? Text(
'JOD',
style: Theme.of(context)
.textTheme
.headline6!
.copyWith(fontSize: 22),
)
: Container(),
],
),
),
),
),
);
}
}
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 have created multiple text field using a single method in different file how i retrieve the value from them. I want to retrieve the value in different variables.
//class method
class CustomTextField {
static TextField display(BuildContext context, [String name, double size=16,IconData icon]) {
return new TextField(
textAlign: TextAlign.center,
style: CustomTextStyle.display(context, Colors.black38, size),
decoration: new InputDecoration(
alignLabelWithHint: true,
icon: new Icon(icon),
contentPadding:EdgeInsets.only(top: 30,right: 30,),
border: InputBorder.none,
hintText:"$name",
focusedBorder: InputBorder.none,
hintStyle: CustomTextStyle.display(context, Colors.grey, size),
),
);
}
}
//call method
new Container(
width: width,
height: height,
decoration: new BoxDecoration(
borderRadius: new BorderRadius.all(Radius.circular(20)),
gradient: new LinearGradient(
colors: [
Color.fromRGBO(252, 191, 93, 1),
Color.fromRGBO(255, 210, 119, 1),
Color.fromRGBO(252, 215, 85, 1),
],
begin: Alignment.bottomCenter,
end: Alignment.topCenter,
),
),
child: CustomTextField.display(context, name,16,icon),
),
First of all, I recommend that you use Stateless Widget to create your TextField instead of using a static function like this code below:
class CustomTextField extends StatelessWidget {
final Function(String) onChanged;
final String name;
final double size;
final IconData icon;
CustomTextField({
this.onChanged,
this.name,
this.size: 16,
this.icon,
});
Widget build(BuildContext context) {
return new TextField(
textAlign: TextAlign.center,
onChanged: onChanged,
style: CustomTextStyle.display(context, Colors.black38, size),
decoration: new InputDecoration(
alignLabelWithHint: true,
icon: new Icon(icon),
contentPadding: EdgeInsets.only(
top: 30,
right: 30,
),
border: InputBorder.none,
hintText: "$name",
focusedBorder: InputBorder.none,
hintStyle: CustomTextStyle.display(context, Colors.grey, size),
),
);
}
}
Then, create a function for the onChange field to receive the new value:
class App extends StatelessWidget {
Widget build(BuildContext context) {
return Scaffold(
body: Container(
width: width,
height: height,
decoration: new BoxDecoration(
borderRadius: new BorderRadius.all(Radius.circular(20)),
gradient: new LinearGradient(
colors: [
Color.fromRGBO(252, 191, 93, 1),
Color.fromRGBO(255, 210, 119, 1),
Color.fromRGBO(252, 215, 85, 1),
],
begin: Alignment.bottomCenter,
end: Alignment.topCenter,
),
),
child: CustomTextField(
// Here you get the value change
onChanged: (value) {
print('Text value changed');
print('New value: $value');
},
name: name,
size: 16,
icon: icon,
),
),
);
}
}
Use Function as a parameter for your CustomTextField and add it to onChanged parameter of TextField;
class CustomTextField {
static TextField display(BuildContext context, Function onChanged,
[String name, double size = 16, IconData icon]) {
return new TextField(
textAlign: TextAlign.center,
onChanged: onChanged,
style: CustomTextStyle.display(context, Colors.black38, size),
decoration: new InputDecoration(
alignLabelWithHint: true,
icon: new Icon(icon),
contentPadding: EdgeInsets.only(
top: 30,
right: 30,
),
border: InputBorder.none,
hintText: "$name",
focusedBorder: InputBorder.none,
hintStyle: CustomTextStyle.display(context, Colors.grey, size),
),
);
}
}
then get your value;
CustomTextField.display(
context,
(value) {
print(value);
},
name,
16,
icon,
),
you should provide a function to handle the onChange property of your custom text field.
here is how i used one in a project of mine:
the custom class widget
class MyTextField extends StatefulWidget {
final String title;
final Function onChange; // you can get the value from this function
final bool isPassword;
MyTextField(this.title, this.onChange, {this.isPassword = false});
#override
_MyTextFieldState createState() => _MyTextFieldState();
}
class _MyTextFieldState extends State<MyTextField> {
bool showPassword = false;
final _controller = TextEditingController();
#override
Widget build(BuildContext context) {
_controller.addListener(() {
setState(() {});
});
return Container(
margin: EdgeInsets.symmetric(vertical: 10),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
widget.title,
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 15,
),
),
SizedBox(height: 2),
TextField(
controller: _controller,
onChanged: widget.onChange,
obscureText: !showPassword && widget.isPassword,
decoration: InputDecoration(
suffixIcon: widget.isPassword
? IconButton(
icon: Icon(
Icons.remove_red_eye,
color: showPassword ? Colors.blue : Colors.grey,
),
onPressed: () {
setState(() => showPassword = !showPassword);
},
)
: IconButton(
icon: Icon(
Icons.clear,
color: _controller.text.isEmpty
? Colors.grey
: Colors.blue,
),
onPressed: () => _controller.clear()),
border: InputBorder.none,
fillColor: Color(0xfff3f3f4),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.blue, width: 5.0),
),
filled: true),
)
],
),
);
}
#override
void dispose() {
super.dispose();
_controller.dispose();
}
}
the use case:
MyTextField('Email', (value) => email = value.trim()), // body of onChange
MyTextField(
'Password',
(value) => password = value.trim(), // body of onChange
isPassword: true,
),
// value is what you get from the text fields.
Provide a TextEditingController as a parameter to construct your CustomTextField.
Minimum 1 alphabetic
Minimum 1 number
Allow only Character (_)
its failed
Pattern pattern = r'^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[_]).{8,}$';
RegExp regex = new RegExp(pattern);
Just check out this example that i have created :
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
TextEditingController userName = TextEditingController();
FocusNode usernameFocus = new FocusNode();
String errorText;
bool _isValid = false;
#override
void initState() {
super.initState();
userName.addListener(() {
String pattern = r'^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[_]).{8,}$';
RegExp regExp = new RegExp(pattern);
if (userName.text.isEmpty) {
setState(() {
errorText = 'Field cannot be empty';
});
} else {
if (!regExp.hasMatch(userName.text)) {
print('The does not matches the requirement');
setState(() {
// here you can add you text
errorText =
'Minimum 1 Capital letter, 1 small letter and 1 number and _';
_isValid = false;
});
} else {
print('the value matches');
setState(() {
errorText = null;
_isValid = true;
});
}
}
});
}
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Padding(
padding: const EdgeInsets.only(left: 20, right: 20),
child: TextField(
focusNode: usernameFocus,
decoration: new InputDecoration(
errorText: errorText,
prefixIcon: Icon(
Icons.supervised_user_circle,
color: Color(0xFF282858),
),
labelText: "UserName",
labelStyle: TextStyle(
fontFamily: "Poppins-Medium",
color: usernameFocus.hasFocus
? Colors.grey[600]
: Colors.grey[600]),
fillColor: Colors.white,
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.grey[400], width: 2.0),
borderRadius: BorderRadius.circular(10.0),
),
border: new OutlineInputBorder(
borderRadius: new BorderRadius.circular(10.0),
borderSide:
new BorderSide(color: Colors.grey[400], width: 2.0),
),
//fillColor: Colors.green
),
controller: userName,
keyboardType: TextInputType.text,
),
),
RaisedButton(
child: Text('Login'),
onPressed: () {
print(_isValid);
if (!_isValid) {
return;
}
print('validation sucess');
},
)
],
)),
),
);
}
}
let me know if it works.
You would need to use a validator on your Textfield. You would add a condtion in the validator function to check if it's false and returns the error meessage that you would like the user to see.
You can either validate by using autovalidate: true, or you can do it manualy by using .currentState.validate() on your form before saving.
so your code could look something like this
validator: (value) {
final alphanumeric = RegExp(YOUR_REGEX_HERE);
if (!alphanumeric.hasMatch(value)) return 'YOUR_ERROR_MESSAGE';
}
You can use this library
pubspec.yaml
flutter_form_builder: ^3.7.3
Code will be like this:
GlobalKey _addextKey = GlobalKey();
FormBuilder(
key: _addextKey,
child: ListView(
children: <Widget>[
TextFormField(
textInputAction: TextInputAction.next,
style: textStyle,
controller: _NameauthController,
// ignore: missing_return
validator: FormBuilderValidators.required(),
decoration: InputDecoration(
hintText: 'name',
hintStyle: TextStyle(fontSize: 12.0),
labelStyle: textStyle,
errorStyle:
TextStyle(color: Colors.red, fontSize: 12.0),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(5.0))),
keyboardType: TextInputType.text,
),
]);),
What I need to do is when the onPressed is called, I get the Textfield error when I don't enter text.
class _ExampleDialogTextState extends State<ExampleDialogText> {
FocusNode focusNode = FocusNode();
final textController = TextEditingController();
bool noText = false;
String nameList = "";
#override
void initState() {
super.initState();
nameList = "";
focusNode.addListener(() {
if (!focusNode.hasFocus) {
setState(() {
noText = nameList.length == 0;
});
FocusScope.of(context).requestFocus(focusNode);
}
});
}
TextField(
focusNode: focusNode,
autofocus: true,
controller: textController,
style: TextStyle(
color: Colors.black, fontSize: 14),
decoration: InputDecoration(
counterText: '',
errorText:
noText ? 'Value Can\'t Be Empty' : null,)
RaisedButton(
onPressed: () {
setState(() {
nameList.isEmpty
? noText = true
: noText = false;
});
},)
}
But still, with that code it doesn't work for me. Attached here is the entire class
code
Thank you!
Your Code is correct but you can not update state in ShowDialog Widget, so you have to return Statetful Widget in ShowDialog.
I added whole code which i change.
import 'package:flutter/material.dart';
class Consts {
Consts._();
static const double padding = 16.0;
static const double buttonPadding = 5.0;
}
class DeleteWidget extends StatefulWidget {
const DeleteWidget({Key key}) : super(key: key);
#override
_DeleteWidgetState createState() => _DeleteWidgetState();
}
class _DeleteWidgetState extends State<DeleteWidget> {
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.blueAccent,
floatingActionButton: FloatingActionButton(
onPressed: () {
showDialogNameList();
},
backgroundColor: Colors.orange,
child: Icon(
Icons.add,
color: Colors.purple,
size: 40,
),
),
);
}
showDialogNameList() {
return showDialog(
context: context,
builder: (context) {
return CustomeDialog1();
});
}
}
class CustomeDialog1 extends StatefulWidget {
CustomeDialog1({Key key}) : super(key: key);
#override
_CustomeDialog1State createState() => _CustomeDialog1State();
}
class _CustomeDialog1State extends State<CustomeDialog1> {
FocusNode focusNode = FocusNode();
final textController = TextEditingController();
bool noText = false;
String nameList = "";
#override
void initState() {
super.initState();
nameList = "";
focusNode.addListener(() {
if (!focusNode.hasFocus) {
setState(() {
noText = nameList.length == 0;
});
FocusScope.of(context).requestFocus(focusNode);
}
});
}
#override
Widget build(BuildContext context) {
var screenHeight = MediaQuery.of(context).size.height;
return Dialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(Consts.padding),
),
elevation: 0.0,
child: Container(
height: screenHeight / 3,
child: Stack(
children: <Widget>[
Container(
padding: EdgeInsets.only(
top: Consts.padding,
bottom: Consts.padding,
left: Consts.padding,
right: Consts.padding,
),
margin: EdgeInsets.only(top: 0),
decoration: BoxDecoration(
color: Colors.white,
shape: BoxShape.rectangle,
borderRadius: BorderRadius.circular(Consts.padding),
boxShadow: [
BoxShadow(
color: Colors.black26,
blurRadius: 10.0,
offset: const Offset(0.0, 10.0),
),
],
),
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
TextField(
focusNode: focusNode,
autofocus: true,
controller: textController,
cursorColor: Colors.white,
style: TextStyle(color: Colors.black, fontSize: 14),
decoration: InputDecoration(
counterText: '',
errorText: noText ? 'Value Can\'t Be Empty' : null,
hintText: 'List Name',
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.black),
),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.green),
),
labelStyle: TextStyle(
color: Colors.white, fontWeight: FontWeight.bold),
),
onChanged: (String text) {
nameList = text;
},
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Container(
width: 150.0,
height: 45.0,
child: RaisedButton(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
onPressed: () {
setState(() {
nameList.isEmpty
? noText = true
: noText = false;
});
},
padding:
EdgeInsets.fromLTRB(0.0, 0.0, 0.0, 0.0),
color: Color(0xFF2DA771),
child: Text('Add',
style: TextStyle(
color: Colors.white,
fontFamily: 'Roboto',
fontSize: 16)),
),
),
],
),
)
],
),
),
)
],
),
));
}
}