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'm a beginner in the flutter, I have a conflict, when I'm focusing on a TexFiled, the keyboard hidden over the TextField, and bottom button not showing i attached my conflict here
any solution for this
Thanks
code here
import 'dart:ui';
import 'package:crapp/pages/create_password/password_screen.dart';
import 'package:crapp/widgets/components/alert.dart';
import 'package:crapp/widgets/components/page_animation.dart';
import 'package:crapp/widgets/theme/constants.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:crapp/provider/theme_provider.dart';
class PasswordScreen extends StatefulWidget {
#override
_PasswordScreenState createState() => _PasswordScreenState();
}
class _PasswordScreenState extends State< PasswordScreen > {
final _controller = TextEditingController();
//validation controller
TextEditingController sQuastionController = new TextEditingController();
TextEditingController answerQController = new TextEditingController();
TextEditingController passController = new TextEditingController();
TextEditingController conPassController = new TextEditingController();
final TextEditingController _pass = TextEditingController();
final TextEditingController _confirmPass = TextEditingController();
bool _isButtonEnabled = false;
//final _controller = TextEditingController();
bool isConfirm=false;
check (BuildContext context){
if(sQuastionController.text.isNotEmpty &&
answerQController.text.isNotEmpty &&
conPassController.text.isNotEmpty &&
passController.text.isNotEmpty){
setState(() {
_isButtonEnabled = true;
});
} else {
setState(() {
_isButtonEnabled = false;
});
}
}
checks (BuildContext context){
if(passController.text.isEmpty){
showDialog<void>(
context: context,
builder: (BuildContext dialogContext) {
return Alert(title: "Alert !!!",subTile: "Password must be 10 characters !",);
}
);
}else if(passController.text.length > 0 && passController.text.length < 10){
isConfirm = true;
showDialog<void>(
context: context,
builder: (BuildContext dialogContext) {
return Alert(title: "Alert !!!",subTile: "Password doesn't match !",);
}
);
}
}
checkChanged(){
if( secretVal != null
)
{
setState(() {
isSave = true;
});
}else{
isSave =false;
}
} bool isSave=false;
final GlobalKey<FormState> formKey = GlobalKey<FormState>();
#override
Widget build(BuildContext context) {
/* double height = MediaQuery.of(context).size.height;
double width = MediaQuery.of(context).size.width;*/
Provider.of<ThemeProvider>(context).themeMode == ThemeMode.dark
? 'DarkTheme'
: 'LightTheme';
return Scaffold(
resizeToAvoidBottomInset: false,
body: SafeArea(
child: Column(
children: <Widget>[
Expanded(
child: _signUp(),
),
],
),
), bottomNavigationBar: BottomAppBar(
elevation: 4,
child: Container(
height: 70,
child: Container(
padding: EdgeInsets.symmetric(horizontal: 16),
child: Row(
children: [
Expanded(
child: MaterialButton(
height: 44,
onPressed: () {
FocusScope.of(context).requestFocus(FocusNode());
//check();
},
shape: RoundedRectangleBorder(
borderRadius:
BorderRadius.circular(4)),
color: Color(0xFF2A3476),
elevation: 0,
highlightElevation: 0,
child: Container(
child: Text(
"Save",
style: TextStyle(
color: Color(0xFF2A3476),
fontSize: 15,
fontFamily: 'medium'),
),
),
),
),
],
),
),
),
),
/* bottomNavigationBar: Container(
padding: EdgeInsets.all(25.0),
decoration: BoxDecoration(color: Colors.white,
),
child: Row(
children: [
Expanded(
child: MaterialButton(
height: 44,
onPressed: () {
FocusScope.of(context).requestFocus(FocusNode());
*//* Navigator.push(context, SlidePageRoute(page:PasswordScreen()));*//*
},
shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(8.0))),
color: _isButtonEnabled ? Color(0xFF2A3476) : Color(0x201E1E99),
elevation: 0,
highlightElevation: 0,
child: Container(
child: Text(
"Next",
style: TextStyle(color: m_fillColor,fontSize: 18,fontWeight: FontWeight.w600 ,
fontFamily: "regular",),
),
),
),
),
],
),
)*/
);
}
Widget _signUp() {
return Container(
constraints: BoxConstraints.expand(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
),
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [
Color(0xFF2A3476),
Color(0xFF2A3476),
],
begin: Alignment.topLeft,
end: Alignment.centerRight,
),
),
child: Form(
key: formKey,
child: Container(
child: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding:
const EdgeInsets.symmetric(vertical: 36.0, horizontal: 24.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Create Password",
style: TextStyle(
color: Colors.white,
fontSize: 30.0,fontFamily: "medium",
fontWeight: FontWeight.w800,
),
),
],
),
),
Container(
width: double.infinity,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(30),
topRight: Radius.circular(30),
),
),
child: Padding(
padding: const EdgeInsets.all(24.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Steps to set your",
style: TextStyle(
fontSize: 22,
fontFamily: "regular",
fontWeight: FontWeight.w300,
color: Colors.black,
),
),
Text(
"password",
style: TextStyle(
fontSize: 22,
fontFamily: "regular",
fontWeight: FontWeight.w300,
color: Colors.black,
),
),
SizedBox(
height: 20.0,
), Text(
'Secret Question',
style:
TextStyle( fontSize: 15,
fontFamily: "regular",),
), SizedBox(
height: 8.0,
),
Row(
children: [
Expanded(child: InkWell(
onTap: (){
FocusScope.of(context).requestFocus(FocusNode());
secretDialogue();
},
child: Stack(
children: <Widget>[
TextField(
/* textInputAction: TextInputAction.next,*/
controller: sQuastionController,
enabled: false,
onChanged: (val) {
check(context);
},
decoration: InputDecoration(
labelText: secretVal==null?"Select One":secretVal,
contentPadding: EdgeInsets.all(8),
border: OutlineInputBorder(
borderRadius:
BorderRadius.circular(8.0),
borderSide: BorderSide.none,
),
filled: true,
fillColor: Color(0xFFE1E8F7),
hintText: "",
/* prefixIcon: Icon(
Icons.people_outline_rounded,
color: Colors.grey[600],
)*/
),
),
Positioned.directional(
textDirection: Directionality.of(context),
end: 0,
top: 0,
bottom: 0,
child: Padding(
padding: const EdgeInsets.all(8.0),
child:Image.asset(
"assets/icons/ic_drop_arrow.png",
scale: 9,
)),
)
],
),
),
),
],
),
SizedBox(
height: 20.0,
),
Text(
'Answer',
style:
TextStyle( fontSize: 15,
fontFamily: "regular",),
),
SizedBox(
height: 8.0,
),
TextField(
/* keyboardType: TextInputType.emailAddress,*/
/* textInputAction: TextInputAction.next,*/
controller: answerQController,
onChanged: (val){
check(context);
},
decoration: InputDecoration(
contentPadding: EdgeInsets.all(8),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8.0),
borderSide: BorderSide.none,
),
filled: true,
fillColor: Color(0xFFE1E8F7),
hintText: "",
/*prefixIcon: Icon(
Icons.people_outline_rounded,
color: Color(0xFFE1E8F7),
)*/),
),
SizedBox(
height: 20.0,
),
Text(
'Password',
style:
TextStyle( fontSize: 15,
fontFamily: "regular",),
),
SizedBox(
height: 8.0,
),
TextFormField(
/* keyboardType: TextInputType.emailAddress,*/
/* textInputAction: TextInputAction.next,*/
controller: passController,
onChanged: (val){
check(context);
},
//password validation
/* validator: (val){
if(val!.isEmpty)
return 'Empty';
return null;
},*/
decoration: InputDecoration(
contentPadding: EdgeInsets.all(8),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8.0),
borderSide: BorderSide.none,
),
filled: true,
fillColor: Color(0xFFE1E8F7),
hintText: "************",
),
),
SizedBox(
height: 20.0,
),
Text(
'Confirm Password',
style:
TextStyle( fontSize: 15,
fontFamily: "regular",),
),
SizedBox(
height: 8.0,
),
TextFormField(
textInputAction: TextInputAction.done,
controller: conPassController,
onChanged: (val){
check(context);
},
//password validation
/* validator: (val){
if(val!.isEmpty)
return 'Empty';
if(val != _pass.text)
return 'Not Match';
return null;
},*/
decoration: InputDecoration(
contentPadding: EdgeInsets.all(8),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8.0),
borderSide: BorderSide.none,
),
filled: true,
fillColor: Color(0xFFE1E8F7),
hintText: "************",
),
),
SizedBox(
height: 20.0,
),
SizedBox(
height: 8.0,
),
SizedBox(
height:200.0,
),
],
),
),
),
],
),
),
),
),
);
}
//
//Secret Qu Alert
List secretList =[
"-What’s your favorite team?",
"-What’s your astrological sign?",
"-What’s your favorite movie?",
"-What city were you born in?",
"-What was your first car?",
];
var secretVal;
void secretDialogue(){
showDialog<void>(
context: context,
// false = user must tap button, true = tap outside dialog
builder: (BuildContext dialogContext) {
return StatefulBuilder(
builder: (context,setState){
return Dialog(
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
insetPadding: EdgeInsets.all(20),
child: Container(
padding: EdgeInsets.symmetric(vertical: 10),
child: Column(
mainAxisSize: MainAxisSize.min,
children: List.generate(secretList.length, (index){
return InkWell(
onTap: (){
setState(() {
secretVal = secretList[index];
Navigator.pop(context);
});
},
child: Container(
height: 50,
padding: EdgeInsets.symmetric(horizontal: 20),
alignment: Alignment.centerLeft,
child: Text(secretList[index],
style: TextStyle(
fontSize: 18,
fontFamily: "medium",
),),
),
);
})
),
),
);
}
);
},
);
}
}
Wrap your Column by SingleChildScrollView. It will solve your problem.
like this..
body: SafeArea(
child: SingleChildScrollView(
child: Column(
Also I think after this there is no need of
resizeToAvoidBottomInset: false,
in Scaffold.
Please check out and I have found some inconsistency in code, refactored some of them
import 'dart:ui';
import 'package:crapp/pages/create_password/password_screen.dart';
import 'package:crapp/widgets/components/alert.dart';
import 'package:crapp/widgets/components/page_animation.dart';
import 'package:crapp/widgets/theme/constants.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:crapp/provider/theme_provider.dart';
class PasswordScreen extends StatefulWidget {
#override
_PasswordScreenState createState() => _PasswordScreenState();
}
class _PasswordScreenState extends State< PasswordScreen > {
final _controller = TextEditingController();
//validation controller
TextEditingController sQuastionController = new TextEditingController();
TextEditingController answerQController = new TextEditingController();
TextEditingController passController = new TextEditingController();
TextEditingController conPassController = new TextEditingController();
final TextEditingController _pass = TextEditingController();
final TextEditingController _confirmPass = TextEditingController();
bool _isButtonEnabled = false;
//final _controller = TextEditingController();
bool isConfirm = false;
check(BuildContext context) {
if (sQuastionController.text.isNotEmpty &&
answerQController.text.isNotEmpty &&
conPassController.text.isNotEmpty &&
passController.text.isNotEmpty) {
setState(() {
_isButtonEnabled = true;
});
} else {
setState(() {
_isButtonEnabled = false;
});
}
}
void initState() {
SystemChannels.textInput.invokeMethod('TextInput.hide');
super.initState();
}
checks (BuildContext context){
if(passController.text.isEmpty){
showDialog<void>(
context: context,
builder: (BuildContext dialogContext) {
return Alert(title: "Alert !!!",subTile: "Password must be 10 characters !",);
}
);
}else if(passController.text.length > 0 && passController.text.length < 10){
isConfirm = true;
showDialog<void>(
context: context,
builder: (BuildContext dialogContext) {
return Alert(title: "Alert !!!",subTile: "Password doesn't match !",);
}
);
}
}
checkChanged() {
if (secretVal != null) {
setState(() {
isSave = true;
});
} else {
isSave = false;
}
}
bool isSave = false;
final GlobalKey<FormState> formKey = GlobalKey<FormState>();
#override
Widget build(BuildContext context) {
/* double height = MediaQuery.of(context).size.height;
double width = MediaQuery.of(context).size.width;*/
Provider.of<ThemeProvider>(context).themeMode == ThemeMode.dark
? 'DarkTheme'
: 'LightTheme';
return Scaffold(
// resizeToAvoidBottomInset: false,
body: _signUp(),
bottomNavigationBar: BottomAppBar(
elevation: 4,
child: Container(
height: 70,
child: Container(
padding: EdgeInsets.symmetric(horizontal: 16),
child: Row(
children: [
Expanded(
child: MaterialButton(
height: 44,
onPressed: () {
FocusScope.of(context).requestFocus(FocusNode());
//check();
},
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(4)),
color: Color(0xFF2A3476),
elevation: 0,
highlightElevation: 0,
child: Container(
child: Text(
"Save",
style: TextStyle(
color: Color(0xFF2A3476),
fontSize: 15,
fontFamily: 'medium'),
),
),
),
),
],
),
),
),
),
/* bottomNavigationBar: Container(
padding: EdgeInsets.all(25.0),
decoration: BoxDecoration(color: Colors.white,
),
child: Row(
children: [
Expanded(
child: MaterialButton(
height: 44,
onPressed: () {
FocusScope.of(context).requestFocus(FocusNode());
*/ /* Navigator.push(context, SlidePageRoute(page:PasswordScreen()));*/ /*
},
shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(8.0))),
color: _isButtonEnabled ? Color(0xFF2A3476) : Color(0x201E1E99),
elevation: 0,
highlightElevation: 0,
child: Container(
child: Text(
"Next",
style: TextStyle(color: m_fillColor,fontSize: 18,fontWeight: FontWeight.w600 ,
fontFamily: "regular",),
),
),
),
),
],
),
)*/
);
}
Widget _signUp() {
return Container(
width: MediaQuery.of(context).size.width,
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [
Color(0xFF2A3476),
Color(0xFF2A3476),
],
begin: Alignment.topLeft,
end: Alignment.centerRight,
),
),
child: SingleChildScrollView(
child: Form(
key: formKey,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.symmetric(
vertical: 36.0, horizontal: 24.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Create Password",
style: TextStyle(
color: Colors.white,
fontSize: 30.0,
fontFamily: "medium",
fontWeight: FontWeight.w800,
),
),
],
),
),
Container(
width: double.infinity,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(30),
topRight: Radius.circular(30),
),
),
child: Padding(
padding: const EdgeInsets.all(24.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Steps to set your",
style: TextStyle(
fontSize: 22,
fontFamily: "regular",
fontWeight: FontWeight.w300,
color: Colors.black,
),
),
Text(
"password",
style: TextStyle(
fontSize: 22,
fontFamily: "regular",
fontWeight: FontWeight.w300,
color: Colors.black,
),
),
SizedBox(
height: 20.0,
),
Text(
'Secret Question',
style: TextStyle(
fontSize: 15,
fontFamily: "regular",
),
),
SizedBox(
height: 8.0,
),
Row(
children: [
Expanded(
child: InkWell(
onTap: () {
FocusScope.of(context)
.requestFocus(FocusNode());
secretDialogue();
},
child: Stack(
children: <Widget>[
TextField(
/* textInputAction: TextInputAction.next,*/
controller: sQuastionController,
enabled: false,
onChanged: (val) {
check(context);
},
decoration: InputDecoration(
labelText: secretVal == null
? "Select One"
: secretVal,
contentPadding: EdgeInsets.all(8),
border: OutlineInputBorder(
borderRadius:
BorderRadius.circular(8.0),
borderSide: BorderSide.none,
),
filled: true,
fillColor: Color(0xFFE1E8F7),
hintText: "",
/* prefixIcon: Icon(
Icons.people_outline_rounded,
color: Colors.grey[600],
)*/
),
),
Positioned.directional(
textDirection: Directionality.of(context),
end: 0,
top: 0,
bottom: 0,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Image.asset(
"assets/icons/ic_drop_arrow.png",
scale: 9,
)),
)
],
),
),
),
],
),
SizedBox(
height: 20.0,
),
Text(
'Answer',
style: TextStyle(
fontSize: 15,
fontFamily: "regular",
),
),
SizedBox(
height: 8.0,
),
GestureDetector(
onTap: () {
FocusScope.of(context).requestFocus(new FocusNode());
},
child: TextField(
/* keyboardType: TextInputType.emailAddress,*/
/* textInputAction: TextInputAction.next,*/
controller: answerQController,
onChanged: (val) {
check(context);
},
decoration: InputDecoration(
contentPadding: EdgeInsets.all(8),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8.0),
borderSide: BorderSide.none,
),
filled: true,
fillColor: Color(0xFFE1E8F7),
hintText: "",
/*prefixIcon: Icon(
Icons.people_outline_rounded,
color: Color(0xFFE1E8F7),
)*/
),
),
),
SizedBox(
height: 20.0,
),
Text(
'Password',
style: TextStyle(
fontSize: 15,
fontFamily: "regular",
),
),
SizedBox(
height: 8.0,
),
GestureDetector(
onTap: () {
FocusScope.of(context).requestFocus(new FocusNode());
},
child: TextFormField(
/* keyboardType: TextInputType.emailAddress,*/
/* textInputAction: TextInputAction.next,*/
controller: passController,
onChanged: (val) {
check(context);
},
//password validation
/* validator: (val){
if(val!.isEmpty)
return 'Empty';
return null;
},*/
decoration: InputDecoration(
contentPadding: EdgeInsets.all(8),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8.0),
borderSide: BorderSide.none,
),
filled: true,
fillColor: Color(0xFFE1E8F7),
hintText: "************",
),
),
),
SizedBox(
height: 20.0,
),
Text(
'Confirm Password',
style: TextStyle(
fontSize: 15,
fontFamily: "regular",
),
),
SizedBox(
height: 8.0,
),
GestureDetector(
onTap: () {
FocusScope.of(context).requestFocus(new FocusNode());
},
child: TextFormField(
textInputAction: TextInputAction.done,
controller: conPassController,
onChanged: (val) {
check(context);
},
//password validation
/* validator: (val){
if(val!.isEmpty)
return 'Empty';
if(val != _pass.text)
return 'Not Match';
return null;
},*/
decoration: InputDecoration(
contentPadding: EdgeInsets.all(8),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8.0),
borderSide: BorderSide.none,
),
filled: true,
fillColor: Color(0xFFE1E8F7),
hintText: "************",
),
),
),
SizedBox(
height: 20.0,
),
SizedBox(
height: 8.0,
),
SizedBox(
height: 200.0,
),
],
),
),
),
],
),
),
),
);
}
//
//Secret Qu Alert
List secretList = [
"-What’s your favorite team?",
"-What’s your astrological sign?",
"-What’s your favorite movie?",
"-What city were you born in?",
"-What was your first car?",
];
var secretVal;
void secretDialogue() {
showDialog<void>(
context: context,
// false = user must tap button, true = tap outside dialog
builder: (BuildContext dialogContext) {
return StatefulBuilder(builder: (context, setState) {
return Dialog(
shape:
RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
insetPadding: EdgeInsets.all(20),
child: Container(
padding: EdgeInsets.symmetric(vertical: 10),
child: Column(
mainAxisSize: MainAxisSize.min,
children: List.generate(secretList.length, (index) {
return InkWell(
onTap: () {
setState(() {
secretVal = secretList[index];
Navigator.pop(context);
});
},
child: Container(
height: 50,
padding: EdgeInsets.symmetric(horizontal: 20),
alignment: Alignment.centerLeft,
child: Text(
secretList[index],
style: TextStyle(
fontSize: 18,
fontFamily: "medium",
),
),
),
);
})),
),
);
});
},
);
}
}
Login/Signup form is supposed to move to homepage on validation of the submit button (an arrow forward button icon) and if not validated, it ought to show a snackbar saying 'Error', but nothing works.
It keeps on giving this error message on button click "Another exception was thrown: NoSuchMethodError: The method 'validate' was called on null."
Here is my code:
import 'package:flutter/cupertino.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:community_material_icon/community_material_icon.dart';
import 'package:time_to_eat_devotionals/screens/home.dart';
import 'package:time_to_eat_devotionals/theme/palette.dart';
class LoginSignupScreen extends StatefulWidget {
#override
_LoginSignupScreenState createState() => _LoginSignupScreenState();
}
class _LoginSignupScreenState extends State<LoginSignupScreen> {
bool isSignUpScreen = true;
bool isRememberMe = false;
final _formkey = GlobalKey<FormState>();
TextEditingController usernameController = TextEditingController();
TextEditingController emailController = TextEditingController();
TextEditingController passwordController = TextEditingController();
TextEditingController nationalityController = TextEditingController();
var countryName = ['Nigeria', 'Ghana'];
#override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [Colors.yellow, Palette.backgroundColor]
),
),
child: Scaffold(
backgroundColor: Colors.transparent,
body: Stack(
children: [
Positioned(
top: 0,
right: 0,
left: 0,
child: Container(
height: 300,
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage(isSignUpScreen? 'assets/images/signupbg.jpg' : 'assets/images/loginbg.jpg'),
fit: BoxFit.fill)),
child: Container(
padding: EdgeInsets.only(top: 90, left: 20),
color: Colors.black.withOpacity(.65),
child: Column(
children: [
RichText(
text: TextSpan(
text: isSignUpScreen? 'Welcome To' : 'Welcome Back',
style: TextStyle(
fontFamily: 'Raleway',
fontSize: 18,
color: Colors.white))),
Container(
height: 8.0,
),
Text(
'Time To Eat Devotionals',
style: TextStyle(
fontFamily: 'Kurale',
fontWeight: FontWeight.w600,
fontSize: 30.0,
color: Colors.white),
),
Container(
height: 8.0,
),
Text(
isSignUpScreen? 'Signup to continue': 'Login to continue',
style: TextStyle(
fontFamily: 'Raleway',
fontSize: 14.0,
color: Colors.white),
)
],
),
),
),
),
AnimatedPositioned(
duration: Duration(milliseconds: 700),
curve: Curves.bounceOut,
top: isSignUpScreen? 200 : 250,
child: AnimatedContainer(
duration: Duration(milliseconds: 700),
curve: Curves.bounceOut,
padding: EdgeInsets.only(top: 5, bottom: 20, right: 20, left: 20),
height: isSignUpScreen? 350 : 280,
width: MediaQuery.of(context).size.width - 40,
margin: EdgeInsets.symmetric(horizontal: 20),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(15),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.3),
blurRadius: 15,
spreadRadius: 5)
]),
child: SingleChildScrollView(
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
GestureDetector(
onTap: () {
setState(() {
isSignUpScreen = true;
});
},
child: Column(
children: [
Text(
"SIGNUP",
style: TextStyle(
fontFamily: 'baloo da 2',
fontSize: 21,
fontWeight: FontWeight.w500,
color: isSignUpScreen
? Palette.activeColor
: Colors.black),
),
if (isSignUpScreen)
Container(
margin: EdgeInsets.only(top: 1.0),
height: 2,
width: 55,
color: Colors.black,
)
],
),
),
GestureDetector(
onTap: () {
setState(() {
isSignUpScreen = false;
});
},
child: Column(
children: [
Text(
"LOGIN",
style: TextStyle(
fontFamily: 'baloo da 2',
fontSize: 21,
fontWeight: FontWeight.w500,
color: isSignUpScreen
? Colors.black
: Palette.activeColor),
),
if (!isSignUpScreen)
Container(
margin: EdgeInsets.only(top: 1.0),
height: 2,
width: 55,
color: Colors.black,
)
],
)),
],
),
isSignUpScreen?
Container(
key: _formkey,
margin: EdgeInsets.only(top: 10),
child: Column(
children: [
buidTextField(Icons.person, 'User Name', 'Enter your user name', false, false, usernameController, (username){
if (username.isEmpty) {
return 'Username is required';
} else if (username.length <6) {
return 'Username is short';
}
return null;
}),
buidTextField(Icons.email, 'Email', 'Enter your valid email address', false, true, emailController, (signupEmail){
if (signupEmail.isEmpty) {
return 'Email is required';
} else if (!signupEmail.contains('#')) {
return 'Please enter a valid email address';
}
return null;
}),
buidTextField(Icons.lock, 'Password', 'Enter your password', true, false, passwordController, (signupPword){
if (signupPword.isEmpty) {
return 'Password is required';
} else if (signupPword.length <8) {
return 'Password must be at least 8 characters';
}
return null;
}),
buidTextField(Icons.flag, 'Nationality', 'What country are you from', false, false, nationalityController, (nationality){
if (nationality.isEmpty) {
return 'Enter Your Nationality';
} else if (!nationality.contain(countryName)) {
return 'Please enter a valid Country name';
}
return null;
}),
RichText(
textAlign: TextAlign.center,
text: TextSpan(
text: "By pressing 'Submit', you agree to our \n",
style: TextStyle(
color: Colors.black,
fontFamily: 'raleway',
fontSize: 13.0, letterSpacing: 0.1
),
children: [
TextSpan(
recognizer: TapGestureRecognizer()
..onTap = () {
print('T&C is clicked');
},
text: 'Terms and Conditions',
style: TextStyle(
color: Palette.backgroundColor,
fontFamily: 'raleway',
fontSize: 13.0, letterSpacing: 0.1,
fontWeight: FontWeight.w500
)
)
]
),
),
],
),)
:
Container(
key: _formkey,
margin: EdgeInsets.only(top: 20),
child: Column(
children: [
buidTextField(Icons.email, 'Email', 'info#example.com', false, true, emailController, (signinEmail){
if (signinEmail.isEmpty) {
return 'Username is required';
} else if (signinEmail.length <6) {
return 'Username is short';
}
return null;
}),
buidTextField(Icons.lock, 'Password', '********', true, false, passwordController, (signinPword){
if (signinPword.isEmpty) {
return 'Password is required';
} else if (signinPword.length <8) {
return 'Password should be at least 8 characters';
}
return null;
}),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(children: [
Checkbox(
value: isRememberMe,
activeColor: Colors.black,
onChanged: (value) {
setState(() {
isRememberMe = !isRememberMe;
});
}
),
Text(
"Remember Me",
style: TextStyle(
fontFamily: 'raleway',
fontSize: 15.0,
),
)
],),
TextButton(
onPressed: () {
print('Forgot Password clicked');
},
child: Text(
'Forgot Password?',
style: TextStyle(
fontFamily: 'raleway',
fontSize: 15.0,
color: Palette.backgroundColor
)
)
)
],
)
],
)
)
],
),
),
)),
AnimatedPositioned(
duration: Duration(milliseconds: 700),
curve: Curves.easeIn,
top: isSignUpScreen? 500 : 480,
right: 0,
left:0,
child: Center(
child: Container(
padding: EdgeInsets.all(15),
height: 90,
width: 90,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(50),
),
child: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [Colors.yellow, Palette.backgroundColor]),
borderRadius: BorderRadius.circular(30),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(.3),
spreadRadius: 1,
blurRadius: 2,
offset: Offset(0, 1)
),
]
),
child: IconButton(
onPressed: () {
setState(() {
if (_formkey.currentState.validate()) {
Navigator.push(context, MaterialPageRoute(builder: (context) => Home()));
} else {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Error'))
);
}
});
},
icon: Icon(Icons.arrow_forward, color: Colors.white,)
),
),
),
)
),
Positioned(
top: MediaQuery.of(context).size.height-100,
right: 0,
left: 0,
child: Column(
children: [
Text(
"Or Signup with",
style: TextStyle(
fontFamily: 'raleway',
fontSize:15.0,
color: Colors.white,
fontWeight: FontWeight.w600
),
),
SizedBox(height: 10,),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
buildTextButton(CommunityMaterialIcons.facebook, 'Facebook', Palette.fbColor),
buildTextButton(CommunityMaterialIcons.google, 'Google', Palette.googleColor),
],
)
],
)
)
],
),
),
);
}
TextButton buildTextButton(IconData icon, String title, Color backgroundColor,) {
return TextButton(
onPressed: () {},
style: TextButton.styleFrom(
backgroundColor: backgroundColor,
primary: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20),
),
side:BorderSide(
width: 1.5,
color: Colors.white
),
minimumSize: Size(140, 40)
),
child: Row(
children: [
Icon(
icon,
color: Colors.white,
size: 22,
),
SizedBox(width: 10,),
Text(
title,
style: TextStyle(
color: Colors.white,
fontFamily: 'baloo da 2',
fontSize: 18
),
)
],
)
);
}
Widget buidTextField(
IconData icon, String labelText, String hintText, bool isPassword, bool isEmail, TextEditingController controller, Function validator) {
return Form(
child: Padding(
padding: const EdgeInsets.only(bottom: 8.0),
child: Column(
children:[
TextFormField(
validator: validator,
controller: controller,
obscureText: isPassword,
keyboardType: isEmail? TextInputType.emailAddress : TextInputType.text,
decoration: InputDecoration(
prefixIcon: Icon(
icon,
color: Colors.black,
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(15),
borderSide: BorderSide(color: Colors.black)),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(15),
borderSide: BorderSide(color: Colors.black)),
labelText: labelText,
labelStyle: TextStyle(fontFamily: 'raleway'),
hintText: hintText,
hintStyle: TextStyle(
fontSize: 14.0,
fontFamily: 'raleway',
),
contentPadding: EdgeInsets.all(10)),
),
]
),
),);
}
}
initialize your form key like this
final GlobalKey<FormState> _formkey = GlobalKey<FormState>();
I am currently working on a flutter project. I made a flat button in the bottom and made the function _submit() as the onPressed method. But it seems like _formKey.currentState.validate() is having an error. The error message is like what's shown below
The method 'validate' was called on null.
Receiver: null
Tried calling: validate()
I found similar questions to mine and tried to fix it. But I can't find my mistake.
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
class AddTaskScreen extends StatefulWidget {
AddTaskScreen({Key key}) : super(key: key);
#override
_AddTaskScreenState createState() => _AddTaskScreenState();
}
class _AddTaskScreenState extends State<AddTaskScreen> {
final _formKey = GlobalKey<FormState>();
String _title = '';
String _priority;
DateTime _date = DateTime.now();
TextEditingController _dateController = TextEditingController();
final DateFormat _dateFormatter = DateFormat('MMM dd, yyy');
final List<String> _priorities = ['Low', 'Medium', 'High'];
_handleDatePicker() async {
final DateTime date = await showDatePicker(
context: context,
initialDate: _date,
firstDate: DateTime(2000),
lastDate: DateTime(2100));
if (date != null && date != _date) {
setState(() {
_date = date;
});
_dateController.text = _dateFormatter.format(date);
}
}
_submit() {
if (_formKey.currentState.validate()) {
_formKey.currentState.save();
print('$_title $_date $_priority');
Navigator.pop(context);
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: GestureDetector(
onTap: () => FocusScope.of(context).unfocus(),
child: SingleChildScrollView(
child: Container(
padding: EdgeInsets.symmetric(horizontal: 40.0, vertical: 80.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
GestureDetector(
onTap: () => Navigator.pop(context),
child: Icon(
Icons.arrow_back_ios,
size: 30.0,
color: Colors.black,
),
),
SizedBox(
height: 20.0,
),
Text('Add Task',
style: TextStyle(
color: Colors.black,
fontSize: 40.0,
fontWeight: FontWeight.bold)),
SizedBox(height: 10.0),
Form(
key: _formKey,
child: Column(
children: <Widget>[
Padding(
padding: EdgeInsets.symmetric(vertical: 20.0),
child: TextFormField(
style: TextStyle(fontSize: 18.0),
decoration: InputDecoration(
labelText: 'Title',
labelStyle: TextStyle(fontSize: 18.0),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10.0))),
validator: (input) => input.trim().isEmpty
? 'Please enter a task title'
: null,
onSaved: (input) => _title = input,
initialValue: _title),
),
Padding(
padding: EdgeInsets.symmetric(vertical: 20.0),
child: TextFormField(
readOnly: true,
controller: _dateController,
style: TextStyle(fontSize: 18.0),
onTap: _handleDatePicker,
decoration: InputDecoration(
labelText: 'Date',
labelStyle: TextStyle(fontSize: 18.0),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10.0))),
)),
Padding(
padding: EdgeInsets.symmetric(vertical: 20.0),
child: DropdownButtonFormField(
icon: Icon(Icons.arrow_drop_down_circle),
iconSize: 22.0,
items: _priorities.map((String priority) {
return DropdownMenuItem(
value: priority,
child: Text(
priority,
style: TextStyle(
color: Colors.black, fontSize: 18.0),
),
);
}).toList(),
style: TextStyle(fontSize: 18.0),
decoration: InputDecoration(
labelText: 'Priority',
labelStyle: TextStyle(fontSize: 18.0),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10.0))),
validator: (input) => _priority == null
? 'Please select a priority level'
: null,
onChanged: (value) {
setState(() {
_priority = value;
});
},
value: _priority,
)),
Container(
margin: EdgeInsets.symmetric(vertical: 20.0),
height: 60.0,
width: double.infinity,
decoration: BoxDecoration(
color: Colors.black,
borderRadius: BorderRadius.circular(30.0)),
child: FlatButton(
onPressed: _submit(),
child: Text(
'Add',
style: TextStyle(
color: Colors.white, fontSize: 20.0),
)),
)
],
),
)
],
),
),
),
),
);
}
}
You can copy paste run full code below
You can change _submit() to _submit
Because _submit() means execute function
code snippet change from
FlatButton(
onPressed: _submit(),
to
FlatButton(
onPressed: _submit,
working demo
full code
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
class AddTaskScreen extends StatefulWidget {
AddTaskScreen({Key key}) : super(key: key);
#override
_AddTaskScreenState createState() => _AddTaskScreenState();
}
class _AddTaskScreenState extends State<AddTaskScreen> {
final _formKey = GlobalKey<FormState>();
String _title = '';
String _priority;
DateTime _date = DateTime.now();
TextEditingController _dateController = TextEditingController();
final DateFormat _dateFormatter = DateFormat('MMM dd, yyy');
final List<String> _priorities = ['Low', 'Medium', 'High'];
_handleDatePicker() async {
final DateTime date = await showDatePicker(
context: context,
initialDate: _date,
firstDate: DateTime(2000),
lastDate: DateTime(2100));
if (date != null && date != _date) {
setState(() {
_date = date;
});
_dateController.text = _dateFormatter.format(date);
}
}
_submit() {
if (_formKey.currentState.validate()) {
_formKey.currentState.save();
print('$_title $_date $_priority');
Navigator.pop(context);
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: GestureDetector(
onTap: () => FocusScope.of(context).unfocus(),
child: SingleChildScrollView(
child: Container(
padding: EdgeInsets.symmetric(horizontal: 40.0, vertical: 80.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
GestureDetector(
onTap: () => Navigator.pop(context),
child: Icon(
Icons.arrow_back_ios,
size: 30.0,
color: Colors.black,
),
),
SizedBox(
height: 20.0,
),
Text('Add Task',
style: TextStyle(
color: Colors.black,
fontSize: 40.0,
fontWeight: FontWeight.bold)),
SizedBox(height: 10.0),
Form(
key: _formKey,
child: Column(
children: <Widget>[
Padding(
padding: EdgeInsets.symmetric(vertical: 20.0),
child: TextFormField(
style: TextStyle(fontSize: 18.0),
decoration: InputDecoration(
labelText: 'Title',
labelStyle: TextStyle(fontSize: 18.0),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10.0))),
validator: (input) => input.trim().isEmpty
? 'Please enter a task title'
: null,
onSaved: (input) => _title = input,
initialValue: _title),
),
Padding(
padding: EdgeInsets.symmetric(vertical: 20.0),
child: TextFormField(
readOnly: true,
controller: _dateController,
style: TextStyle(fontSize: 18.0),
onTap: _handleDatePicker,
decoration: InputDecoration(
labelText: 'Date',
labelStyle: TextStyle(fontSize: 18.0),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10.0))),
)),
Padding(
padding: EdgeInsets.symmetric(vertical: 20.0),
child: DropdownButtonFormField(
icon: Icon(Icons.arrow_drop_down_circle),
iconSize: 22.0,
items: _priorities.map((String priority) {
return DropdownMenuItem(
value: priority,
child: Text(
priority,
style: TextStyle(
color: Colors.black, fontSize: 18.0),
),
);
}).toList(),
style: TextStyle(fontSize: 18.0),
decoration: InputDecoration(
labelText: 'Priority',
labelStyle: TextStyle(fontSize: 18.0),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10.0))),
validator: (input) => _priority == null
? 'Please select a priority level'
: null,
onChanged: (value) {
setState(() {
_priority = value;
});
},
value: _priority,
)),
Container(
margin: EdgeInsets.symmetric(vertical: 20.0),
height: 60.0,
width: double.infinity,
decoration: BoxDecoration(
color: Colors.black,
borderRadius: BorderRadius.circular(30.0)),
child: FlatButton(
onPressed: _submit,
child: Text(
'Add',
style: TextStyle(
color: Colors.white, fontSize: 20.0),
)),
)
],
),
)
],
),
),
),
),
);
}
}
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: AddTaskScreen(),
);
}
}
Attached the image of my desired output I need to create an Add Card form page , where there are 2 tabbed appbars. One is Debit Card and other is Credit Card. I need to get the details , so I need to include a form , with a next button at the bottom. The whole form should be overlapped above the appbar. I have attached my desired output screen and my output. Please help me.
import 'package:flutter/material.dart';
import 'package:rewahub/Addcard/form.dart';
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
TextStyle style = TextStyle(fontFamily: 'Montserrat', fontSize: 20.0);
#override
Widget build(BuildContext context) {
final emailField = TextFormField(
//obscureText: true,
style: style,
decoration: InputDecoration(
contentPadding: EdgeInsets.fromLTRB(20.0, 0, 0, 10.0),
labelText: "Card Number",
hintText: 'xxxx xxxx xxxx xxxx',
),
);
final Exp_Date = TextFormField(
obscureText: true,
style: style,
decoration: InputDecoration(
contentPadding: EdgeInsets.fromLTRB(20.0,0,0,10.0),
labelText: "Exp Date",
hintText: "MM/YY",
),
);
final name = TextFormField(
obscureText: true,
style: style,
decoration: InputDecoration(
contentPadding: EdgeInsets.fromLTRB(20.0,0,0,10.0),
labelText: "Name",
hintText: "Name of the card holder",
),
);
final CVV = TextFormField(
obscureText: true,
style: style,
decoration: InputDecoration(
contentPadding: EdgeInsets.fromLTRB(20.0,0,0,10.0),
labelText: "CVV",
hintText: "XXXX",
),
);
final text1=Text("Prototype");
final nextButon = Material(
elevation: 5.0,
borderRadius: BorderRadius.circular(15.0),
color: Color(0XFFab2785),
child: MaterialButton(
minWidth: MediaQuery.of(context).size.width,
padding: EdgeInsets.fromLTRB(20.0, 15.0, 20.0, 15.0),
onPressed: () {},
child: Text("NEXT",
textAlign: TextAlign.center,
style: style.copyWith(
color: Colors.white, fontWeight: FontWeight.bold)),
),
);
return Scaffold(
appBar:PreferredSize(
preferredSize: Size.fromHeight(240.0),
child: new AppBar(
centerTitle: true,
title: Column(children: [
Text(
"rewahub",
),
GestureDetector(
child: Text('PAYMENT METHODS'),
onTap: () {
print("tapped subtitle");
},
)
]),
backgroundColor: Color.fromRGBO(189, 78, 97, 1),
), ),
body: SingleChildScrollView(
child: Center(
child: Container(
color: Colors.white,
child: Padding(
padding: const EdgeInsets.all(40.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
SizedBox(height: 15.0),
emailField,
SizedBox(height: 15.0),
Exp_Date,
SizedBox(height: 15.0),
name,
SizedBox(height: 15.0),
CVV,
SizedBox(height: 15.0,),
text1,
SizedBox(height: 15.0,),
nextButon,
],
),
),
),
),
)
);
}
}
I have made some changes in your code please check below
import 'package:flutter/material.dart';
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
TextStyle style = TextStyle(fontFamily: 'Montserrat', fontSize: 20.0);
int selectedTab = 0;
Widget emailField() {
return TextFormField(
//obscureText: true,
style: style,
decoration: InputDecoration(
contentPadding: EdgeInsets.fromLTRB(20.0, 0, 0, 10.0),
labelText: "Card Number",
hintText: 'xxxx xxxx xxxx xxxx',
),
);
}
Widget Exp_Date() {
return TextFormField(
obscureText: true,
style: style,
decoration: InputDecoration(
contentPadding: EdgeInsets.fromLTRB(20.0, 0, 0, 10.0),
labelText: "Exp Date",
hintText: "MM/YY",
),
);
}
Widget name() {
return TextFormField(
obscureText: true,
style: style,
decoration: InputDecoration(
contentPadding: EdgeInsets.fromLTRB(20.0, 0, 0, 10.0),
labelText: "Name",
hintText: "Name of the card holder",
),
);
}
Widget CVV() {
return TextFormField(
obscureText: true,
style: style,
decoration: InputDecoration(
contentPadding: EdgeInsets.fromLTRB(20.0, 0, 0, 10.0),
labelText: "CVV",
hintText: "XXXX",
),
);
}
final text1 = Text("Prototype");
Widget nextButon() {
return Material(
elevation: 5.0,
borderRadius: BorderRadius.circular(15.0),
color: Color(0XFFab2785),
child: MaterialButton(
minWidth: MediaQuery.of(context).size.width,
padding: EdgeInsets.fromLTRB(20.0, 15.0, 20.0, 15.0),
onPressed: () {},
child: Text(
"NEXT",
textAlign: TextAlign.center,
style: style.copyWith(
color: Colors.white,
fontWeight: FontWeight.bold,
),
),
),
);
}
#override
Widget build(BuildContext context) {
return DefaultTabController(
length: 2,
child: Scaffold(
body: Stack(
children: <Widget>[
Container(
height: 240.0,
color: Color.fromRGBO(189, 78, 97, 1),
),
Column(
children: <Widget>[
AppBar(
elevation: 0,
centerTitle: true,
title: GestureDetector(
child: Text('PAYMENT METHODS'),
onTap: () {
print("tapped subtitle");
},
),
backgroundColor: Color.fromRGBO(189, 78, 97, 1),
),
SizedBox(
height: 20,
),
TabBar(
labelStyle: Theme.of(context).textTheme.body2,
indicator: UnderlineTabIndicator(
borderSide: BorderSide(width: 2, color: Colors.white),
insets: EdgeInsets.symmetric(
horizontal: 0,
),
),
onTap: (int position) {
setState(() {
selectedTab = position;
});
},
tabs: [
Tab(
child: new Text(
"Credit Card",
style: Theme.of(context)
.textTheme
.body1
.apply(color: Colors.white),
),
),
Tab(
child: new Text(
"Debit Card",
style: Theme.of(context)
.textTheme
.body1
.apply(color: Colors.white),
),
),
],
),
selectedTab == 0 ? creditCard() : debitCard(),
],
),
],
),
),
);
}
Widget creditCard() {
return SingleChildScrollView(
child: Container(
margin: EdgeInsets.all(40),
child: Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20.0),
),
child: Center(
child: Container(
color: Colors.white,
child: Padding(
padding: const EdgeInsets.all(40.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
SizedBox(height: 15.0),
emailField(),
SizedBox(height: 15.0),
Exp_Date(),
SizedBox(height: 15.0),
name(),
SizedBox(height: 15.0),
CVV(),
SizedBox(height: 15.0),
text1,
SizedBox(height: 15.0),
nextButon(),
],
),
),
),
),
),
),
);
}
Widget debitCard() {
return SingleChildScrollView(
child: Container(
margin: EdgeInsets.all(40),
child: Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20.0),
),
child: Center(
child: Container(
color: Colors.white,
child: Padding(
padding: const EdgeInsets.all(40.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
SizedBox(height: 15.0),
emailField(),
SizedBox(height: 15.0),
Exp_Date(),
SizedBox(height: 15.0),
name(),
SizedBox(height: 15.0),
CVV(),
SizedBox(height: 15.0),
text1,
SizedBox(height: 15.0),
nextButon(),
],
),
),
),
),
),
),
);
}
}