In my application, written in Flutter, I need an icon button to enable/disable input to it. I declared bool variables which are holding information to TextFormField to be enabled/disabled. But, it is not working as expected. It looks that it depends on type of keyboard, so until all characters keyboard is in use, it is not validated. So, if I disable field which allows only numeric keyboard, field input is not disabled until I switch to field with all characters kexboard. So, how can I disable input to TextFomField immediatelly?
`import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:aisscanning/data/database_helper.dart';
import 'package:aisscanning/data/inventoryitem.dart';
import 'package:aisscanning/data/masteritem.dart';
class InventoryScanning extends StatefulWidget {
InventoryScanning({Key key, this.title}) : super(key: key);
final String title;
#override
_InventoryScanningState createState() => new _InventoryScanningState();
}
class _InventoryScanningState extends State<InventoryScanning> {
static GlobalKey<FormState> _formKey = new GlobalKey<FormState>();
final TextEditingController teSku = TextEditingController();
final TextEditingController teDesc = TextEditingController();
final TextEditingController teLoc = TextEditingController();
final TextEditingController teSubLoc = TextEditingController();
final TextEditingController teQty = TextEditingController();
final TextEditingController tePrice = TextEditingController();
bool lockLoc = true;
bool lockSubLoc = true;
bool lockQty = true;
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("Item Scanning"),
backgroundColor: Colors.black,
),
resizeToAvoidBottomPadding: false,
body: Padding(
padding: const EdgeInsets.only(top: 12.0),
child: new Form(
key: _formKey,
autovalidate: true,
child: new ListView(
// padding: const EdgeInsets.symmetric(horizontal: 16.0),
padding: new EdgeInsets.all(8.0),
itemExtent: 60.0,
children: <Widget>[
new Row(
// Location
mainAxisSize: MainAxisSize.min,
children: <Widget>[
IconButton(
icon: const Icon(
Icons.lock,
color: const Color(0xFF167F67),
size: 25.0,
),
onPressed: () {
if (lockLoc == false) {
lockLoc = true;
} else {
lockLoc = false;
}
},
),
Expanded(
child: TextFormField(
controller: teLoc,
keyboardType: TextInputType.number,
enabled: lockLoc,
style: new TextStyle(
color: const Color(0xFF0f2638),
fontFamily: 'ProximaNova',
fontStyle: FontStyle.normal,
fontSize: 20.0,
),
decoration: new InputDecoration(
hintText: 'Enter Location or press Search Icon',
labelText: 'Location',
fillColor: Colors.white,
contentPadding: new EdgeInsets.symmetric(
vertical: 15.0, horizontal: 10.0),
border: new OutlineInputBorder(
borderRadius: new BorderRadius.circular(25.0),
borderSide: new BorderSide(),
),
labelStyle: TextStyle(
color: Colors.black,
fontWeight: FontWeight.w600,
fontSize: 20.0,
),
),
),
),
IconButton(
icon: const Icon(
Icons.search,
color: const Color(0xFF167F67),
size: 25.0,
),
onPressed: () {},
),
],
),
new Row(
// SubLocation
mainAxisSize: MainAxisSize.min,
children: <Widget>[
IconButton(
icon: const Icon(
Icons.lock,
color: const Color(0xFF167F67),
size: 25.0,
),
onPressed: () {
if (lockSubLoc == false) {
lockSubLoc = true;
} else {
lockSubLoc = false;
} },
),
Expanded(
child: TextFormField(
controller: teSubLoc,
enabled: lockSubLoc,
style: new TextStyle(
color: const Color(0xFF0f2638),
fontFamily: 'ProximaNova',
fontStyle: FontStyle.normal,
fontSize: 20.0,
),
decoration: new InputDecoration(
hintText: 'Enter SubLocation',
labelText: 'SubLocation',
contentPadding: new EdgeInsets.symmetric(
vertical: 15.0, horizontal: 10.0),
fillColor: Colors.white,
border: OutlineInputBorder(
borderRadius: new BorderRadius.circular(25.0),
borderSide: new BorderSide(),
),
//fillColor: Colors.green
labelStyle: TextStyle(
color: Colors.black,
fontWeight: FontWeight.w600,
fontSize: 16.0,
),
),
),
),
IconButton(
icon: const Icon(
Icons.search,
color: const Color(0xFF167F67),
size: 25.0,
),
onPressed: () {},
),
],
),
new Row(
// QTY
mainAxisSize: MainAxisSize.min,
children: <Widget>[
IconButton(
icon: const Icon(
Icons.lock,
color: const Color(0xFF167F67),
size: 25.0,
),
onPressed: () {
if (lockQty == false) {
lockQty = true;
} else {
lockQty = false;
}},
),
Expanded(
child: TextFormField(
controller: teQty,
textAlign: TextAlign.right,
keyboardType: TextInputType.number,
enabled: lockQty,
style: new TextStyle(
color: const Color(0xFF0f2638),
fontFamily: 'ProximaNova',
fontStyle: FontStyle.normal,
fontSize: 18.0,
),
decoration: new InputDecoration(
hintText: 'Enter Quantity',
labelText: 'Quantity',
contentPadding: new EdgeInsets.symmetric(
vertical: 15.0, horizontal: 10.0),
border: new OutlineInputBorder(
borderRadius: new BorderRadius.circular(30.0),
borderSide: new BorderSide(),
),
labelStyle: TextStyle(
color: Colors.black,
fontWeight: FontWeight.w600,
fontSize: 20.0,
),
),
),
),
],
),
new Row(
// Buttons
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
new RaisedButton(
child: new Text("Save"),
onPressed: () {
addRecord();
},
shape: new RoundedRectangleBorder(
borderRadius: new BorderRadius.circular(30.0)),
color: Colors.green,
elevation: 4.0,
),
new RaisedButton(
child: new Text("Cancel"),
onPressed: () {},
shape: new RoundedRectangleBorder(
borderRadius: new BorderRadius.circular(30.0)),
color: Colors.red,
elevation: 4.0,
),
],
),
]),
),
),
);
}
`
When Ever we need to update our screen UI we need to call SetState(). so In Your Code in onPressed Method.
onPressed: () {
setState(() {
if (lockLoc == false) {
lockLoc = true;
} else {
lockLoc = false;
}
});
},
Related
I am trying to create a scrollable sign up screen for when the keyboard pops up but my SingleChildScrollView widget doesn't seem to be working. I don't know whether this has to do with its placement in the stack or the inner column but help would be much appreciated. I've tried a ListView instead of a column, using the Expanded widget around the SingleChildScrollView but to no success.
Sign Up Screen
Sign Up Screen with Keyboard
An example to copy and run here.
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(
primarySwatch: Colors.blue,
),
home: const SignUpScreen(),
);
}
}
class SignUpScreen extends StatefulWidget {
const SignUpScreen({Key? key}) : super(key: key);
#override
_SignUpScreenState createState() => _SignUpScreenState();
}
class _SignUpScreenState extends State<SignUpScreen> {
final _formKey = GlobalKey<FormState>();
bool _obscurePassword = true;
Color _obscureColor = Colors.grey;
InputDecoration textFormFieldDecoration = InputDecoration(
filled: true,
fillColor: const Color(0xFFF5F5F5),
prefixIcon: const Padding(
padding: EdgeInsets.symmetric(horizontal: 20),
child: Icon(
Icons.email,
color: Colors.blueAccent,
size: 26,
),
),
suffixIcon: null,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(30),
borderSide: const BorderSide(color: Colors.white),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(30),
borderSide: const BorderSide(color: Colors.white),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(30),
borderSide: const BorderSide(color: Colors.white),
),
hintText: 'E-mail',
hintStyle: const TextStyle(
fontFamily: 'OpenSans',
fontSize: 18,
),
);
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
resizeToAvoidBottomInset: false,
// Shows circular progress indicator while loading
body:
// A stack lays items over one another.
Stack(
children: [
//The SizedBox provides the colored rounded aesthetic card behind the login.
SizedBox(
height: MediaQuery.of(context).size.height * 0.7,
child: Container(
color: Colors.redAccent,
),
),
Form(
key: _formKey,
child: Column(
// Keeps things in the center vertically
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
// Builds App Logo
Row(
// Keeps things in the center horizontally.
mainAxisAlignment: MainAxisAlignment.center,
children: const [
Text(
'Heart',
style: TextStyle(
fontSize: 34,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
Text(
'by AHG',
style: TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
],
),
const SizedBox(height: 30),
// Build sign up container card.
ClipRRect(
borderRadius: const BorderRadius.all(
Radius.circular(20),
),
child: SingleChildScrollView(
child: Container(
height: MediaQuery.of(context).size.height * 0.65,
width: MediaQuery.of(context).size.width * 0.85,
color: Colors.white,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 24),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
//Sign Up / Login Text
const Text(
'Sign Up',
style: TextStyle(
fontSize: 30,
fontWeight: FontWeight.w700,
color: Colors.black,
),
),
const SizedBox(height: 25),
// Email form field
TextFormField(
keyboardType: TextInputType.emailAddress,
decoration: textFormFieldDecoration.copyWith(
prefixIcon: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 20),
child: Icon(
Icons.email,
color: Theme.of(context)
.colorScheme
.secondary,
size: 26,
),
),
hintText: 'E-mail'),
autocorrect: false,
),
const SizedBox(height: 13),
// Build password form field
TextFormField(
obscureText: _obscurePassword,
keyboardType: TextInputType.text,
decoration: textFormFieldDecoration.copyWith(
prefixIcon: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 20),
child: Icon(
Icons.lock,
color: Theme.of(context)
.colorScheme
.secondary,
size: 26,
),
),
suffixIcon: Padding(
padding: const EdgeInsets.only(right: 25),
child: IconButton(
icon: const Icon(
Icons.remove_red_eye_rounded),
color: _obscureColor,
iconSize: 23,
onPressed: () {
setState(() {
_obscurePassword =
!_obscurePassword;
_obscureColor == Colors.grey
? _obscureColor =
Theme.of(context)
.colorScheme
.secondary
: _obscureColor = Colors.grey;
});
},
),
),
hintText: 'Password'),
autocorrect: false,
),
const SizedBox(height: 13),
// Build confirm password form field
TextFormField(
obscureText: _obscurePassword,
keyboardType: TextInputType.text,
decoration: textFormFieldDecoration.copyWith(
prefixIcon: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 20),
child: Icon(
Icons.lock,
color: Theme.of(context)
.colorScheme
.secondary,
size: 26,
),
),
suffixIcon: Padding(
padding: const EdgeInsets.only(right: 25),
child: IconButton(
icon: const Icon(
Icons.remove_red_eye_rounded),
color: _obscureColor,
iconSize: 23,
onPressed: () {
setState(() {
_obscurePassword =
!_obscurePassword;
_obscureColor == Colors.grey
? _obscureColor =
Theme.of(context)
.colorScheme
.secondary
: _obscureColor = Colors.grey;
});
},
),
),
hintText: 'Confirm'),
autocorrect: false,
),
// Login Button
const SizedBox(
height: 30,
),
SizedBox(
height: 1.4 *
(MediaQuery.of(context).size.height / 20),
width: 5 *
(MediaQuery.of(context).size.width / 10),
child: ElevatedButton(
child: const Text('Sign Up'),
onPressed: _validateInputs,
),
),
],
),
),
),
),
),
//Sign Up Text
const SizedBox(
height: 20,
),
TextButton(
onPressed: () {},
child: RichText(
text: TextSpan(children: [
TextSpan(
text: 'Don\'t have an account?',
style: TextStyle(
color: Colors.black,
fontSize: MediaQuery.of(context).size.height / 40,
fontWeight: FontWeight.w400,
),
),
TextSpan(
text: ' Login',
style: TextStyle(
color: Theme.of(context).colorScheme.primary,
fontSize: MediaQuery.of(context).size.height / 40,
fontWeight: FontWeight.bold,
),
)
]),
),
),
],
),
)
],
),
),
);
}
void _validateInputs() {
if (_formKey.currentState?.validate() != null) {
final _validForm = _formKey.currentState!.validate();
if (_validForm) {
_formKey.currentState!.save();
}
}
}
}
Change resizeToAvoidBottomInset to true
put SingleChildScrollView before Stack
Like this
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
resizeToAvoidBottomInset: true,
body: SingleChildScrollView(...)
Put the SingleChildScrollView as the Scaffold's body.
Scaffold(
resizeToAvoidBottomInset: true,
body:
SingleChildScrollView(child: ...)
)
I am making a todo-app using getx and get_storage and in the todoEditing screen in the title text field, whenever I add a new character, the previous value repeats itself and then the new character appears. This however only happens in the title text field and not in the notes text field. I am not able to find where the issue is originating from in the code and any help would be much appreciated.
class TodoScreen extends StatelessWidget {
final int? index;
final TodoController todoController = Get.find();
TodoScreen({this.index});
#override
Widget build(BuildContext context) {
String title = '';
String detail = '';
if (this.index != null) {
title = todoController.todos[index!].title;
detail = todoController.todos[index!].details;
}
Color add = Color(0xFFA8A8A8);
TextEditingController titleEditingController =
TextEditingController(text: title);
TextEditingController detailEditingController =
TextEditingController(text: detail);
return Scaffold(
appBar: AppBar(
title: Text((this.index == null) ? 'New Reminder' : 'Edit Reminder',
style: TextStyle(
fontSize: 22,
color: Theme.of(context).textTheme.headline2!.color)),
leadingWidth: 80.0,
leading: Center(
child: TextButton(
style: const ButtonStyle(
splashFactory: NoSplash.splashFactory,
),
onPressed: () {
Get.back();
},
child: const Text(
"Cancel",
style: TextStyle(fontSize: 20.0, color: Color(0xFF39A7FD)),
),
),
),
centerTitle: true,
actions: [
Center(
child: TextButton(
style: const ButtonStyle(
splashFactory: NoSplash.splashFactory,
),
onPressed: () {
if (this.index == null) {
todoController.todos.add(Todo(
details: detailEditingController.text,
title: titleEditingController.text,
));
} else {
var editing = todoController.todos[index!];
editing.title = titleEditingController.text;
editing.details = detailEditingController.text;
todoController.todos[index!] = editing;
}
;
Get.back();
},
child: Text((this.index == null) ? 'Add' : 'Update',
style:
TextStyle(color: Color(0xFF39A7FD), fontSize: 20.0))),
)
],
),
body: SafeArea(
child: Container(
width: double.infinity,
padding: const EdgeInsets.symmetric(horizontal: 15.0, vertical: 20.0),
child: Container(
decoration: BoxDecoration(
color: Color(0xFF414141),
boxShadow: const [
BoxShadow(
color: Color(0xFF414141),
offset: Offset(2.5, 2.5),
blurRadius: 5.0,
spreadRadius: 1.0,
), //B
],
borderRadius: BorderRadius.circular(14.0)),
padding:
const EdgeInsets.symmetric(horizontal: 24.0, vertical: 15.0),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
TextField(
controller: titleEditingController,
autofocus: true,
autocorrect: false,
cursorColor: Colors.grey,
maxLines: 1,
textInputAction: TextInputAction.next,
decoration: const InputDecoration(
hintText: "Title", border: InputBorder.none),
style: GoogleFonts.notoSans(
color: Color(0xFFA8A8A8), fontSize: 20.0),
),
const Divider(
color: Color(0xFF707070),
),
TextField(
controller: detailEditingController,
maxLines: null,
autocorrect: false,
cursorColor: Colors.grey,
textInputAction: TextInputAction.done,
decoration: const InputDecoration(
hintText: "Notes", border: InputBorder.none),
style: GoogleFonts.notoSans(
color: Color(0xFFA8A8A8), fontSize: 20.0),
),
],
)),
),
),
);
}
}
My approche would be like this:
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
class TodoScreen extends StatefulWidget {
final int? index;
const TodoScreen({Key? key, this.index}) : super(key: key);
#override
State<TodoScreen> createState() => _TodoScreenState();
}
class _TodoScreenState extends State<TodoScreen> {
final TodoController todoController = Get.find();
TextEditingController titleEditingController = TextEditingController();
TextEditingController detailEditingController = TextEditingController();
#override
void initState() {
super.initState();
if (widget.index != null) {
titleEditingController.text = todoController.todos[widget.index!].title;
detailEditingController.text =
todoController.todos[widget.index!].details;
}
// Color add = const Color(0xFFA8A8A8);
}
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
appBar: AppBar(
title: Text((widget.index == null) ? 'New Reminder' : 'Edit Reminder',
style: TextStyle(
fontSize: 22,
color: Theme.of(context).textTheme.headline2!.color)),
leadingWidth: 80.0,
leading: Center(
child: TextButton(
style: const ButtonStyle(
splashFactory: NoSplash.splashFactory,
),
onPressed: () {
Get.back();
},
child: const Text(
"Cancel",
style: TextStyle(fontSize: 20.0, color: Color(0xFF39A7FD)),
),
),
),
centerTitle: true,
actions: [
Center(
child: TextButton(
style: const ButtonStyle(
splashFactory: NoSplash.splashFactory,
),
onPressed: () {
if (widget.index == null) {
todoController.todos.add(Todo(
details: detailEditingController.text,
title: titleEditingController.text,
));
} else {
var editing = todoController.todos[widget.index!];
editing.title = titleEditingController.text;
editing.details = detailEditingController.text;
todoController.todos[widget.index!] = editing;
}
Get.back();
},
child: Text((widget.index == null) ? 'Add' : 'Update',
style: const TextStyle(
color: Color(0xFF39A7FD), fontSize: 20.0))),
)
],
),
body: Container(
width: double.infinity,
padding: const EdgeInsets.symmetric(horizontal: 15.0, vertical: 20.0),
child: Container(
decoration: BoxDecoration(
color: const Color(0xFF414141),
boxShadow: const [
BoxShadow(
color: Color(0xFF414141),
offset: Offset(2.5, 2.5),
blurRadius: 5.0,
spreadRadius: 1.0,
), //B
],
borderRadius: BorderRadius.circular(14.0)),
padding:
const EdgeInsets.symmetric(horizontal: 24.0, vertical: 15.0),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
TextField(
controller: titleEditingController,
autofocus: true,
autocorrect: false,
cursorColor: Colors.grey,
maxLines: 1,
textInputAction: TextInputAction.next,
decoration: const InputDecoration(
hintText: "Title", border: InputBorder.none),
style: GoogleFonts.notoSans(
color: const Color(0xFFA8A8A8), fontSize: 20.0),
),
const Divider(
color: Color(0xFF707070),
),
TextField(
controller: detailEditingController,
maxLines: null,
autocorrect: false,
cursorColor: Colors.grey,
textInputAction: TextInputAction.done,
decoration: const InputDecoration(
hintText: "Notes", border: InputBorder.none),
style: GoogleFonts.notoSans(
color: const Color(0xFFA8A8A8), fontSize: 20.0),
),
],
)),
),
),
);
}
}
Hello guys i am trying to check if the input fields for my register screen are empty and give an error message for each one if any is empty.
I added the text editing controllers and the booleans for if each box is empty or not.
Then on button press it checks if there is no text in any of the fields and should display the error message for each of the field.
Right now it tells me that the text provided in this "errorText: _emptyboxmail ? 'field cannot be empty' : null," is dead code for each one.
If i change the boolean to true then it shows that null is dead code in code i gave above.
How do i make this work without having dead code? The program runs as usual it just not show me the error message if i leave the boxes empty
import 'package:club_mark_2/styles/style.dart';
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'userPreferences/user_details_preference.dart';
class RegisterScreen extends StatefulWidget {
const RegisterScreen({Key? key}) : super(key: key);
#override
_RegisterScreenState createState() => _RegisterScreenState();
}
class _RegisterScreenState extends State<RegisterScreen> {
#override
Widget build(BuildContext context) {
final registerEmail = TextEditingController();
final registerPassword = TextEditingController();
final verifyPassword = TextEditingController();
final registerName = TextEditingController();
bool _emptyboxmail = false;
bool _emptyboxpass = false;
bool _emptyboxverify = false;
bool _emptyboxregistername = false;
double width = MediaQuery.of(context).size.width;
double height = MediaQuery.of(context).size.height;
#override
void dispose() {
// Clean up the controller when the widget is disposed.
registerEmail.dispose();
registerPassword.dispose();
verifyPassword.dispose();
registerName.dispose();
super.dispose();
}
return Scaffold(
backgroundColor: Colors.transparent,
body: SizedBox(
width: width,
height: height,
child: Stack(children: <Widget>[
Padding(
padding: const EdgeInsets.only(left: 15, top: 165, right: 15),
child: ListView(
children: [
Center(
child: Text(
'SIGN UP',
style: TextStyle(
color: Colors.white,
fontSize: 30.0,
fontWeight: FontWeight.bold,
fontFamily: 'Montserrat',
),
),
),
Container(
padding: EdgeInsets.all(8.0),
child: TextFormField(
style: TextStyle(color: Colors.white),
decoration: InputDecoration(
errorText: _emptyboxregistername
? 'field cannot be empty'
: null,
enabledBorder: OutlineInputBorder(
borderSide:
BorderSide(color: Colors.grey.withOpacity(0.5)),
borderRadius: BorderRadius.circular(20)),
hintText: 'Full Name',
hintStyle: TextStyle(color: kcMediumGreyColor),
labelStyle: TextStyle(color: Colors.white),
prefixIcon: const Icon(
Icons.person,
color: Colors.white,
),
),
controller: registerName,
),
),
SizedBox(
height: 5,
),
Container(
padding: EdgeInsets.all(8.0),
child: TextFormField(
style: TextStyle(color: Colors.white),
decoration: InputDecoration(
errorText: _emptyboxmail ? 'field cannot be empty' : null,
enabledBorder: OutlineInputBorder(
borderSide:
BorderSide(color: Colors.grey.withOpacity(0.5)),
borderRadius: BorderRadius.circular(20),
),
hintText: 'E-mail',
hintStyle: TextStyle(color: kcMediumGreyColor),
labelStyle: TextStyle(color: Colors.white),
prefixIcon: const Icon(
Icons.email,
color: Colors.white,
),
),
controller: registerEmail,
),
),
SizedBox(
height: 5,
),
Container(
padding: EdgeInsets.all(8.0),
child: TextFormField(
style: TextStyle(color: Colors.white),
obscureText: true,
decoration: InputDecoration(
errorText: _emptyboxpass ? 'field cannot be empty' : null,
enabledBorder: OutlineInputBorder(
borderSide:
BorderSide(color: Colors.grey.withOpacity(0.5)),
borderRadius: BorderRadius.circular(20),
),
hintText: 'Password',
hintStyle: TextStyle(color: kcMediumGreyColor),
labelStyle: TextStyle(
color: Colors.white,
),
prefixIcon: const Icon(
Icons.lock,
color: Colors.white,
),
),
controller: registerPassword,
),
),
SizedBox(
height: 5,
),
//VERIFY PASSWORD TEXT BOX
Container(
padding: EdgeInsets.all(8.0),
child: TextFormField(
style: TextStyle(color: Colors.white),
obscureText: true,
decoration: InputDecoration(
errorText:
_emptyboxverify ? 'field cannot be empty' : null,
enabledBorder: OutlineInputBorder(
borderSide:
BorderSide(color: Colors.grey.withOpacity(0.5)),
borderRadius: BorderRadius.circular(20),
),
hintText: 'Verify Password',
hintStyle: TextStyle(color: kcMediumGreyColor),
labelStyle: TextStyle(color: Colors.white),
prefixIcon: const Icon(
Icons.lock,
color: Colors.white,
),
),
//TEXT EDITING CONTROLLER
controller: verifyPassword,
),
),
SizedBox(
height: 20,
),
SizedBox(
height: 60,
child: TextButton(
style: ButtonStyle(
shape: MaterialStateProperty.all<RoundedRectangleBorder>(
RoundedRectangleBorder(
borderRadius: BorderRadius.circular(18.0),
),
),
),
// THE BUTTON THAT CHECKS IF THE BOOLEANS ARE TRUE OR FALSE FOR THE TEXT BEING EMPTY
onPressed: () {
registerEmail.text.isEmpty
? _emptyboxmail = true
: _emptyboxmail = false;
registerName.text.isEmpty
? _emptyboxregistername = true
: _emptyboxregistername = false;
registerPassword.text.isEmpty
? _emptyboxpass = true
: _emptyboxpass = false;
verifyPassword.text.isEmpty
? _emptyboxverify = true
: _emptyboxverify = false;
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => UserDetailsPreference(),
),
);
},
child: Text('Sign Up'),
),
),
SizedBox(
height: 20,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
padding: EdgeInsets.all(8.0),
child: Text(
"━━━━━ OR SIGN UP WITH ━━━━━",
style: TextStyle(color: kcMediumGreyColor),
),
),
],
),
SizedBox(
height: 20,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
InkWell(
onTap: () {},
child: Container(
decoration: BoxDecoration(),
child: ClipRRect(
borderRadius: BorderRadius.circular(10.0),
child: Image.asset('lib/assets/images/googleIcon.png',
width: 50.0, height: 50.0),
),
),
),
SizedBox(
width: 30,
),
InkWell(
onTap: () {},
child: Container(
decoration: BoxDecoration(),
child: ClipRRect(
// borderRadius: BorderRadius.circular(20.0),
child: Image.asset(
'lib/assets/images/facebookIcon.png',
width: 45.0,
height: 45.0),
),
),
),
],
),
SizedBox(
height: 20,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
padding: EdgeInsets.all(8.0),
child: Text(
"Already have an account?",
style: TextStyle(color: Colors.white),
),
),
Text(
"SIGN IN",
style: TextStyle(color: kcPrimaryColor),
),
],
),
],
),
),
]),
),
);
}
}
You have to move all your initializations and dispose method out of build method.
class _RegisterScreenState extends State<RegisterScreen> {
final registerEmail = TextEditingController();
final registerPassword = TextEditingController();
final verifyPassword = TextEditingController();
final registerName = TextEditingController();
bool _emptyboxmail = false;
bool _emptyboxpass = false;
bool _emptyboxverify = false;
bool _emptyboxregistername = false;
#override
void dispose() {
// Clean up the controller when the widget is disposed.
registerEmail.dispose();
registerPassword.dispose();
verifyPassword.dispose();
registerName.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
double width = MediaQuery.of(context).size.width;
double height = MediaQuery.of(context).size.height;
return Scaffold(
backgroundColor: Colors.transparent,
body: SizedBox(
width: width,
height: height,
// ... rest of your code
Create a Form with a GlobalKey
Add a TextFormField with validation logic
Create a button to validate and submit the form
https://flutter.dev/docs/cookbook/forms/validation
Please, how do i reset my currentstate Navigator such that when user type in the text field, the error message goes off instead of remaining until they hit the SUBMIT button. I know it's the use of the unChanged function, but I cant really figure that out.
Please, kindly help out. I have also attached my code below.
Thank you.
class ForgotPwd extends StatefulWidget {
#override
_ForgotPwdState createState() => _ForgotPwdState();
}
class _ForgotPwdState extends State<ForgotPwd> {
final TextEditingController _popEditingController = TextEditingController();
final _formKey = GlobalKey<FormState>();
#override
Widget build(BuildContext context) {
return Dialog(
child: Stack(
children: [
Container(
height: 270.0,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.all(
Radius.circular(10.0),
),
),
child: Padding(
padding: EdgeInsets.only(top: 40.0),
child: Form(
key: _formKey,
child: Column(children: [
Text(
'Forgot Password?',
style: TextStyle(
fontFamily: 'Work Sans',
fontSize: 18.0,
color: Color(0XFF25282B),
fontWeight: FontWeight.w600),
),
Padding(
padding:
EdgeInsets.only(left: 20.0, right: 20.0, top: 30.0),
child: TextFormField(
validator: (value) {
if (value.isEmpty == true) {
return 'Please enter email address';
} else {
return null;
}
},
controller: _popEditingController,
keyboardType: TextInputType.emailAddress,
decoration: InputDecoration(
prefixIcon: Icon(FontAwesomeIcons.envelope),
labelStyle: TextStyle(fontSize: 15.0),
hintText: 'Enter your email address',
hintStyle: TextStyle(fontSize: 15.0),
border: UnderlineInputBorder(
borderSide: BorderSide(color: Colors.black))),
),
),
Padding(
padding: EdgeInsets.all(30.0),
child: RaisedButton(
shape: RoundedRectangleBorder(
borderRadius: new BorderRadius.circular(10.0)),
color: Color(0XFFC20370),
onPressed: () {
setState(() {
if (_formKey.currentState.validate()) {
Navigator.of(context)
.pop(_popEditingController.text.toString());
}
});
},
child: Text('SUBMIT',
style: TextStyle(
color: Colors.white,
fontFamily: 'Work Sans',
fontSize: 18.0,
fontWeight: FontWeight.w600)),
))
]),
),
),
),
],
),
);
}
}
You can call _formKey.currentState.validate() in the onChanged method of the textfield
I didn't make use of Expanded widget but I don't know why I keep getting for this error.
Uncaught exception by widget library, Incorrect use of ParentDataWidget in four places I can't get where exactly the error is coming from. though it doesn't stop me from using the application but I feel it should be fixed. please can anyone help me?
This is my code below:
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:erg_app/Anchors.dart';
import 'package:erg_app/api/api.dart';
import 'package:shared_preferences/shared_preferences.dart';
class LogIn extends StatefulWidget {
#override
_LogInState createState() => _LogInState();
}
class _LogInState extends State<LogIn> {
bool _isLoading = false;
TextEditingController mailController = TextEditingController();
TextEditingController passwordController = TextEditingController();
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
ScaffoldState scaffoldState;
_showMsg() {
final snackBar = SnackBar(
content: Text(
'Invalid Username or Password',
style: (TextStyle(fontSize: 18)),
),
backgroundColor: Colors.amber[900],
);
_scaffoldKey.currentState.showSnackBar(snackBar);
}
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
FocusScopeNode currentFocus = FocusScope.of(context);
if (!currentFocus.hasPrimaryFocus) {
currentFocus.unfocus();
}
},
child: Scaffold(
key: _scaffoldKey,
body: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
stops: [0.0, 0.4, 0.9],
colors: [
Color(0XFF4CAF50),
Color(0xFF388E3C),
Color(0xFF075009),
],
),
),
child: ListView(
children: <Widget>[
/////////// background///////////
SizedBox(height: 30),
new Container(
width: 100.00,
height: 100.00,
decoration: new BoxDecoration(
image: new DecorationImage(
image: AssetImage('assets/images/icon.png'),
fit: BoxFit.contain,
),
)),
Column(
children: <Widget>[
Positioned(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Positioned(
left: 30,
top: 100,
child: Container(
margin: EdgeInsets.only(top: 50),
child: Center(
child: Text(
"Welcome",
style: TextStyle(
color: Colors.white,
fontSize: 23,
fontWeight: FontWeight.bold),
),
),
),
),
SizedBox(height: 30),
Card(
elevation: 4.0,
color: Colors.white,
margin: EdgeInsets.only(left: 20, right: 20),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15)),
child: Padding(
padding: const EdgeInsets.all(10.0),
// child: form(key: _formKey),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
///////////// Email//////////////
TextField(
style: TextStyle(color: Color(0xFF000000)),
controller: mailController,
cursorColor: Color(0xFF9b9b9b),
keyboardType: TextInputType.text,
decoration: InputDecoration(
prefixIcon: Icon(
Icons.account_circle,
color: Colors.grey,
),
hintText: "Username",
hintStyle: TextStyle(
color: Color(0xFF9b9b9b),
fontSize: 15,
fontWeight: FontWeight.normal),
focusedBorder: OutlineInputBorder(
borderSide:
BorderSide(color: Colors.green)),
),
),
/////////////// password////////////////////
TextField(
style: TextStyle(color: Color(0xFF000000)),
cursorColor: Color(0xFF9b9b9b),
controller: passwordController,
keyboardType: TextInputType.number,
obscureText: true,
decoration: InputDecoration(
prefixIcon: Icon(
Icons.vpn_key,
color: Colors.grey,
),
focusedBorder: OutlineInputBorder(
borderSide:
BorderSide(color: Colors.green)),
hintText: "Password",
hintStyle: TextStyle(
color: Color(0xFF9b9b9b),
fontSize: 15,
fontWeight: FontWeight.normal),
),
),
///////////// LogIn Botton///////////////////
Padding(
padding: const EdgeInsets.all(10.0),
child: FlatButton(
child: Padding(
padding: EdgeInsets.only(
top: 8,
bottom: 8,
left: 10,
right: 10),
child: Text(
_isLoading ? 'Loging...' : 'Login',
textDirection: TextDirection.ltr,
style: TextStyle(
color: Colors.white,
fontSize: 15.0,
decoration: TextDecoration.none,
fontWeight: FontWeight.normal,
),
),
),
color: Colors.green,
disabledColor: Colors.grey,
shape: new RoundedRectangleBorder(
borderRadius:
new BorderRadius.circular(20.0)),
onPressed: _isLoading ? null : _login,
),
),
],
),
),
),
//////////// new account///////////////
Padding(
padding: const EdgeInsets.only(top: 20),
child: InkWell(
onTap: () {
Navigator.push(
context,
new MaterialPageRoute(
builder: (context) => LogIn()));
},
child: Text(
'Forgot Your Password?',
textDirection: TextDirection.ltr,
style: TextStyle(
color: Colors.white,
fontSize: 15.0,
decoration: TextDecoration.none,
fontWeight: FontWeight.normal,
),
),
),
),
],
),
),
),
],
)
],
),
),
));
// Gesture ends here
}
}
this is the picture of the error message:
You have a Positioned widget inside Column widgets in different parts of your code.
A Positioned widget must be a descendant of a Stack, and the path from
the Positioned widget to its enclosing Stack must contain only
StatelessWidgets or StatefulWidgets
I pasted the above from Flutter docs and it says that a Positioned must be descendant of a Stack i.e you cannot have a position inside other Widgets aside from a Stack widget.
You should remove the Positioned widgets from your code. or wrap them with a Stack widget
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:erg_app/Anchors.dart';
import 'package:erg_app/api/api.dart';
import 'package:shared_preferences/shared_preferences.dart';
class LogIn extends StatefulWidget {
#override
_LogInState createState() => _LogInState();
}
class _LogInState extends State<LogIn> {
bool _isLoading = false;
TextEditingController mailController = TextEditingController();
TextEditingController passwordController = TextEditingController();
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
ScaffoldState scaffoldState;
_showMsg() {
final snackBar = SnackBar(
content: Text(
'Invalid Username or Password',
style: (TextStyle(fontSize: 18)),
),
backgroundColor: Colors.amber[900],
);
_scaffoldKey.currentState.showSnackBar(snackBar);
}
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
FocusScopeNode currentFocus = FocusScope.of(context);
if (!currentFocus.hasPrimaryFocus) {
currentFocus.unfocus();
}
},
child: Scaffold(
key: _scaffoldKey,
body: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
stops: [0.0, 0.4, 0.9],
colors: [
Color(0XFF4CAF50),
Color(0xFF388E3C),
Color(0xFF075009),
],
),
),
child: ListView(
children: <Widget>[
/////////// background///////////
SizedBox(height: 30),
new Container(
width: 100.00,
height: 100.00,
decoration: new BoxDecoration(
image: new DecorationImage(
image: AssetImage('assets/images/icon.png'),
fit: BoxFit.contain,
),
)),
Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Container(
margin: EdgeInsets.only(top: 50),
child: Center(
child: Text(
"Welcome",
style: TextStyle(
color: Colors.white,
fontSize: 23,
fontWeight: FontWeight.bold),
),
),
),
SizedBox(height: 30),
Card(
elevation: 4.0,
color: Colors.white,
margin: EdgeInsets.only(left: 20, right: 20),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15)),
child: Padding(
padding: const EdgeInsets.all(10.0),
// child: form(key: _formKey),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
///////////// Email//////////////
TextField(
style: TextStyle(color: Color(0xFF000000)),
controller: mailController,
cursorColor: Color(0xFF9b9b9b),
keyboardType: TextInputType.text,
decoration: InputDecoration(
prefixIcon: Icon(
Icons.account_circle,
color: Colors.grey,
),
hintText: "Username",
hintStyle: TextStyle(
color: Color(0xFF9b9b9b),
fontSize: 15,
fontWeight: FontWeight.normal),
focusedBorder: OutlineInputBorder(
borderSide:
BorderSide(color: Colors.green)),
),
),
/////////////// password////////////////////
TextField(
style: TextStyle(color: Color(0xFF000000)),
cursorColor: Color(0xFF9b9b9b),
controller: passwordController,
keyboardType: TextInputType.number,
obscureText: true,
decoration: InputDecoration(
prefixIcon: Icon(
Icons.vpn_key,
color: Colors.grey,
),
focusedBorder: OutlineInputBorder(
borderSide:
BorderSide(color: Colors.green)),
hintText: "Password",
hintStyle: TextStyle(
color: Color(0xFF9b9b9b),
fontSize: 15,
fontWeight: FontWeight.normal),
),
),
///////////// LogIn Botton///////////////////
Padding(
padding: const EdgeInsets.all(10.0),
child: FlatButton(
child: Padding(
padding: EdgeInsets.only(
top: 8,
bottom: 8,
left: 10,
right: 10),
child: Text(
_isLoading ? 'Loging...' : 'Login',
textDirection: TextDirection.ltr,
style: TextStyle(
color: Colors.white,
fontSize: 15.0,
decoration: TextDecoration.none,
fontWeight: FontWeight.normal,
),
),
),
color: Colors.green,
disabledColor: Colors.grey,
shape: new RoundedRectangleBorder(
borderRadius:
new BorderRadius.circular(20.0)),
onPressed: _isLoading ? null : _login,
),
),
],
),
),
),
//////////// new account///////////////
Padding(
padding: const EdgeInsets.only(top: 20),
child: InkWell(
onTap: () {
Navigator.push(
context,
new MaterialPageRoute(
builder: (context) => LogIn()));
},
child: Text(
'Forgot Your Password?',
textDirection: TextDirection.ltr,
style: TextStyle(
color: Colors.white,
fontSize: 15.0,
decoration: TextDecoration.none,
fontWeight: FontWeight.normal,
),
),
),
),
],
),
),
],
)
],
),
),
));
// Gesture ends here
}
}