Related
I'm new to flutter. I'm creating a login page. but now getting the below error in my code when I add remember me and forget password buttons into a Row Widget to display in one row. how to solve this. for your reference I have attached the full code and UI. login_screen full dart code , login_screen UI image
RenderBox was not laid out: _RenderListTile#c9c23
relayoutBoundary=up24 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
'package:flutter/src/rendering/box.dart': Failed assertion: line 1982
pos 12: 'hasSize'
#override
Widget build(BuildContext context) {
return SingleChildScrollView(
child: Form(
key: _formKey,
autovalidateMode: AutovalidateMode.disabled,
child: Container(
margin: const EdgeInsets.all(20.0),
child: Column(
children: [
SizedBox(
height: 40,
),
TextFormField(
controller: emailEditingController,
enabled: true,
decoration: InputDecoration(
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(30.0),
),
hintText: "Email/ Username",
hintStyle: TextStyle(
color: textGrey, fontFamily: "Dubai", fontSize: 14),
),
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: 20,
),
TextFormField(
controller: passwordEditingController,
obscureText: _isObscure,
enabled: typing,
decoration: InputDecoration(
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(30.0),
),
suffixIcon: IconButton(
icon: Icon(_isObscure
? Icons.visibility
: Icons.visibility_off),
onPressed: () {
setState(() {
_isObscure = !_isObscure;
});
}),
hintText: "Password",
hintStyle: TextStyle(
color: textGrey, fontFamily: "Dubai", fontSize: 14)),
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!;
},
),
// this is where I got an error.
Row(
// mainAxisAlignment: MainAxisAlignment.start,
children: [
CheckboxListTile(
title: const Text(
"Remember Me",
style: TextStyle(
color: textGrey, fontFamily: "Dubai", fontSize: 14),
),
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
),
SizedBox(
width: 5,
),
TextButton(
child: Text(
"Forget Password",
style: TextStyle(
color: textGrey, fontFamily: "Dubai", fontSize: 14),
),
onPressed: () {
//Get.to(ForgetPassword());
},
)
],
),
SizedBox(
height: 30,
),
isLoading
? SpinKitDualRing(
color: mainGreen,
size: 40,
)
: GestureDetector(
child: MainButton("Login"),
onTap: () {
},
),
SizedBox(
height: 30,
),
GestureDetector(
child: MainButton("Signup"),
onTap: () {
},
),
],
),
),
),
);
}
The issue is coming from CheckboxListTile while it is inside the Row,
Wrap CheckboxListTile with Expanded widget, it will get available width inside row.
Row(
children: [
Expanded(
child: CheckboxListTile(
More about Expanded.
Hi I have created a default form field, in a separate dart file called components, and I have login_screen.dart also.
there are many errors I don't know how to fix it, and make the code work, I will put down the code of the component.dart code:
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
Widget defaultButton(
{double width = double.infinity,
Color background = Colors.blue,
double radius = 10.0,
required Function function,
required String text,
bool isUpperCase = true}) =>
Container(
height: 40.0,
width: width,
child: MaterialButton(
onLongPress: () {},
onPressed: function(),
child: Text(
isUpperCase ? text.toUpperCase() : text.toLowerCase(),
style: TextStyle(color: Colors.white),
)),
decoration: BoxDecoration(
borderRadius: BorderRadiusDirectional.circular(radius),
color: background,
),
);
Widget defaultFormFeild({
required TextEditingController controller,
required TextInputType type,
Function onSubmit,
Function onChange,
required Function validate,
required var label,
required IconData prefix,
}) =>
TextFormField(
controller: controller,
keyboardType: type,
onFieldSubmitted: onSubmit(),
onChanged: onChange(),
validator: validate(),
decoration: InputDecoration(
labelText: label,
prefixIcon: Icon(prefix),
border: OutlineInputBorder()
),
);
and here is the code of the login_screen.dart:
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:udemy_flutter/shared/components/components.dart';
class LoginScreen extends StatelessWidget {
var emailController = TextEditingController();
var passController = TextEditingController();
var formKey = GlobalKey<FormState>();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Padding(
padding: const EdgeInsets.all(20.0),
child: Center(
child: SingleChildScrollView(
child: Form(
key: formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'Login',
style: TextStyle(
fontSize: 40.0,
fontWeight: FontWeight.bold
),
),
const SizedBox(
height: 40.0,
),
defaultFormFeild(
controller: emailController,
label: 'Email',
prefix: Icons.email,
type: TextInputType.emailAddress,
validate: (String value){
if(value.isEmpty != null){
return 'Email Cannot Be Empty';
}
return null;
}
),
const SizedBox(
height: 15.0,
),
TextFormField(
controller: passController,
obscureText: true,
keyboardType: TextInputType.visiblePassword,
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: 'Password',
prefixIcon: Icon(
Icons.lock
),
suffixIcon: Icon(
Icons.remove_red_eye,
)
),
onChanged: (value) {
print(value);
},
onFieldSubmitted: (value) {
print(value);
},
validator: (value) {
if(value!.isEmpty){
return 'Password cannot be empty';
}
return null;
},
),
const SizedBox(
height: 10.0,
),
defaultButton(
function: (){
print(emailController.text);
print(passController.text);
},
text: 'Login',
),
const SizedBox(
height: 10.0,
),
defaultButton(
text: 'ReGister',
function: () {
print('You have just clicked on register');
},
background: Colors.red,
isUpperCase: false
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text('Don\'t you have an account?'),
TextButton(onPressed: () {}, child: const Text(
'Register Now'
))
],
)
],
),
),
),
),
),
);
}
}
Idk if all the problems came from a null-safety feature in a flutter because I'm new in this technology.
Why
The reason this happens is because with null safety enabled, your functions onSubmit and onChange can't be null.
Solution
I would do it this way:
Widget defaultFormFeild({
required TextEditingController controller,
required TextInputType type,
Function? onSubmit, //Add question mark
Function? onChange, //Add question mark
required Function validate,
required var label,
required IconData prefix,
}) =>
TextFormField(
controller: controller,
keyboardType: type,
onFieldSubmitted: onSubmit != null? onSubmit() : null, //do null checking
onChanged: onChange != null? onChange() : null, //do null checking
validator: validate(),
decoration: InputDecoration(
labelText: label,
prefixIcon: Icon(prefix),
border: OutlineInputBorder()
),
);
import 'package:flutter/material.dart';
import 'package:mmitra/widgets/header.dart';
import 'home.dart';
class CreateAccount extends StatefulWidget {
#override
_CreateAccountState createState() => _CreateAccountState();
}
class _CreateAccountState extends State<CreateAccount> {
late String username;
final _key = Global Key<FormState>();
#override
Widget build(BuildContext parentContext) {
return Scaffold(
appBar: header(context, titleText: 'Create Account'),
body: ListView(children: [
Container(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Padding(
padding: EdgeInsets.only(top: 25),
child: Center(
child: Text(
'Create a username',
style: TextStyle(fontSize: 25.0),
),
),
),
Padding(
padding: EdgeInsets.all(16.0),
child: Form(
child: TextFormField(
key: _key,
// controller: myController,
onSaved: (val) => username = val!,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelStyle: TextStyle(fontSize: 15),
labelText: 'Username',
hintText: 'Must be at least 3 Characters'),
),
),
),
GestureDetector(
onTap: () {
_key.currentState!.save();
Navigator.pop(context, username
);
},
child: Container(
height: 50,
width: 300,
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.circular(7)),
child: Center(
child: Text(
'Submit',
style:
TextStyle(fontSize: 15, fontWeight: FontWeight.bold),
),
),
),
),
],
),
),
]),
);
}
}
and I'm getting below shown errors:
Exception caught by gesture
The following Cast Error was thrown while handling a gesture
Null check operator used on a null value
I just want to get the textfromfield value and i want to pass it to the home.dart page in order to create the document in firebase collection
you must define a EditTextControll() ex:textController and set it to TextFormField to controller paramerter , and then get text as textController.text and pass with Navigatoer .
for pass wihtin first screen to two screen
Firstly /
TextEditingController controller = TextEditingController();
Secoundly /
body: Form(
child: TextFormField(
controller: controller,
onTap: (){
//here SettingsScreen() is example
// name is paramerter in the secound screen
Navigator.push(context,
MaterialPageRoute(builder: (context)=>SettingsScreen(name:controller.text),),
);
},
),
),
You added key in TextFormField
Form(
child: TextFormField(
key: _key,
// controller: myController,
onSaved: (val) => username = val!,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelStyle: TextStyle(fontSize: 15),
labelText: 'Username',
hintText: 'Must be at least 3 Characters'),
),
),
),
Remove it from TextFormField and Add it in Form
Just Like:
Form(
key: _key,
child: TextFormField(
// controller: myController,
onSaved: (val) => username = val!,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelStyle: TextStyle(fontSize: 15),
labelText: 'Username',
hintText: 'Must be at least 3 Characters'),
),
),
),
This will Solve your Issue.
I am trying to move to other TextFormField but whenever I lose focus from first TextFormField text became empty, I search about this issue but I don't find any solution till now.
var _formKey = GlobalKey<FormState>();
Note note;
TextEditingController titleController=TextEditingController();
TextEditingController descriptionController=TextEditingController();
#override
Widget build(BuildContext context) {
TextStyle textStyle=Theme.of(context).textTheme.title;
titleController.text=note.title;
descriptionController.text=note.description;
// TODO: implement build
return WillPopScope(
onWillPop: (){
moveToLastScreen();
},
child:Scaffold(
appBar: AppBar(
title: Text("appBarTitle"),
leading: IconButton(icon:Icon(Icons.arrow_back),onPressed: (){
moveToLastScreen();
},),
),
body: Form(
key: _formKey,
child: Padding(
padding: EdgeInsets.only(top: 15.0,left: 15.0,right: 10.0),
child: ListView(
children: <Widget>[
//1st element
Padding(
padding: EdgeInsets.only(top: 15.0,bottom: 15.0,),
child: TextFormField(
validator: (String value){
if(value.isEmpty)
{
return "Please enter Title";
}
},
controller: titleController,
style: textStyle,
onSaved: (value){
debugPrint("Something changed in title Text field");
updateTitle();
},
/*onChanged: (value){
debugPrint("Something changed in title Text field");
updateTitle();
},*/
decoration: InputDecoration(
labelText: "Title",
labelStyle: textStyle,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(5.0)
)
),
),
),
//2nd element
Padding(
padding: EdgeInsets.only(top: 15.0,bottom: 15.0,),
child: TextFormField(
validator: (String value){ //2nd step for form with validation
if(value.isEmpty)
{
return "Please enter principle amount";
}
},
onSaved: (value){
debugPrint("Something changed in Description Text field");
updateDescription();
},
controller: descriptionController,
style: textStyle,
/*onChanged: (value){
debugPrint("Something changed in Description Text field");
updateDescription();
},*/
decoration: InputDecoration(
labelText: "Description",
labelStyle: textStyle,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(5.0)
)
),
),
),
//3th element
Padding(
padding: EdgeInsets.only(top: 15.0,bottom: 15.0),
child: Row(
children: <Widget>[
Expanded(
child: RaisedButton(
color: Theme.of(context).primaryColorDark,
textColor: Theme.of(context).primaryColorLight,
child: Text("Save",textScaleFactor: 1.5,),
onPressed: (){
setState(() {
if(_formKey.currentState.validate()) {
debugPrint("Save Pressed");
_save();
}
});
}
),
),
Container(width: 5.0,),
Expanded(
child: RaisedButton(
color: Theme.of(context).primaryColorDark,
textColor: Theme.of(context).primaryColorLight,
child: Text("Delete",textScaleFactor: 1.5,),
onPressed: (){
setState(() {
debugPrint("Delete Pressed");
_delete();
});
}
),
),
],
),
),
],
),
)),
));
}
Please suggest me I am new in flutter.
Remove titleController.text=note.title; descriptionController.text=note.description; from your build method and place it in initState method.
You will lose the value in the textField because those lines get executed anytime there is a rebuild, thereby replacing the values gotten from the textFields and replacing it with note.title and note.description which are empty at that point.
In other words, remove those lines and add this to your code.
#override
void initState() {
super.initState();
titleController.text=note.title;
descriptionController.text=note.description;
}
I am trying to catch the tap event on TextFormField into a flutter Form.
I use a GestureDetector to do that with the TextFormField as child but nothing is firing when a click on it :
#override
Widget build(BuildContext context) {
return new Scaffold(
key: _scaffoldKey,
appBar: new AppBar(title: const Text('Recherche de sorties')),
body: new DropdownButtonHideUnderline(
child: new Form(
key: _formKey,
autovalidate: _autovalidate,
child: new ListView(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
children: <Widget>[
new DatePicker(
labelText: 'Date',
selectedDate: widget.request.dateDebut,
initialDate: widget.request.dateDebut,
firstDate: new DateTime.now().add(new Duration(days: -1)),
lastDate: new DateTime.now().add(new Duration(days: 365 * 4)),
selectDate: (DateTime value) {
setState(() {
widget.request.dateDebut = value;
});
},
datePickerMode: DatePickerMode.day,
icon: const Icon(Icons.date_range),
),
new InputDecorator(
decoration: const InputDecoration(
labelText: 'Rayon',
hintText: '-- Choisissez un rayon --',
icon: const Icon(Icons.settings_backup_restore),
),
isEmpty: widget.request.rayon == null,
child: new DropdownButton<String>(
value: widget.request.rayon.toString(),
isDense: true,
onChanged: (String newValue) {
setState(() {
widget.request.rayon = int.parse(newValue);
});
},
items: _rayons.keys.map((int key) {
return new DropdownMenuItem<String>(
value: key.toString(),
child: new Text(_rayons[key]),
);
}).toList(),
),
),
new GestureDetector(
onTap: () async {
print("Container clicked");
Prediction p = await showGooglePlacesAutocomplete(
context: context,
apiKey: Consts.googlePlacesApiKey,
mode: Mode.fullscreen,
language: "fr",
components: [new Component(Component.country, "fr")]);
if (p != null) {
(_scaffoldKey.currentState).showSnackBar(
new SnackBar(content: new Text(p.description)));
}
},
child: new TextFormField(
// controller: controller,
decoration: const InputDecoration(
icon: const Icon(Icons.room),
hintText: 'Où êtes vous ?',
labelText: 'Localisation',
),
),
),
new Container(
padding: const EdgeInsets.all(20.0),
alignment: Alignment.center,
child: new Align(
alignment: const Alignment(0.0, -0.2),
child: new ButtonBar(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
new RaisedButton(
child: const Text('ANNULER'),
onPressed: _fermerCritereRecherche,
),
new RaisedButton(
child: const Text('VALIDER'),
onPressed: _valider,
),
],
),
)),
]),
),
),
);
}
If i replace :
new GestureDetector(
onTap: () async {
print("Container clicked");
Prediction p = await showGooglePlacesAutocomplete(
context: context,
apiKey: Consts.googlePlacesApiKey,
mode: Mode.fullscreen,
language: "fr",
components: [new Component(Component.country, "fr")]);
if (p != null) {
(_scaffoldKey.currentState).showSnackBar(
new SnackBar(content: new Text(p.description)));
}
},
child: new TextFormField(
// controller: controller,
decoration: const InputDecoration(
icon: const Icon(Icons.room),
hintText: 'Où êtes vous ?',
labelText: 'Localisation',
),
),
),
By a simple Container it is working :
new GestureDetector(
onTap: () async {
print("Container clicked");
Prediction p = await showGooglePlacesAutocomplete(
context: context,
apiKey: Consts.googlePlacesApiKey,
mode: Mode.fullscreen,
language: "fr",
components: [new Component(Component.country, "fr")]);
if (p != null) {
(_scaffoldKey.currentState).showSnackBar(
new SnackBar(content: new Text(p.description)));
}
},
child: new Container(
width: 80.0,
height: 80.0,
margin: new EdgeInsets.all(10.0),
color: Colors.black),
),
Do you have any ideas how to make GestureDetector work with TextFormField ? Maybe with a controller but i have tried without any success
Thanks in advance
Simply use onTap Method of TextFormField:
TextFormField(
onTap: () {
print("I'm here!!!");
}
)
Wrap TextFormField widget With AbsorbPointer widget , then OnTap() works definitely
here is an example:-
GestureDetector(
onTap: () => dialog(),
child: AbsorbPointer(
child: TextFormField(
textInputAction: TextInputAction.newline,
decoration: new InputDecoration(
fillColor: Colors.grey,
border: OutlineInputBorder(
borderRadius:
BorderRadius.all(Radius.circular(6.0)),
borderSide:
BorderSide(color: Colors.grey[100]),
gapPadding: 4),
labelText: "Enter your mood",
labelStyle: TextStyle(
letterSpacing: 1,
color: Colors.grey,
fontSize: 13),
hintMaxLines: 1),
validator: (val) {
if (val == "") return "Field can't be empty";
},
keyboardType: TextInputType.text,
enabled: true,
textAlign: TextAlign.justify,
minLines: 3,
autofocus: false,
style: new TextStyle(
fontSize: 16.0,
color: Colors.black,
),
maxLines: 10,
),
),
),
Wrap AbsorbPointer Widget with Gesture Detector, and then work in onTap(). it will work fine.
I have found a solution by using the InputDecorator (from the flutter gallery) :
child: new InputDecorator(
decoration: const InputDecoration(
labelText: 'Localisation',
icon: const Icon(Icons.room),
),
child: widget.request.localisationLibelle != null
? new Text(widget.request.localisationLibelle)
: new Text("-- Choisissez un lieu --"),
),
Instead of using a TextFormField that catch the tap at the place of the GestureDetector I use a simple child Text of the InputDecorator widget.
I just solved this myself using Flutter 0.6.0.
The GestureDetector object takes in a behavior property from this enum to determine how to defer actions.
Small snippet of the GestureDetector taking priority over a TextFormField:
new GestureDetector(
onTap: onTap,
behavior: HitTestBehavior.opaque,
child: new TextFormField(
enabled: onTap == null,
*other stuff here*
),
)
The onTap object is a Function object I declare outside of this. I also set the enabled property based on my onTap object, so I can ensure that if I want to capture a tap, the text form field is disabled.
onTap function is working but if you use it with InputDecoration { enabled: false }, it will not working.
decoration: InputDecoration(
enabled: false, // not working when on tap
isDense: true,
filled: true,
fillColor: _listRadioItemPosition.isEmpty ? Colors.grey[100] : Colors.white,
border: UnderlineInputBorder(borderSide: BorderSide(color: Color(0xFFC4C4C4), width: 1)),
),
onTap: (){
displayBottomSheetPosition(context);
},