Flutter, TextFormField: KeyBoard immediately disappears when it's opened - flutter

I'm working on a login screen and I use TextFormField to insert a user's email and password. When I use a tablet emulator the keyboard immediately disappears after I click on it. It isn't for every emulator. With my real phone it works and also with another emulator. But with other three emulators it doesn't work. This are the imports:
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:prcarpolimi/Internet/NetworkCheck.dart';
import 'package:prcarpolimi/auth/signUp.dart';
import 'package:prcarpolimi/auth/forgot_password.dart';
import 'package:prcarpolimi/models/marker_to_pass.dart';
import 'package:prcarpolimi/models/userModel.dart';
import 'package:prcarpolimi/homepage.dart';
import 'package:prcarpolimi/services/services.dart';
import '../models/static_user.dart';
import 'package:intl/intl.dart';
And this is my code:
final Service loginService;
const Login({Key? key, required this.loginService}) : super(key: key);
#override
State<Login> createState() => _LoginState();
}
class _LoginState extends State<Login> {
UserModel userModel = UserModel();
static final _emailController = TextEditingController();
static final _passwordController = TextEditingController();
static final _formKey = GlobalKey<FormState>();
bool from = true;
Future<User?> loginUsingEmailPassword(
{required String email,
required String password,
required BuildContext context}) async {
User? user;
try {
user = await widget.loginService.signInWithemailandpass(email, password);
} on FirebaseAuthException catch (e) {
if (e.code == "user-not-found") {}
Fluttertoast.showToast(
msg: 'Login failed :( wrong email or password', fontSize: 20);
return null;
}
showDialog(
context: context,
barrierDismissible: false,
builder: (context) => const Center(child: CircularProgressIndicator()),
);
return user;
}
_finishReservation(User user) async {
var data = await widget.loginService
.firebasefirestore()
.collection('users')
.doc(user.uid)
.collection('booking-out')
.get();
if (data.docs.isNotEmpty) {
for (var bookOut in data.docs) {
String data = bookOut.data()['date'];
final splitted = data.split('-');
String finalDate = splitted[1];
DateTime dayEnd = DateFormat("dd/MM/yyyy").parse(finalDate);
if (dayEnd.compareTo(DateTime.now()) < 0) {
await widget.loginService
.firebasefirestore()
.collection('users')
.doc(user.uid)
.collection('booking-out')
.doc(bookOut.data()['bookingId'])
.update({'status': 'f'});
}
}
}
var data2 = await widget.loginService
.firebasefirestore()
.collection('users')
.doc(user.uid)
.collection('cars')
.get();
if (data2.docs.isNotEmpty) {
for (var car in data.docs) {
await widget.loginService
.firebasefirestore()
.collection('users')
.doc(car.data()['uid'])
.collection('cars')
.doc(car.data()['cid'])
.collection('booking-in')
.get()
.then((ds) async {
if (ds.docs.isNotEmpty) {
for (var book in ds.docs) {
String data = book.data()['date'];
final splitted = data.split('-');
String finalDate = splitted[1];
DateTime dayEnd = DateFormat("dd/MM/yyyy").parse(finalDate);
if (dayEnd.compareTo(DateTime.now()) < 0) {
await widget.loginService
.firebasefirestore()
.collection('users')
.doc(user.uid)
.collection('cars')
.doc(book.data()['cid'])
.collection('booking-in')
.doc(book.data()['bookingId'])
.update({'status': 'f'});
}
}
}
});
}
}
}
#override
Widget build(BuildContext context) {
final screenHeight = MediaQuery.of(context).size.height;
final screenWidth = MediaQuery.of(context).size.width;
final screenText = MediaQuery.of(context).textScaleFactor;
final emailField = TextFormField(
key: const ValueKey(1),
autofocus: false,
style: TextStyle(fontSize: sizeHintText()),
controller: _emailController,
keyboardType: TextInputType.emailAddress,
onSaved: (value) {
_emailController.text = value!;
},
textInputAction: TextInputAction.next,
decoration: InputDecoration(
prefixIcon: Icon(Icons.mail, size: sizeHintText()),
contentPadding: EdgeInsets.fromLTRB(screenWidth * 0.02,
screenHeight * 0.015, screenWidth * 0.02, screenHeight * 0.015),
hintText: "Email",
hintStyle: TextStyle(fontSize: sizeHintText()),
border:
OutlineInputBorder(borderRadius: BorderRadius.circular(10))));
final passwordField = TextFormField(
key: const ValueKey(2),
autofocus: false,
style: TextStyle(fontSize: sizeHintText()),
controller: _passwordController,
obscureText: true,
onSaved: (value) {
_passwordController.text = value!;
},
textInputAction: TextInputAction.done,
decoration: InputDecoration(
prefixIcon: Icon(Icons.vpn_key, size: sizeHintText()),
contentPadding: EdgeInsets.fromLTRB(screenWidth * 0.02,
screenHeight * 0.015, screenWidth * 0.02, screenHeight * 0.015),
hintText: "Password",
hintStyle: TextStyle(fontSize: sizeHintText()),
border:
OutlineInputBorder(borderRadius: BorderRadius.circular(10))));
Scaffold(
resizeToAvoidBottomInset: true,
backgroundColor: Colors.white,
body: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
SizedBox(height: screenHeight * 0.1),
Text("Welcome to PrCar!",
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.black,
fontSize: screenText * 45,
fontWeight: FontWeight.bold)),
SizedBox(height: screenHeight * 0.05),
SizedBox(
height: screenHeight * 0.2,
child: Image.asset("assets/prcarlogo.png",
fit: BoxFit.contain)),
SizedBox(height: screenHeight * 0.05),
emailField,
SizedBox(height: screenHeight * 0.02),
passwordField,
SizedBox(height: screenHeight * 0.05),
Row(children: [
SizedBox(width: screenWidth * 0.06),
GestureDetector(
child: Text('Forgot password?',
style: TextStyle(
decoration: TextDecoration.underline,
color: Colors.redAccent,
fontSize: screenText * 16)),
onTap: () =>
Navigator.of(context).push(MaterialPageRoute(
builder: (context) => const ForgotPasswordPage(),
))),
Text(' or ', style: TextStyle(fontSize: screenText * 12)),
GestureDetector(
key: Key("New Account"),
child: Text("Don't have an account?",
textAlign: TextAlign.start,
style: TextStyle(
decoration: TextDecoration.underline,
color: Colors.redAccent,
fontSize: screenText * 16)),
onTap: () => Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const SignUp())))
]),
SizedBox(height: screenHeight * 0.06),
Row(mainAxisAlignment: MainAxisAlignment.center, children: [
Container(
key: const Key("clickButtom"),
height: screenHeight * 0.07,
width: screenWidth * 0.85,
child: MaterialButton(
color: Colors.redAccent,
onPressed: () async {
if (await NetworkCheck().check()) {
User? user = await loginUsingEmailPassword(
email: _emailController.text,
password: _passwordController.text,
context: context);
if (user != null) {
await widget.loginService
.firebasefirestore()
.collection('users')
.doc(user.uid)
.get()
.then((ds) {
userModel = UserModel.fromMap(ds);
StaticUser.email = userModel.email!;
StaticUser.uid = userModel.uid!;
StaticUser.firstName = userModel.firstName!;
StaticUser.secondName =
userModel.secondName!;
PassMarker.from = true;
_finishReservation(user);
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => HomePage(
homePageService: Service())));
});
}
} else {
Fluttertoast.showToast(
msg: 'No internet connection',
fontSize: 20);
}
},
child: Text("Login",
style: TextStyle(
color: Colors.white,
fontSize: screenText * 25))),
decoration: BoxDecoration(
color: Colors.deepPurple,
borderRadius: BorderRadius.circular(12),
boxShadow: const [
BoxShadow(
color: Colors.deepPurple,
spreadRadius: 6,
blurRadius: 3)
]))
])
])));
}
}

you dont need to add this line
onSaved: (value) {
_passwordController.text = value!;
},
controller will automatically update text when you change in textformfield

Related

Getting error during late initialisation in flutter

I am calling form below for add and edit operations.When clicked on edit button I have to get details of particular document based on its unique Id, so when clicked on edit I am calling API in initState() but when clicked on add button I am facing an issue like futureDocuments is not initialised, I cannot initialise it to null also, how to resolve this?
I am also getting an error like dId is not initialised while cliked on add document button
please guide me towards both the initializations
class DocumentForm extends StatefulWidget {
bool update;
final String userName;
//final String createdBY;
DocumentForm(this.userName, this.update);
#override
State createState() {
return _DocumentFormState(this.userName, this.update);
}
}
// AddAppointmentState<AddDocument> createState() => _AddDocumentState();
class _DocumentFormState extends State<DocumentForm> {
final String userName;
String playerId = '';
bool update;
//final String createdBY;
_DocumentFormState(this.userName, this.update);
late final String date1;
late String datainput;
final List<String> items1 = ["Open", "Closed", "Cancel", "Submitted"];
String? selectedItem;
final GlobalKey<FormState> formKey = GlobalKey<FormState>();
TextEditingController docIdController = TextEditingController();
TextEditingController docTitleController = TextEditingController();
TextEditingController tokenNoController = TextEditingController();
TextEditingController addressController = TextEditingController();
TextEditingController cityController = TextEditingController();
TextEditingController docStatusController = TextEditingController();
TextEditingController docTypeController = TextEditingController();
TextEditingController partyNameController = TextEditingController();
TextEditingController durationController = TextEditingController();
TextEditingController pinCodeController = TextEditingController();
TextEditingController rentDescController = TextEditingController();
TextEditingController startDateController = TextEditingController();
TextEditingController endDateController = TextEditingController();
late TextEditingController docstatusController = TextEditingController();
late String docType = docTypeController.text;
late final String createdBY;
final List<String> items = [
"Residential",
"Commercial",
];
String? selectedValue;
late Future<Document>? futureDocuments;
#override
void initState() {
this.update == true
? futureDocuments = DocumentController.fetchDocumentsByID(this.dId)
: futureDocuments = null;
// TODO: implement initState
super.initState();
// initPlatformState();
// initPlatformStateApt();
init();
}
#override
void dispose() {
docStatusController.dispose();
docTypeController.dispose();
super.dispose();
}
Future init() async {
// initPlatformState();
}
#override
Future<Document>? _futureDocument;
body: SafeArea(
child: SingleChildScrollView(
child: Container(
// height: MediaQuery.of(context).size.height,
//width: width * 1,
//height: MediaQuery.of(context).size.height,
alignment: Alignment.center,
padding: const EdgeInsets.all(25),
child: (_futureDocument == null)
? buildColumn(update)
: buildFutureBuilder(),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(10),
topRight: Radius.circular(10))),
),
),
),
Form buildColumn(bool update) {
return Form(
key: formKey,
child: FutureBuilder<Document>(
future: futureDocuments,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
if (snapshot.hasData) {
createdBY = snapshot.data!.createdBy;
this.dId = snapshot.data!.docId;
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
SizedBox(
height: 5,
),
// SizedBox(
// height: MediaQuery.of(context).size.height * 0.06,
// width: MediaQuery.of(context).size.width * 8,
// child:
Align(
alignment: Alignment.topLeft,
child: SizedBox(
width: MediaQuery.of(context).size.width * 0.95,
height: MediaQuery.of(context).size.height * 0.06,
// height: MediaQuery.of(context).size.height * 0.5,
child: TextFormField(
// minLines: 1,
// maxLines: 5,
// textCapitalization: TextCapitalization.words,
// //autovalidateMode: AutovalidateMode.onUserInteraction,
inputFormatters: [
// LengthLimitingTextInputFormatter(100),
FilteringTextInputFormatter.allow(
RegExp("[ ',-/ a-z A-Z á-ú Á-Ú 0-9]")),
],
controller: this.update == true
? docTitleController = TextEditingController(
text: '${snapshot.data!.docTitle}')
: docTitleController,
style: TextStyle(fontSize: 12),
// keyboardType: TextInputType.multiline,
decoration: const InputDecoration(
errorStyle: const TextStyle(fontSize: 0.05),
border: OutlineInputBorder(
borderRadius: BorderRadius.all(
Radius.circular(30),
)),
hintStyle: TextStyle(fontSize: 12),
labelStyle: TextStyle(
fontSize: 12,
),
labelText: 'Document Title',
hintText: 'Document title required'),
// validator: ,
validator: MultiValidator(
[RequiredValidator(errorText: 'Required*')]),
),
),
),
SizedBox(
height: 20,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Align(
alignment: Alignment.topLeft,
child: SizedBox(
height: MediaQuery.of(context).size.height * 0.06,
width: MediaQuery.of(context).size.width * 0.4,
child: TextFormField(
style: TextStyle(
fontSize: 12,
),
// minLines: 1,
// maxLines: 2,
inputFormatters: [
FilteringTextInputFormatter.digitsOnly,
LengthLimitingTextInputFormatter(14)
],
// //autovalidateMode: AutovalidateMode.onUserInteraction,
controller: this.update == true
? tokenNoController = TextEditingController(
text: '${snapshot.data!.tokenNo}')
: tokenNoController,
keyboardType: TextInputType.number,
decoration: const InputDecoration(
errorStyle: const TextStyle(fontSize: 0.05),
counterText: "",
border: OutlineInputBorder(
borderRadius:
BorderRadius.all(Radius.circular(30)),
),
focusColor: Color.fromARGB(255, 3, 87,
156), //Color.fromARGB(255, 253, 153, 33),
hintStyle: TextStyle(fontSize: 12),
labelStyle: TextStyle(
fontSize: 12,
),
labelText: 'Token No',
hintText: 'Token no required'),
validator: (value) {
if (value == null || value.isEmpty) {
return 'Please enter token No';
} else if (value.length < 14) {
return 'Please enter 14 digits number';
}
return null;
},
),
),
),
SizedBox(
width: MediaQuery.of(context).size.width * 0.01,
),
Align(
alignment: Alignment.topLeft,
child: SizedBox(
height: MediaQuery.of(context).size.height * 0.06,
width: MediaQuery.of(context).size.width * 0.4,
child: TextFormField(
style: TextStyle(fontSize: 12),
// minLines: 1,
// maxLines: 2,
//autovalidateMode: AutovalidateMode.onUserInteraction,
inputFormatters: [
FilteringTextInputFormatter.digitsOnly,
LengthLimitingTextInputFormatter(2)
],
controller: this.update == true
? durationController = TextEditingController(
text: '${snapshot.data!.duration}')
: durationController,
keyboardType: TextInputType.number,
decoration: const InputDecoration(
errorStyle: const TextStyle(fontSize: 0.05),
border: OutlineInputBorder(
borderRadius: BorderRadius.all(
Radius.circular(30))),
hintStyle: TextStyle(fontSize: 12),
labelStyle: TextStyle(
fontSize: 12,
),
labelText: 'Duration(M)',
hintText: 'Duration required'),
validator: MultiValidator(
[RequiredValidator(errorText: 'Required*')],
),
),
),
),
],
),
SizedBox(
height: 20,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Align(
alignment: Alignment.topLeft,
child: SizedBox(
height: MediaQuery.of(context).size.height * 0.06,
width: MediaQuery.of(context).size.width * 0.4,
child: TextFormField(
style: TextStyle(fontSize: 12),
// //autovalidateMode: AutovalidateMode.onUserInteraction,
//FilteringTextInputFormatter.allow(RegExp("[- 0-9]")),
inputFormatters: [
FilteringTextInputFormatter.allow(
RegExp("[- 0-9]")),
LengthLimitingTextInputFormatter(10)
],
controller: this.update == true
? startDateController = TextEditingController(
text: '${snapshot.data!.startDate}')
: startDateController,
keyboardType: TextInputType.datetime,
decoration: const InputDecoration(
errorStyle: const TextStyle(fontSize: 0.05),
prefixIcon: Icon(Icons.calendar_month),
border: OutlineInputBorder(
borderRadius:
BorderRadius.all(Radius.circular(30))),
hintStyle: TextStyle(fontSize: 12),
labelStyle: TextStyle(
fontSize: 12,
),
labelText: 'Start Date',
hintText: 'yyyy-MM-dd',
),
onTap: () async {
DateTime? pickedDate = await showDatePicker(
context: context,
initialDate: DateTime.now(),
firstDate: DateTime(
1991), //DateTime.now() - not to allow to choose before today.
lastDate: DateTime(2101),
// onConfirm:widget.onChanged,
).then((pickedDate) {
if (pickedDate != null) {
// print(
// pickedDate); //pickedDate output format => 2021-03-10 00:00:00.000
String formattedDate =
DateFormat('yyyy-MM-dd')
.format(pickedDate);
print(formattedDate);
setState(() {
startDateController.text = formattedDate;
//set output date to TextField value.
});
print(startDateController.text);
} else {
print("Date is not selected");
}
});
final int dur =
int.parse(durationController.text);
var stDate =
DateTime.parse(startDateController.text);
var jiffy = Jiffy(stDate).add(
months: dur,
days: -1,
// days: 1095,
);
DateTime d = jiffy.dateTime;
String s = jiffy.format('yyyy-MM-dd');
setState(() {
endDateController.text = s.toString();
});
},
validator: MultiValidator(
[RequiredValidator(errorText: 'Required*')]),
),
),
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Container(
height: 30,
width: 150,
child: ElevatedButton(
onPressed: () {
// ******Add new document **********///////
formKey.currentState?.validate();
final isValidForm =
formKey.currentState!.validate();
if (isValidForm && (update == false)) {
final String docTitle =
docTitleController.text;
final int tokenNo =
int.parse(tokenNoController.text)
.toInt();
//final String tokenNo = tokenNoController.text;
final String partyName =
partyNameController.text;
// addStatus(selectedItem!);
final String docType =
selectedValue.toString();
final String docStatus =
selectedItem.toString();
final String address =
addressController.text;
final String city = cityController.text;
final String rentDesc =
rentDescController.text;
final String pinCode =
pinCodeController.text;
final String duration =
durationController.text;
final String startDate =
startDateController.text;
final String endDate =
endDateController.text;
final String createdBy = this.userName;
print('Username :${createdBy}');
final String updatedBy = '';
Navigator.of(context).push(
MaterialPageRoute(
builder: (BuildContext context) =>
DocumentPage(
this.userName,
)));
setState(() {
_futureDocument = createDocument(
// docId,
docTitle,
tokenNo,
partyName,
docType,
address,
city,
pinCode,
duration,
rentDesc,
docStatus,
startDate,
endDate,
createdBy,
updatedBy,
// createdAt,
);
});
// }
//}
}
///*****************/
//****Edit document ******/
else if (isValidForm && update == true) {
final int docid = snapshot.data!.docId;
final String docTitle =
docTitleController.text;
final int tokenNo =
int.parse(tokenNoController.text)
.toInt();
final String partyName =
partyNameController.text;
final String docType =
docTypeController.text;
final String city = cityController.text;
final String address =
addressController.text;
final String pinCode =
pinCodeController.text;
final String duration =
durationController.text;
final String rentDesc =
rentDescController.text;
final String docStatus =
docstatusController.text;
final String startDate =
startDateController.text;
final String endDate =
endDateController.text;
final String createdBy = this.createdBY;
final String updatedBy = this.userName;
print(
'the user name from doc edit page ${this.userName}');
setState(() {
futureDocuments = updateDocument(
docid,
docTitle,
tokenNo,
partyName,
docType,
address,
city,
pinCode,
duration,
rentDesc,
docStatus,
startDate,
endDate,
createdBy,
updatedBy);
Navigator.of(context).push(
MaterialPageRoute(
builder: (BuildContext context) =>
DocumentsDetails(
docid,
this.userName,
)));
});
}
;
},
child: const Text("Save"),
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all(
Color.fromARGB(255, 253, 153, 33),
//Color.fromARGB(255, 253, 153, 33)
),
shape: MaterialStateProperty.all<
RoundedRectangleBorder>(
RoundedRectangleBorder(
borderRadius:
BorderRadius.circular(18.0),
//side: BorderSide(color: Colors.red)
),
)))),
],
),
],
);
}
}
return Center(child: const CircularProgressIndicator());
}),
);
//])
//);
}
FutureBuilder<Document> buildFutureBuilder() {
return FutureBuilder<Document>(
future: _futureDocument,
builder: (context, snapshot) {
if (snapshot.hasData) {
return Text(snapshot.data!.docTitle);
} else if (snapshot.hasError) {
return Text('${snapshot.error}');
}
return const CircularProgressIndicator();
},
);
}
You can remove late since it's already nullable. You have to also update the state after assigning it to futureDocuments.
Change late to nullable values using ? operator. i.e
Change from
late final String date1;
late String datainput;
to
final String? date1;
String? datainput;
Now you can assign null to date1 and datainput!

Not able to remove focus from input field

I have four textfields, a title field, a details field, a date field, and a time field. Both the date and time fields are wrapped within a gesture detector, and onTap calls a pickDateAndTime method. The problem is that when I click on the date field and try to manually change the time through the input rather than the dial way, the focus goes to the title field and when I am still on the time picker and type something in the time picker, the title field gets changed with the new input. The weird part is that this error just appeared out of nowhere, and there are no errors reported in the console.
class TodoScreen extends StatefulWidget {
final int? todoIndex;
final int? arrayIndex;
const TodoScreen({Key? key, this.todoIndex, this.arrayIndex})
: super(key: key);
#override
State<TodoScreen> createState() => _TodoScreenState();
}
class _TodoScreenState extends State<TodoScreen> {
final ArrayController arrayController = Get.find();
final AuthController authController = Get.find();
final String uid = Get.find<AuthController>().user!.uid;
late TextEditingController _dateController;
late TextEditingController _timeController;
late TextEditingController titleEditingController;
late TextEditingController detailEditingController;
late String _setTime, _setDate;
late String _hour, _minute, _time;
late String dateTime;
late bool done;
#override
void initState() {
super.initState();
String title = '';
String detail = '';
String date = '';
String? time = '';
if (widget.todoIndex != null) {
title = arrayController
.arrays[widget.arrayIndex!].todos![widget.todoIndex!].title ??
'';
detail = arrayController
.arrays[widget.arrayIndex!].todos![widget.todoIndex!].details ??
'';
date = arrayController
.arrays[widget.arrayIndex!].todos![widget.todoIndex!].date!;
time = arrayController
.arrays[widget.arrayIndex!].todos![widget.todoIndex!].time;
}
_dateController = TextEditingController(text: date);
_timeController = TextEditingController(text: time);
titleEditingController = TextEditingController(text: title);
detailEditingController = TextEditingController(text: detail);
done = (widget.todoIndex == null)
? false
: arrayController
.arrays[widget.arrayIndex!].todos![widget.todoIndex!].done!;
}
DateTime selectedDate = DateTime.now();
TimeOfDay selectedTime = TimeOfDay(
hour: (TimeOfDay.now().minute > 55)
? TimeOfDay.now().hour + 1
: TimeOfDay.now().hour,
minute: (TimeOfDay.now().minute > 55) ? 0 : TimeOfDay.now().minute + 5);
Future<DateTime?> _selectDate() => showDatePicker(
builder: (context, child) {
return datePickerTheme(child);
},
initialEntryMode: DatePickerEntryMode.calendarOnly,
context: context,
initialDate: selectedDate,
initialDatePickerMode: DatePickerMode.day,
firstDate: DateTime.now(),
lastDate: DateTime(DateTime.now().year + 5));
Future<TimeOfDay?> _selectTime() => showTimePicker(
builder: (context, child) {
return timePickerTheme(child);
},
context: context,
initialTime: selectedTime,
initialEntryMode: TimePickerEntryMode.input);
Future _pickDateTime() async {
DateTime? date = await _selectDate();
if (date == null) return;
if (date != null) {
selectedDate = date;
_dateController.text = DateFormat("MM/dd/yyyy").format(selectedDate);
}
TimeOfDay? time = await _selectTime();
if (time == null) {
_timeController.text = formatDate(
DateTime(
DateTime.now().year,
DateTime.now().day,
DateTime.now().month,
DateTime.now().hour,
DateTime.now().minute + 5),
[hh, ':', nn, " ", am]).toString();
}
if (time != null) {
selectedTime = time;
_hour = selectedTime.hour.toString();
_minute = selectedTime.minute.toString();
_time = '$_hour : $_minute';
_timeController.text = _time;
_timeController.text = formatDate(
DateTime(2019, 08, 1, selectedTime.hour, selectedTime.minute),
[hh, ':', nn, " ", am]).toString();
}
}
#override
Widget build(BuildContext context) {
bool visible =
(_dateController.text.isEmpty && _timeController.text.isEmpty)
? false
: true;
final formKey = GlobalKey<FormState>();
return Scaffold(
resizeToAvoidBottomInset: false,
appBar: AppBar(
title: Text((widget.todoIndex == null) ? 'New Task' : 'Edit Task',
style: menuTextStyle),
leadingWidth: (MediaQuery.of(context).size.width < 768) ? 90.0 : 100.0,
leading: Center(
child: Padding(
padding: (MediaQuery.of(context).size.width < 768)
? const EdgeInsets.only(left: 0)
: const EdgeInsets.only(left: 21.0),
child: TextButton(
style: const ButtonStyle(
splashFactory: NoSplash.splashFactory,
),
onPressed: () {
Get.back();
},
child: Text(
"Cancel",
style: paragraphPrimary,
),
),
),
),
centerTitle: true,
actions: [
Center(
child: Padding(
padding: (MediaQuery.of(context).size.width < 768)
? const EdgeInsets.only(left: 0)
: const EdgeInsets.only(right: 21.0),
child: TextButton(
style: const ButtonStyle(
splashFactory: NoSplash.splashFactory,
),
onPressed: () async {
},
child: Text((widget.todoIndex == null) ? 'Add' : 'Update',
style: paragraphPrimary),
),
),
)
],
),
body: SafeArea(
child: Container(
width: double.infinity,
padding: (MediaQuery.of(context).size.width < 768)
? const EdgeInsets.symmetric(horizontal: 15.0, vertical: 20.0)
: const EdgeInsets.symmetric(horizontal: 35.0, vertical: 15.0),
child: Column(
children: [
Form(
key: formKey,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
TextFormField(
validator: Validator.titleValidator,
controller: titleEditingController,
autofocus: true, // problem here
autocorrect: false,
cursorColor: Colors.grey,
maxLines: 1,
maxLength: 25,
textInputAction: TextInputAction.next,
decoration: InputDecoration(
counterStyle: counterTextStyle,
hintStyle: hintTextStyle,
hintText: "Title",
border: InputBorder.none),
style: todoScreenStyle),
primaryDivider,
TextField(
controller: detailEditingController,
maxLines: null,
autocorrect: false,
cursorColor: Colors.grey,
textInputAction: TextInputAction.done,
decoration: InputDecoration(
counterStyle: counterTextStyle,
hintStyle: hintTextStyle,
hintText: "Notes",
border: InputBorder.none),
style: todoScreenDetailsStyle),
],
),
),
Visibility(
visible: (widget.todoIndex != null) ? true : false,
child: GestureDetector(
onTap: () {},
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
"Completed",
style: todoScreenStyle,
),
Transform.scale(
scale: 1.3,
child: Theme(
data: ThemeData(
unselectedWidgetColor: const Color.fromARGB(
255, 187, 187, 187)),
child: Checkbox(
shape: const CircleBorder(),
checkColor: Colors.white,
activeColor: primaryColor,
value: done,
side: Theme.of(context).checkboxTheme.side,
onChanged: (value) {
setState(() {
done = value!;
});
})),
)
],
),
),
),
GestureDetector(
onTap: () async {
await _pickDateTime();
setState(() {
visible = true;
});
},
child: Column(
children: [
Row(
children: [
Flexible(
child: TextField(
enabled: false,
controller: _dateController,
onChanged: (String val) {
_setDate = val;
},
decoration: InputDecoration(
hintText: "Date",
hintStyle: hintTextStyle,
border: InputBorder.none),
style: todoScreenStyle,
),
),
visible
? IconButton(
onPressed: () {
_dateController.clear();
_timeController.clear();
setState(() {});
},
icon: const Icon(
Icons.close,
color: Colors.white,
))
: Container()
],
),
primaryDivider,
TextField(
onChanged: (String val) {
_setTime = val;
},
enabled: false,
controller: _timeController,
decoration: InputDecoration(
hintText: "Time",
hintStyle: hintTextStyle,
border: InputBorder.none),
style: todoScreenStyle,
)
],
),
),
],
),
),
),
);
}
}
Should I open an issue on Github, as I had not made any changes to the code for it behave this way and also because there were no errors in the console
Here is the full code on Github
Update
Here is a reproducible example:
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const TodoScreen(),
);
}
}
class TodoScreen extends StatefulWidget {
const TodoScreen({Key? key}) : super(key: key);
#override
State<TodoScreen> createState() => _TodoScreenState();
}
class _TodoScreenState extends State<TodoScreen> {
late TextEditingController _dateController;
late TextEditingController _timeController;
late TextEditingController titleEditingController;
late TextEditingController detailEditingController;
late String _setTime, _setDate;
late String _hour, _minute, _time;
late String dateTime;
#override
void initState() {
super.initState();
String title = '';
String detail = '';
String date = '';
String? time = '';
_dateController = TextEditingController(text: date);
_timeController = TextEditingController(text: time);
titleEditingController = TextEditingController(text: title);
detailEditingController = TextEditingController(text: detail);
}
#override
void dispose() {
super.dispose();
titleEditingController.dispose();
detailEditingController.dispose();
_timeController.dispose();
_dateController.dispose();
}
Theme timePickerTheme(child) => Theme(
data: ThemeData.dark().copyWith(
timePickerTheme: TimePickerThemeData(
backgroundColor: const Color.fromARGB(255, 70, 70, 70),
dayPeriodTextColor: Colors.green,
hourMinuteTextColor: MaterialStateColor.resolveWith((states) =>
states.contains(MaterialState.selected)
? Colors.white
: Colors.white),
dialHandColor: Colors.green,
helpTextStyle: TextStyle(
fontSize: 12, fontWeight: FontWeight.bold, color: Colors.green),
dialTextColor: MaterialStateColor.resolveWith((states) =>
states.contains(MaterialState.selected)
? Colors.white
: Colors.white),
entryModeIconColor: Colors.green,
),
textButtonTheme: TextButtonThemeData(
style: ButtonStyle(
foregroundColor:
MaterialStateColor.resolveWith((states) => Colors.green)),
),
),
child: child!,
);
Theme datePickerTheme(child) => Theme(
data: ThemeData.dark().copyWith(
colorScheme: ColorScheme.dark(
surface: Colors.green,
secondary: Colors.green,
onPrimary: Colors.white,
onSurface: Colors.white,
primary: Colors.green,
)),
child: child!,
);
DateTime selectedDate = DateTime.now();
TimeOfDay selectedTime = TimeOfDay(
hour: (TimeOfDay.now().minute > 55)
? TimeOfDay.now().hour + 1
: TimeOfDay.now().hour,
minute: (TimeOfDay.now().minute > 55) ? 0 : TimeOfDay.now().minute + 5);
Future<DateTime?> _selectDate() => showDatePicker(
builder: (context, child) {
return datePickerTheme(child);
},
initialEntryMode: DatePickerEntryMode.calendarOnly,
context: context,
initialDate: selectedDate,
initialDatePickerMode: DatePickerMode.day,
firstDate: DateTime.now(),
lastDate: DateTime(DateTime.now().year + 5));
Future<TimeOfDay?> _selectTime() => showTimePicker(
builder: (context, child) {
return timePickerTheme(child);
},
context: context,
initialTime: selectedTime,
initialEntryMode: TimePickerEntryMode.input);
Future _pickDateTime() async {
DateTime? date = await _selectDate();
if (date == null) return;
if (date != null) {
selectedDate = date;
_dateController.text = selectedDate.toString();
}
TimeOfDay? time = await _selectTime();
if (time != null) {
selectedTime = time;
_hour = selectedTime.hour.toString();
_minute = selectedTime.minute.toString();
_time = '$_hour : $_minute';
_timeController.text = _time;
_timeController.text =
DateTime(2019, 08, 1, selectedTime.hour, selectedTime.minute)
.toString();
}
}
#override
Widget build(BuildContext context) {
bool visible =
(_dateController.text.isEmpty && _timeController.text.isEmpty)
? false
: true;
final formKey = GlobalKey<FormState>();
return Scaffold(
resizeToAvoidBottomInset: false,
appBar: AppBar(
centerTitle: true,
),
body: SafeArea(
child: Container(
width: double.infinity,
padding: (MediaQuery.of(context).size.width < 768)
? const EdgeInsets.symmetric(horizontal: 15.0, vertical: 20.0)
: const EdgeInsets.symmetric(horizontal: 35.0, vertical: 15.0),
child: Column(
children: [
Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(14.0)),
padding: const EdgeInsets.symmetric(
horizontal: 24.0, vertical: 15.0),
child: Form(
key: formKey,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
TextFormField(
controller: titleEditingController,
autofocus: true,
autocorrect: false,
cursorColor: Colors.grey,
maxLines: 1,
maxLength: 25,
textInputAction: TextInputAction.next,
decoration: InputDecoration(
hintText: "Title", border: InputBorder.none),
),
Divider(color: Colors.black),
TextField(
controller: detailEditingController,
maxLines: null,
autocorrect: false,
cursorColor: Colors.grey,
textInputAction: TextInputAction.done,
decoration: InputDecoration(
hintText: "Notes", border: InputBorder.none),
),
],
),
)),
GestureDetector(
onTap: () async {
await _pickDateTime();
setState(() {
visible = true;
});
},
child: Container(
margin: const EdgeInsets.only(top: 20.0),
width: double.infinity,
padding: const EdgeInsets.symmetric(
horizontal: 24.0, vertical: 15.0),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(14.0)),
child: Column(
children: [
Row(
children: [
Flexible(
child: TextField(
enabled: false,
controller: _dateController,
onChanged: (String val) {
_setDate = val;
},
decoration: InputDecoration(
hintText: "Date", border: InputBorder.none),
),
),
visible
? IconButton(
onPressed: () {
_dateController.clear();
_timeController.clear();
setState(() {});
},
icon: const Icon(
Icons.close,
color: Colors.white,
))
: Container()
],
),
Divider(
color: Colors.blue,
),
TextField(
onChanged: (String val) {
_setTime = val;
},
enabled: false,
controller: _timeController,
decoration: InputDecoration(
hintText: "Enter", border: InputBorder.none),
)
],
)),
),
],
),
),
),
);
}
}
In your main.dart file, you should return something like this:
void main() async {
WidgetsFlutterBinding.ensureInitialized();
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
// This allows closing keyboard when tapping outside of a text field
FocusScopeNode currentFocus = FocusScope.of(context);
if (!currentFocus.hasPrimaryFocus &&
currentFocus.focusedChild != null) {
FocusManager.instance.primaryFocus!.unfocus();
}
},
child: // your app's entry point,
);
}
}
Add a focusNode in your textField:
FocusNode focusNode = FocusNode();
TextField(
focusNode: focusNode,
);
And then in the gesture detector, add that following code to unselect the textfield input:
FocusScope.of(context).requestFocus(FocusNode());
simply wrap your Scaffold widget GestureDetector and add FocusScope.of(context).requestFocus(FocusNode()); it will automatically unfocused text field when you click anywhere on your screen
GestureDetector(
onTap: () {
FocusScope.of(context).requestFocus(FocusNode());
},
child: Scaffold()
)
You can use below code to remove focus in gesture detector event
FocusScopeNode currentFocus = FocusScope.of(context);
if (!currentFocus.hasPrimaryFocus && currentFocus.focusedChild != null) {
currentFocus.unfocus();
}

buildScope missed some dirty elements in flutter

enter image description here
I have error like above picture. what is buildscope. I think it is related with lifecycle. I cannot find where is problem. I think that it doesn't use dispose so it show error. but it is not correct. PincodeTextField widget automatically do dispose. what is problem in my code.
class PinSettingScreen extends StatefulWidget {
const PinSettingScreen({Key? key}) : super(key: key);
#override
State<PinSettingScreen> createState() => _PinSettingScreenState();
}
class _PinSettingScreenState extends State<PinSettingScreen> {
late FlutterSecureStorage _storage;
late MethodChannel _finPongChannel;
late TextEditingController _inputEditingController;
late String _pinNo;
late Map _userData;
late FocusNode _inputPinFocusNode;
bool _isCompleted = false;
#override
void initState() {
super.initState();
_storage = const FlutterSecureStorage();
_inputEditingController = TextEditingController();
_inputPinFocusNode = FocusNode();
_finPongChannel = const MethodChannel("io.codef.finpong");
_finPongChannel.setMethodCallHandler(closeFinPong);
}
#override
void didChangeDependencies() {
super.didChangeDependencies();
_userData = context.currentBeamLocation.data as Map;
}
Future<void> closeFinPong(MethodCall call) async {
if (call.method == "closeFinPong") {
Provider.of<AuthenticationNotifier>(context, listen: false)
.setUserAuth(true);
}
}
Widget _pinInputPage() {
return Center(
child: Padding(
padding: const EdgeInsets.all(20.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
"헤이홀더에서 사용할",
style: TextStyle(
color: Colors.black,
fontSize: 20.0.sp,
fontWeight: FontWeight.w500),
),
SizedBox(
height: 5.0.h,
),
Text("비밀번호를 입력해주세요.",
style: TextStyle(
color: Colors.black,
fontSize: 20.0.sp,
fontWeight: FontWeight.w500)),
SizedBox(
height: 30.0.h,
),
PinCodeTextField(
appContext: context,
length: 6,
keyboardType: TextInputType.number,
obscureText: true,
autoFocus: true,
blinkWhenObscuring: true,
focusNode: _inputPinFocusNode,
controller: _inputEditingController,
inputFormatters: <TextInputFormatter>[
FilteringTextInputFormatter.digitsOnly
],
onChanged: (value) {},
pinTheme: PinTheme(
shape: PinCodeFieldShape.box,
borderRadius: BorderRadius.circular(5)),
onCompleted: (value) {
setState(() {
_isCompleted = true;
_pinNo = _inputEditingController.text;
});
_inputEditingController.clear();
FocusScope.of(context).nextFocus();
},
)
],
),
),
);
}
Future<void> _signup() async {
showCircularProgressIndicator(context);
final authNotifier =
Provider.of<AuthenticationNotifier>(context, listen: false);
final fcmToken = await FirebaseMessaging.instance.getToken();
_userData.putIfAbsent("pinNo", () => _pinNo);
_userData.putIfAbsent("deviceId", () => fcmToken);
SignUpModel signUpResult = await AuthService().signUp(_userData);
if (signUpResult.ok!) {
final SharedPreferences pref = await SharedPreferences.getInstance();
await pref.setBool("useLock", true);
await _storage.write(
key: "userId", value: signUpResult.data?.userId.toString());
final userState = signUpResult.data?.userState;
if (userState == "new") {
final codefToken = signUpResult.data?.codefToken;
final arguments = {"codefToken": codefToken, "entry": "0"};
await _finPongChannel.invokeMethod("finpongStart", arguments);
} else {
authNotifier.setUserAuth(true);
}
} else {
//TODO://알수없는 에러 발생.
}
}
Widget _pinCheckPage() {
return Center(
child: Padding(
padding: const EdgeInsets.all(20.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
"비밀번호 확인을 위해",
style: TextStyle(
color: Colors.black,
fontSize: 20.0.sp,
fontWeight: FontWeight.w500),
),
SizedBox(
height: 5.0.h,
),
Text(
"다시 한번 입력해주세요.",
style: TextStyle(
color: Colors.black,
fontSize: 20.0.sp,
fontWeight: FontWeight.w500),
),
SizedBox(
height: 30.0.h,
),
PinCodeTextField(
appContext: context,
length: 6,
keyboardType: TextInputType.number,
obscureText: true,
blinkWhenObscuring: true,
onChanged: (value) {},
inputFormatters: <TextInputFormatter>[
FilteringTextInputFormatter.digitsOnly
],
pinTheme: PinTheme(
shape: PinCodeFieldShape.box,
borderRadius: BorderRadius.circular(5)),
validator: (value) {
if (value!.length == 6 && _pinNo != value) {
return "이전 입력 값과 다른 값을 입력하였습니다.";
} else {
return null;
}
},
onCompleted: (value) async {
if (_pinNo == value) {
await _signup();
}
},
)
],
),
),
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: _isCompleted
? AppBar(
elevation: 0,
backgroundColor: Colors.white,
leadingWidth: 38.0.w,
leading: IconButton(
padding: EdgeInsets.only(left: 15.0.w),
icon: const Icon(
Icons.arrow_back_ios,
color: Colors.black,
),
onPressed: () {
setState(() {
_pinNo = "";
_isCompleted = false;
});
_inputEditingController.clear();
FocusScope.of(context).requestFocus(_inputPinFocusNode);
},
),
)
: null,
body: _isCompleted ? _pinCheckPage() : _pinInputPage());
}
}

My objective is to put message response everytime user enter the same email into the snackbar but what i get is a null

ive been getting this error for days now but still cant figure it out. My objective is to put message response everytime user enter the same email into the snackbar but what i get is a null.
This is my signup screen.
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:form_field_validator/form_field_validator.dart';
import 'package:formvalid/models/register_model.dart';
import 'package:http/http.dart' as http;
import 'package:formvalid/progressHUD.dart';
import 'package:formvalid/screens/login.dart';
class SignupScreen extends StatefulWidget {
const SignupScreen({Key? key}) : super(key: key);
#override
_SignupScreenState createState() => _SignupScreenState();
}
class RegisterAPI {
Future<RegisterResponse> register(
String name, String email, String password) async {
String url = 'http://api.staging.tarsoft.co/api/register';
final response = await http.post(Uri.parse('$url'),
body: {'name': name, 'email': email, 'password': password});
if (response.statusCode == 200 || response.statusCode == 401) {
print(response.body);
// print(response.statusCode);
return RegisterResponse.fromJson(json.decode(response.body));
} else {
print(response.body);
throw Exception('Failed to load data');
}
}
}
class _SignupScreenState extends State<SignupScreen> {
TextEditingController passController = new TextEditingController();
TextEditingController emailController = new TextEditingController();
TextEditingController nameController = new TextEditingController();
GlobalKey<FormState> formKey = GlobalKey<FormState>();
final scaffoldKey = GlobalKey<FormState>();
late RegisterResponse _user;
bool hidePassword = true;
bool isApiCallprocess = false;
#override
void initState() {
super.initState();
_user = new RegisterResponse();
}
#override
Widget build(BuildContext context) {
return ProgressHUD(
child: _uibuild(context),
inAsyncCall: isApiCallprocess,
opacity: 0.3,
);
}
Widget _uibuild(BuildContext context) {
final double height = MediaQuery.of(context).size.height;
return Scaffold(
appBar: AppBar(
key: scaffoldKey,
backgroundColor: Colors.transparent,
elevation: 0,
leading: IconButton(
icon: Icon(Icons.arrow_back, color: Colors.black),
onPressed: () {
Navigator.push(context,
MaterialPageRoute(builder: (context) => LoginScreen()));
},
)),
backgroundColor: Color(0xFFffffff),
body: SingleChildScrollView(
child: Form(
key: formKey,
child: Container(
padding: EdgeInsets.only(left: 40, right: 40),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(height: height * 0.04),
Text(
'Prizes and Suprises',
style: TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold,
color: Color(0xFF363f93)),
),
Text(
'Await you !',
style: TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold,
color: Color(0xFF363f93)),
),
SizedBox(
height: height * 0.03,
),
TextFormField(
controller: nameController,
onSaved: (input) => _user.name = input,
decoration: InputDecoration(labelText: 'Enter your name'),
validator: (value) {
if (value!.isEmpty ||
!RegExp(r'^[a-z A-Z]+$').hasMatch(value)) {
return 'Enter correct name';
} else {
return null;
}
}),
SizedBox(height: height * 0.05),
TextFormField(
controller: emailController,
onSaved: (input) => _user.email = input,
decoration: InputDecoration(labelText: 'Enter your email'),
validator: MultiValidator([
RequiredValidator(errorText: 'Enter your email'),
EmailValidator(errorText: 'Not A Valid Email')
])),
SizedBox(height: height * 0.05),
TextFormField(
controller: passController,
onSaved: (input) => _user.password = input,
decoration: InputDecoration(labelText: 'Enter your password'),
validator: MultiValidator([
RequiredValidator(errorText: 'Enter your password'),
MinLengthValidator(6,
errorText: 'Should be at least 6 characters')
]),
obscureText: hidePassword,
),
SizedBox(height: height * 0.05),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
TextButton(
onPressed: () {
final String name = nameController.text;
final String email = emailController.text;
final String password = passController.text;
if (validateAndSave()) {
setState(() {
isApiCallprocess = true;
});
RegisterAPI registerAPI = new RegisterAPI();
registerAPI
.register(name, email, password)
.then((value) => {
setState(() {
isApiCallprocess = false;
}),
if (value.token?.isNotEmpty ?? false)
{
ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(
content: Text(
'${_user.name}')))
}
else
{
ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(
content:
Text('${_user.message}')))
}
});
print(_user.toJson());
}
},
child: Container(
margin: EdgeInsets.only(left: 100.0),
child: Padding(
padding: const EdgeInsets.only(left: 35, top: 10),
child: Text(
'Register',
style: TextStyle(color: Colors.white),
),
),
height: 40,
width: 120,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5.0),
color: Color(0xFF363f93),
),
)),
SizedBox(
height: height * 0.09,
),
],
),
],
),
),
),
),
);
}
bool validateAndSave() {
final form = formKey.currentState;
if (form!.validate()) {
form.save();
return true;
}
return false;
}
}
//ignore: must_be_immutable
class TextInput extends StatelessWidget {
final String textString;
TextEditingController textController;
final bool obscureText;
TextInput(
{Key? key,
required this.textString,
required this.textController,
required this.obscureText})
: super(key: key);
#override
Widget build(BuildContext context) {
return TextField(
style: TextStyle(color: Color(0xFF000000)),
cursorColor: Color(0xFF9b9b9b),
controller: textController,
keyboardType: TextInputType.text,
obscureText: obscureText,
decoration: InputDecoration(
hintText: this.textString,
hintStyle: TextStyle(
color: Color(0xFF9b9b9b),
fontSize: 15,
fontWeight: FontWeight.normal),
),
);
}
}
This is my responseregister
class RegisterResponse{
String? email;
String? password;
String? name;
String? token;
String? error;
String? message;
String? success;
RegisterResponse({this.email, this.password, this.name,this.token,this.error,this.message,this.success});
factory RegisterResponse.fromJson(Map<String, dynamic> json) =>
RegisterResponse(
name: json['name'],
email: json['email'],
password: json['password'],
token: json['token'] == null ? json['token'] : '',
error: json['error'],
message: json['email'],
success: json['Success']
);
Map<String, dynamic> toJson() {
Map<String, dynamic> map = {
'name': name,
'email': email,
'password': password,
};
return map;
}
}
this is in debugger console shows "the email has already been taken"
display null

The method 'getUsers' was called on null. Receiver: null Tried calling: getUsers()

I am getting error on red screen right after i run my app. My first screen is login screen. I want to simply register the user and login the user. but when i use the getUsers() or getLogin() I get the above error. I am fed up of this error. Searched everywhere but m not able to find any working solutions. Please can u please write the code which i need to add. Please help me.
UserLogin.dart
import 'dart:ui';
import 'package:customer/models/registerUser.dart';
import 'package:customer/screens/UserRegistration.dart';
import 'package:customer/screens/people_list.dart';
import 'package:customer/services/db_service.dart';
import 'package:customer/utils/form_helper.dart';
import 'package:flutter/material.dart';
import 'ForgotPassword.dart';
class UserLogin extends StatefulWidget {
#override
State<StatefulWidget> createState() {
return UserLoginState();
}
}
class UserLoginState extends State<UserLogin>{
final reguser = RegisterUser();
String name,_password,_email;
var _formKey=GlobalKey<FormState>();
RegisterUser model;
DBService dbService;
var _minimumPadding = 5.0;
TextEditingController usernameController=TextEditingController();
TextEditingController passwordController=TextEditingController();
bool isHiddenPassword=true;
final scaffoldKey = new GlobalKey<ScaffoldState>();
void _showSnackBar(String text) {
scaffoldKey.currentState.showSnackBar(new SnackBar(
content: new Text(text),
));
}
void _togglePasswordView() {
setState(() {
isHiddenPassword = !isHiddenPassword;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
title: Text('Customer Tracking System'),),
body:_fetchData(),
);
}
Widget _fetchData(){
return FutureBuilder<List<RegisterUser>>(
future: dbService.getUsers(),
builder:
(BuildContext context, AsyncSnapshot<List<RegisterUser>> userDetails) {
if (userDetails.hasData) {
return _loginUI(userDetails.data);
}
return CircularProgressIndicator();
},
);
}
Widget _loginUI(List<RegisterUser> userDetails){
TextStyle textStyle = Theme.of(context).textTheme.title;
var height = MediaQuery.of(context).size.height;
var width = MediaQuery.of(context).size.width;
Form(
key: _formKey,
child: Container(
child: Padding(
padding: EdgeInsets.all(_minimumPadding * 2),
child: ListView
(
children: <Widget>[
Text("Login".toUpperCase(),
style: TextStyle(
fontSize: 40.0, fontWeight: FontWeight.bold),
textAlign: TextAlign.center),
SizedBox(height: height * 0.08,),
Divider(),
Padding(
padding: EdgeInsets.only(
top: _minimumPadding * 3,
bottom: _minimumPadding),
child: TextFormField(
controller: usernameController,
style: textStyle,
validator: (String value) {
if (value.isEmpty) {
return 'Please Enter Name';
}
return null;
},
onSaved: (String value) {
_email = value;
},
decoration: InputDecoration(
// filled: true,
//fillColor: Colors.white,
prefixIcon: Icon(Icons.person),
labelText: 'Username',
hintText: 'Username',
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(25.0)
)
)
)),
Padding(
padding: EdgeInsets.only(
top: _minimumPadding * 3,
bottom: _minimumPadding),
child: TextFormField(
style: textStyle,
obscureText: isHiddenPassword,
controller: passwordController,
validator: (String value) {
if (value.isEmpty) {
return 'Please Enter Name';
}
return null;
},
onSaved: (String value) {
_password = value;
},
decoration: InputDecoration(
prefixIcon: Icon(Icons.lock),
suffixIcon: InkWell(
onTap: _togglePasswordView,
child: Icon(Icons.visibility)),
labelText: 'Password',
hintText: 'Password',
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(25.0)
)
)
)
),
InkWell(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ForgotPassword()));
},
child: Text(
"Forgot Password ?",
style: TextStyle(
fontSize: 18,
color: Colors.purpleAccent,
//fontWeight: FontWeight.bold,
letterSpacing: 1.7),
textAlign: TextAlign.right,
),
),
SizedBox(
height: height * 0.08,
),
GestureDetector(
onTap: () {
_submit();
},
child: Container(
padding:
EdgeInsets.symmetric(horizontal: 26, vertical: 20),
decoration: BoxDecoration(
//gradient: new LinearGradient(
//colors: [Colors.purple, Colors.purpleAccent]),
color: Theme.of(context).primaryColor,
borderRadius: BorderRadius.circular(20),
boxShadow: [
BoxShadow(
blurRadius: 4,
//color: Colors.purpleAccent,
offset: Offset(2, 2))
]),
child: Text(
"Login".toUpperCase(),
style: TextStyle(
fontSize: 20,
color: Colors.white,
fontWeight: FontWeight.bold,
letterSpacing: 1.7),
textAlign: TextAlign.center,
),
),
),
SizedBox(
height: height * 0.05,
),
SizedBox(
height: height * 0.05,
),
Row(
children: <Widget>[
Expanded(
child: Text("Not yet registered?",
style: TextStyle(
fontSize: 25.0)
)
),
GestureDetector(
onTap: () {
Navigator.push(context,
MaterialPageRoute(builder: (context) => UserRegistration()));
},
child: Center(
child: Container(
padding:
EdgeInsets.symmetric(
horizontal: 26, vertical: 10),
decoration: BoxDecoration(
//gradient: new LinearGradient(
// colors: [Colors.purple, Colors.purpleAccent]),
color: Theme.of(context).primaryColor,
borderRadius: BorderRadius.circular(20),
boxShadow: [
BoxShadow(
blurRadius: 4,
//color:,
offset: Offset(2, 2))
]),
child: Text(
"Register".toUpperCase(),
style: TextStyle(
fontSize: 20,
color: Colors.white,
fontWeight: FontWeight.bold,
letterSpacing: 1.7),
textAlign: TextAlign.center,
),
),
),
)
],
),
],
)),
),
);
}
bool validateAndSave() {
final form = _formKey.currentState;
if (form.validate()) {
form.save();
return true;
}
return false;
}
void _submit(){
final form = _formKey.currentState;
var res;
if (validateAndSave()) {
setState(() {
//getLogin(_email, _password);
res=dbService.getLogin(_email, _password).then((value) {
if(res!=0){
FormHelper.showMessage(
context,
"Login",
"Login Successfull",
"Ok",
() {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => People_List(),
),
);
},
);}
else {
FormHelper.showMessage(
context,
"Login",
"Login not Successfull",
"Ok", () {}
);
}
});
});
}
}
}
RegisterUser.dart
import 'model.dart';
class RegisterUser extends Model {
static String table = 'userDetails';
int id;
String firstName;
String lastName;
String mobileNum;
String emailId;
String address;
String userType;
String password;
RegisterUser({
this.id,
this.firstName,
this.lastName,
this.mobileNum,
this.emailId,
this.address,
this.userType,
this.password
});
static RegisterUser fromMap(Map<String, dynamic> map) {
return RegisterUser(
id: map["id"],
firstName: map['firstName'].toString(),
lastName: map['lastName'],
mobileNum: map['mobileNum'],
emailId: map['emailId'],
address: map['address'],
userType: map['userType'],
password: map['password']
);
}
Map<String, dynamic> toMap() {
Map<String, dynamic> map = {
'id': id,
'firstName': firstName,
'lastName': lastName,
'mobileNum': mobileNum,
'emailId': emailId,
'address': address,
'userType':userType,
'password':password
};
if (id != null) {
map['id'] = id;
}
return map;
}
}
db_service.dart
import 'package:customer/models/registerUser.dart';
import 'package:customer/utils/database_helper.dart';
Future<List<RegisterUser>> getUsers() async {
await DB.init();
List<Map<String, dynamic>> userDetails = await DB.query(RegisterUser.table);
return userDetails.map((item) => RegisterUser.fromMap(item)).toList();
}
Future<List<RegisterUser>> getLogin(String email, String password) async {
await DB.init();
List<Map<String, dynamic>> res = await DB.rawQuery("SELECT * FROM userDetails WHERE emailId = '$email' and password = '$password'");
if (res.length > 0) {
return res.map((item) => RegisterUser.fromMap(item)).toList();
//return new User.fromMap(res.first);
}
return null;
}
You need a line with dbService = something before you can do dbService.getUsers() because just saying DbService dbService; initializes it to be null.
It's like a paper with no phone number on it and you are trying to call someone with it. You need to write down a phone number on it.
I finally got the answer to my question.
I had to just instantiate the DBService.
i.e DBService dbService=new DBService();
class UserLoginState extends State<UserLogin>{
final reguser = RegisterUser();
String name,_password,_email;
var _formKey=GlobalKey<FormState>();
RegisterUser model;
DBService dbService=new DBService();
...