How to launch once login and splash screen page after app start - dart

I'm developing a login page and splash screen for a certain application, how can I set those route to launch only once?
Stack(
fit: StackFit.loose,
children: <Widget>[
Image(
image: AssetImage('images/home.png'),
fit: BoxFit.cover,
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
),
Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
// SizedBox(height: 20.0),
//height was 60
Column(
children: <Widget>[
SizedBox(
height: 30.0,
),
Text(
"SMART HYDROPONICS",
style: TextStyle(
color: Colors.white,
fontSize: 22.0,
fontWeight: FontWeight.bold,
),
),
SizedBox(
height: 30.0,
),
CircleAvatar(
backgroundColor: Colors.white,
radius: 90.0,
child: Container(
alignment: Alignment.center,
child: CircleAvatar(
backgroundColor: Colors.green,
child: Text(
'REGISTER',
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.white),
),
radius: 70.0,
),
)),
],
),
SizedBox(height: 20.0),
Form(
key: _key,
autovalidate: _autovalidate,
child: Column(children: <Widget>[
TextFormField(
decoration: InputDecoration(
hintText: "Enter Name",
border: InputBorder.none,
hintStyle: TextStyle(
color: Colors.white,
wordSpacing: 20.0,
fontWeight: FontWeight.normal,
fontSize: 18.0),
icon: Icon(
Icons.nature_people,
size: 30.0,
color: Colors.black,
)),
maxLength: 25,
keyboardType: TextInputType.text,
obscureText: false,
textAlign: TextAlign.justify,
onSaved: (val) {
_name = val;
},
validator: _myName,
),
SizedBox(
height: 20.0,
),
SizedBox(height: 40.0),
TextFormField(
textCapitalization: TextCapitalization.characters,
decoration: InputDecoration(
hintText: "Enter Number",
border: InputBorder.none,
// contentPadding: EdgeInsets.all(0.0),
hintStyle: TextStyle(
color: Colors.white,
wordSpacing: 20.0,
fontWeight: FontWeight.normal,
fontSize: 18.0),
icon: Icon(
Icons.phone,
size: 30.0,
color: Colors.black,
)),
maxLength: 10,
maxLines: 1,
keyboardType: TextInputType.phone,
obscureText: false,
textAlign: TextAlign.justify,
onSaved: (val) {
_number = val;
},
validator: _myNumber,
),
SizedBox(
height: 50.0,
),
TextFormField(
textCapitalization: TextCapitalization.characters,
decoration: InputDecoration(
hintText: "Product ID",
border: InputBorder.none,
// contentPadding: EdgeInsets.all(0.0),
hintStyle: TextStyle(
color: Colors.white,
wordSpacing: 20.0,
fontWeight: FontWeight.normal,
fontSize: 18.0),
icon: Icon(
Icons.settings_brightness,
size: 30.0,
color: Colors.black,
)),
maxLength: 10,
maxLines: 1,
keyboardType: TextInputType.phone,
obscureText: false,
textAlign: TextAlign.justify,
onSaved: (val) {
_number = val;
},
validator: _productId,
),
// SizedBox(height: MediaQuery.of(context).size.height/990000 ),
RaisedButton(
onPressed: _sendToServer,
color: Colors.greenAccent,
child: Text(
"Finish",
style: TextStyle(
color: Colors.white,
),
)),
]),
),
]),
],
)

You'll want to keep persistent state (like login tokens or flags marking things as viewed/accepted) via the shared_preferences plugin or some other persistent store that's local like sqlite or a flat file.

Related

Flutter IOS Bottomsheet blinking when multiple textfields add and open the keyboard

I have used the bottomsheet at one of my flutter project. It works perfectly on android and IOS simulator. When I run the project on real iPhone I am facing issues. please check attached code and image.
_changePasswordBottomSheet() {
showModalBottomSheet(
isScrollControlled: true,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
context: context,
builder: (builder) {
return Padding(
padding: MediaQuery.of(context).viewInsets,
child: Container(
padding: EdgeInsets.symmetric(horizontal: 15),
height: 400,
color: Colors.transparent,
child: Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: const Radius.circular(10.0),
topRight: const Radius.circular(10.0))),
child: Column(
children: [
Padding(
padding: EdgeInsets.all(12.w),
child: InkWell(
onTap: () {
NavigationService().setPopNavigator();
},
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
setWidth(25),
setComonText(
'CHANGE PASSWORD',
setAlignment: TextAlign.center,
style: CustomTheme().setTextStyle(
fontsize: 18.w,
weight: weight.semibold,
color: C.blackTxt),
),
Container(
height: 25.w,
width: 25.w,
decoration: BoxDecoration(
color: C.primaryGreyColor,
borderRadius: BorderRadius.circular(12.5.w),
),
child: Icon(
Icons.close,
color: C.white,
size: 16.w,
)),
],
),
),
),
setHight(25.w),
Container(
padding: EdgeInsets.symmetric(horizontal: 8),
decoration: BoxDecoration(
border: Border.all(color: C.boxBorderColor),
borderRadius: BorderRadius.circular(5)),
child: TextFormField(
controller: editController.signupPassword,
obscureText: true,
decoration: InputDecoration(
hintText: "Passsword",
border: InputBorder.none,
hintStyle: CustomTheme().setTextStyle(
fontsize: 16.w,
weight: weight.semibold,
color: C.boxBorderColor)),
style: CustomTheme().setTextStyle(
fontsize: 16.w, weight: weight.semibold),
),
),
setHight(35.w),
Container(
padding: EdgeInsets.symmetric(horizontal: 8),
decoration: BoxDecoration(
border: Border.all(color: C.boxBorderColor),
borderRadius: BorderRadius.circular(5)),
child: TextFormField(
controller: editController.signupNewPass,
obscureText: true,
decoration: InputDecoration(
hintText: "New Passsword",
border: InputBorder.none,
hintStyle: CustomTheme().setTextStyle(
fontsize: 16.w,
weight: weight.semibold,
color: C.boxBorderColor)),
style: CustomTheme().setTextStyle(
fontsize: 16.w, weight: weight.semibold),
),
),
setHight(10.w),
Container(
padding: EdgeInsets.symmetric(horizontal: 8),
decoration: BoxDecoration(
border: Border.all(color: C.boxBorderColor),
borderRadius: BorderRadius.circular(5)),
child: TextFormField(
controller: editController.signupConfirmPass,
obscureText: true,
decoration: InputDecoration(
hintText: "Confirm Passsword",
border: InputBorder.none,
hintStyle: CustomTheme().setTextStyle(
fontsize: 16.w,
weight: weight.semibold,
color: C.boxBorderColor)),
style: CustomTheme().setTextStyle(
fontsize: 16.w, weight: weight.semibold),
),
),
setHight(50.w),
Row(
children: [
setWidth(20.w),
Expanded(
child: createButton(
width: setDeviceWidth() - 40.w,
text: 'CANCEL',
txtColor: C.white,
btnColour: C.primaryGreyColor,
onBtnClick: () {
editController.cancelPassword();
NavigationService().setPopNavigator();
},
fontSize: 14.w,
height: 45.w,
borderRadius: BorderRadius.circular(22.5.w)),
),
setWidth(20.w),
Expanded(
child: createButton(
width: setDeviceWidth() - 40.w,
text: 'SAVE',
txtColor: C.white,
onBtnClick: () {
editController.cancelPassword();
NavigationService().setPopNavigator();
modalBottomSheetSuccess(
'Password Saved \nSuccessfully!');
TimerUtils().startTimer(() {
NavigationService().setPopNavigator();
});
},
fontSize: 14.w,
height: 45.w,
borderRadius: BorderRadius.circular(22.5.w)),
),
setWidth(20.w),
],
)
],
)),
),
);
});
}
Attached Image is:

Flutter TextFormField in iOS randomly jumping to the previous field

Here's a link for a GIF of its unwanted behavior
I have 2 TextFormField(username and PIN) inside a Form in this page. But exclusively in iOS, when I press the PIN field after I filled the username field, it would immediately jump back to the username field.
Another thing to remember, I have a GestureDetector in the whole background at first, its function is for hiding the keyboard when the user taps outside the field and buttons. So I tried separating the GestureDetector to only above and below the Form because I thought overlapping the GestureDetector was the cause. Apparently, it doesn't fix anything.
body: SingleChildScrollView(
child: Form(
key: _formKey,
child: Padding(
padding: EdgeInsets.all(15),
child: AutofillGroup(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
GestureDetector(
onTap: () => unfocus(context),
child: Container(
color: Theme.of(context).scaffoldBackgroundColor,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Login',
style: Theme.of(context).textTheme.subtitle1.copyWith(
fontSize: 20,
),
),
SizedBox(height: 10),
Text(
args.fromPurchase ? 'Please enter your NIK and PIN to purchase' : 'Please enter your NIK and PIN',
style: Theme.of(context).textTheme.bodyText2.copyWith(
fontSize: 15,
),
),
SizedBox(height: _showNotice ? 30 : 15),
Container(
height: _showNotice ? null : 0,
padding: EdgeInsets.all(5),
decoration: BoxDecoration(
color: _noticeError ? aLightRed : aLightGreen,
borderRadius: BorderRadius.circular(15)
),
child: Row(
children: [
IconButton(
splashRadius: 5,
padding: EdgeInsets.all(0),
icon: Icon(
Icons.cancel,
size: _showNotice ? 20 : 0,
color: _noticeError ? aRed : aGreen,
),
onPressed: () => _onClose(),
),
Expanded(
child: Text(
_noticeError ? _errorText.capitalizeFirstofEach : 'We have sent a new PIN to your email.',
maxLines: 2,
style: Theme.of(context).textTheme.bodyText1.copyWith(
fontSize: 15,
color: _noticeError ? aRed : aGreen,
),
),
),
],
),
),
SizedBox(height: _showNotice ? 20 : 15),
Text(
'NIK',
style: Theme.of(context).textTheme.bodyText1.copyWith(
fontSize: 15,
),
),
],
),
),
),
SizedBox(height: 10),
TextFormField(
keyboardType: TextInputType.number,
controller: _userNikController,
maxLength: 16,
autofillHints: [AutofillHints.username],
onChanged: (_) => setState((){}),
inputFormatters: [
FilteringTextInputFormatter.allow(RegExp("[0-9]")),
],
style: Theme.of(context).textTheme.bodyText1,
decoration: InputDecoration(
counterText: '',
contentPadding: EdgeInsets.all(15),
fillColor: Colors.grey[50],
filled: true,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: BorderSide(color: aBorderColor.withAlpha(75)),
),
hintText: 'Please enter your NIK',
hintStyle: Theme.of(context).textTheme.bodyText2.copyWith(
fontSize: 15,
color: aLightTextColor.withAlpha(175),
),
),
),
SizedBox(height: 20),
Text(
'PIN',
style: Theme.of(context).textTheme.bodyText1.copyWith(
fontSize: 15,
),
),
SizedBox(height: 10),
TextFormField(
keyboardType: TextInputType.number,
controller: _userPinController,
obscureText: !_pinVisible,
obscuringCharacter: '*',
maxLength: 6,
autofillHints: [AutofillHints.password],
onChanged: (_) => setState((){}),
inputFormatters: [
FilteringTextInputFormatter.allow(RegExp("[0-9]")),
],
style: Theme.of(context).textTheme.bodyText1,
decoration: InputDecoration(
counterText: '',
contentPadding: EdgeInsets.all(15),
fillColor: Colors.grey[50],
filled: true,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: BorderSide(color: aBorderColor.withAlpha(75)),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: BorderSide(color: aBorderColor.withAlpha(75)),
),
hintText: 'Please enter your PIN',
hintStyle: Theme.of(context).textTheme.bodyText2.copyWith(
fontSize: 15,
color: aLightTextColor.withAlpha(175),
),
suffixIcon: IconButton(
splashRadius: 5,
icon: Icon(
_pinVisible ? Icons.visibility : Icons.visibility_off,
color: _pinVisible ? aDarkTextColor : aBorderColor,
),
onPressed: () => setState(() => _pinVisible = !_pinVisible),
),
),
),
SizedBox(height: 20),
Parent(
gesture: Gestures()
..onTap(() => _onLogin(args.fromPurchase)),
style: ParentStyle()
..opacity((_userNikController.text != '' && _userPinController.text != '') ? 1 : 0.6)
..width(double.infinity)
..height(45)
..borderRadius(all: 10)
..padding(horizontal: 15)
..animate(400, Curves.easeOut)
..background.color(Theme.of(context).primaryColor),
child: Center(
child: Center(
child: Text(
args.fromPurchase ? 'Purchase Order' : 'Login',
style: Theme.of(context).textTheme.button.copyWith(
fontWeight: FontWeight.w500,
fontSize: 15,
),
),
),
),
),
GestureDetector(
onTap: () => unfocus(context),
child: Container(
width: double.infinity,
height: 200,
color: Theme.of(context).scaffoldBackgroundColor,
),
),
],
),
),
),
),
),
Thank you in advance.

bottom overflowed by 42 pixels in a SingleChildScrollView

I have used a form inside a SingleChildScrollView, and everything works fine:
Form :
Everything works fine,
I have used this code
#override
Widget build(BuildContext context) {
double stackHeight = MediaQuery.of(context).size.height/4;
double width = MediaQuery.of(context).size.width;
return Scaffold(
body: SingleChildScrollView(
child :SafeArea(
child: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [const Color(0xFF3023AE), const Color(0xFFC86DD7)])),
child: Column(
children: <Widget>[
Container(
height: stackHeight*2.6,
child: IntroViewsFlutter(
pages,
onTapDoneButton: (){
Navigator.pop(context);
},
showSkipButton: false,
pageButtonsColor: btnColors,
),
),
Container(
height: stackHeight*1.4,
child: bottomHomePage(),
color: pageColor,
width: width,
),
],
),
)
),
)
);
but when errors appear, this is what happens :
I have tried many things, I have heard about layoutBuilder, but dont know if it will work for me or there are another solutions that can adapt to runtime events.
UPDATE :
the problem was coming only of using an expanded inside a column : here we are the code again :
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
body: SingleChildScrollView(
child: Center (
child: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [const Color(0xFF3023AE), const Color(0xFFC86DD7)])),
child: Form(
key: _formKey,
child: Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.only(top: 70.0, bottom: 20.0),
child: Text(
"C'est parti !",
style: TextStyle(fontSize: 32, color: Colors.white),
),
),
Padding(
padding: const EdgeInsets.only(bottom: 8.0),
child: Container(
width: width_textFormField + 15.0,
child: Text(
" Avant de commencer, sache que pour utiliser pleinement ta BanKids tu devras demander à tes parents de s'inscrire pour te débloquer toutes les fonctionnalités",
style: TextStyle(
fontSize: 14,
color: Colors.white,
),
textAlign: TextAlign.center,
)),
),
Container(
alignment: Alignment.center,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Container(
child: Text(
"Client Bank ?",
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.white),
),
),
Container(
child: Row(
children: <Widget>[
Text(
"Oui",
style: TextStyle(color: Colors.white),
),
Radio(
value: 1,
activeColor: Colors.white,
groupValue: _grpVal,
onChanged: _handleRadioValueChange1,
),
],
)),
Container(
child: Row(
children: <Widget>[
Text(
"Non",
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.white),
),
Radio(
activeColor: Colors.white,
value: 2,
groupValue: _grpVal,
onChanged: _handleRadioValueChange1,
),
],
)),
],
)),
Container(
child: Column(
children: <Widget>[
customizedTextFormField(
hintText: "Nom",
width: width_textFormField + 10.0,
txtColor: Colors.black),
customizedTextFormField(
hintText: "Prénom",
width: width_textFormField + 10.0,
txtColor: Colors.black),
customizedTextFormField(
hintText: "Date de Naissance",
width: width_textFormField + 10.0,
txtColor: Colors.black),
customizedTextFormField(
hintText: "CIN",
width: width_textFormField + 10.0,
txtColor: Colors.black),
customizedTextFormField(
hintText: "Email",
width: width_textFormField + 10.0,
txtColor: Colors.black)
],
),
),
Padding(
padding: const EdgeInsets.only(top: 8.0),
child: Container(
width: width_textFormField,
child: Row(
children: <Widget>[
Checkbox(
checkColor: Color(0xFF3023AE),
value: isCheck,
activeColor: Colors.white,
onChanged: _handleCheckBox,
),
Expanded(
child: Text(
"En continuant l'inscription, je déclare accepter ces conditions d'utilisations ",
style: TextStyle(color: Colors.white),
),
),
],
),
),
),
//************ next work
Container(
width: 200,
height: 60,
margin: EdgeInsets.only(right: 8.0,bottom: 8.0),
alignment: Alignment.center,
child: new Row(
children: <Widget>[
Button_with_icon(
backgroundColor: Color(0xFF7CB342),
textColor: Colors.white,
textButton: "Continuer",
onPressed: (){
if(_formKey.currentState.validate()){
print("say l3adab");
}
},
icon: Icon(Icons.arrow_forward_ios),
),
],
)
),
],
),
)),
),
)
),
);
The problem was only of using an expanded inside my form, so I have removed and removed the height and width that I have given to my container :
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
body: SingleChildScrollView(
child: Center (
child: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [const Color(0xFF3023AE), const Color(0xFFC86DD7)])),
child: Form(
key: _formKey,
child: Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.only(top: 70.0, bottom: 20.0),
child: Text(
"C'est parti !",
style: TextStyle(fontSize: 32, color: Colors.white),
),
),
Padding(
padding: const EdgeInsets.only(bottom: 8.0),
child: Container(
width: width_textFormField + 15.0,
child: Text(
" Avant de commencer, sache que pour utiliser pleinement ta BanKids tu devras demander à tes parents de s'inscrire pour te débloquer toutes les fonctionnalités",
style: TextStyle(
fontSize: 14,
color: Colors.white,
),
textAlign: TextAlign.center,
)),
),
Container(
alignment: Alignment.center,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Container(
child: Text(
"Client Bank ?",
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.white),
),
),
Container(
child: Row(
children: <Widget>[
Text(
"Oui",
style: TextStyle(color: Colors.white),
),
Radio(
value: 1,
activeColor: Colors.white,
groupValue: _grpVal,
onChanged: _handleRadioValueChange1,
),
],
)),
Container(
child: Row(
children: <Widget>[
Text(
"Non",
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.white),
),
Radio(
activeColor: Colors.white,
value: 2,
groupValue: _grpVal,
onChanged: _handleRadioValueChange1,
),
],
)),
],
)),
Container(
child: Column(
children: <Widget>[
customizedTextFormField(
hintText: "Nom",
width: width_textFormField + 10.0,
txtColor: Colors.black),
customizedTextFormField(
hintText: "Prénom",
width: width_textFormField + 10.0,
txtColor: Colors.black),
customizedTextFormField(
hintText: "Date de Naissance",
width: width_textFormField + 10.0,
txtColor: Colors.black),
customizedTextFormField(
hintText: "CIN",
width: width_textFormField + 10.0,
txtColor: Colors.black),
customizedTextFormField(
hintText: "Email",
width: width_textFormField + 10.0,
txtColor: Colors.black)
],
),
),
Padding(
padding: const EdgeInsets.only(top: 8.0),
child: Container(
width: width_textFormField,
child: Row(
children: <Widget>[
Checkbox(
checkColor: Color(0xFF3023AE),
value: isCheck,
activeColor: Colors.white,
onChanged: _handleCheckBox,
),
Expanded(
child: Text(
"En continuant l'inscription, je déclare accepter ces conditions d'utilisations ",
style: TextStyle(color: Colors.white),
),
),
],
),
),
),
//************ next work
Container(
width: 200,
height: 60,
margin: EdgeInsets.only(right: 8.0,bottom: 8.0),
alignment: Alignment.center,
child: new Row(
children: <Widget>[
Button_with_icon(
backgroundColor: Color(0xFF7CB342),
textColor: Colors.white,
textButton: "Continuer",
onPressed: (){
if(_formKey.currentState.validate()){
print("say l3adab");
}
},
icon: Icon(Icons.arrow_forward_ios),
),
],
)
),
],
),
)),
),
)
),
);
put a column child on singlechildscrollview then create a row for each form element, and put those in expanded widget
SingleChildScrollView(
physics: BouncingScrollPhysics(),
child: Material(
elevation: 0,
child: Container(
padding: EdgeInsets.all(16),
child: Column(
children: <Widget>[
Column(
children: <Widget>[
Form(
onChanged: () {
_tcFormKey.currentState.validate();
if (_tcController.text.length != 11) {
setState(() {
tcValidated = false;
});
}
},
key: _tcFormKey,
child: TextFormField(
controller: _tcController,
maxLength: 11,
inputFormatters: <TextInputFormatter>[
WhitelistingTextInputFormatter.digitsOnly,
],
validator: (String value) {
if (value.isEmpty) {
return 'Zorunlu alan';
}
if (value.length != 11) {
return 'Kimlik numarası 11 haneli olmalıdır';
}
if (value.length == 11 && !Functions.validateTC(value.toString())) {
return 'Hatalı TC. Kimlik No';
} else {
setState(() {
tcValidated = true;
});
}
},
keyboardType: TextInputType.numberWithOptions(),
decoration: InputDecoration(
counterText: '',
suffixIcon: tcValidated
? Icon(
Icons.check,
color: Colors.green,
)
: Text(''),
labelText: 'TC Kimlik No',
border: OutlineInputBorder(
borderSide: BorderSide(color: Colors.blue, width: 1),
),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.black26, width: 1),
),
),
),
),
SizedBox(
height: 12,
),
Form(
onChanged: () {
_uavtFormKey.currentState.validate();
},
key: _uavtFormKey,
child: TextFormField(
controller: _uavtController,
maxLength: 11,
inputFormatters: <TextInputFormatter>[WhitelistingTextInputFormatter.digitsOnly],
validator: (String value) {
if (value.isEmpty) {
return 'Zorunlu alan';
}
},
keyboardType: TextInputType.numberWithOptions(),
decoration: InputDecoration(
labelText: 'UAVT Adres Kodu',
suffixIcon: Icon(Icons.location_on),
counterText: '',
border: OutlineInputBorder(
borderSide: BorderSide(color: Colors.blue, width: 1),
),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.black26, width: 1),
),
),
),
),
SizedBox(
height: 12,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Expanded(
child: Form(
onChanged: () {
_adFormKey.currentState.validate();
},
key: _adFormKey,
child: TextFormField(
controller: _adController,
maxLength: 64,
validator: (String value) {
if (value.isEmpty) {
return 'Zorunlu alan';
}
},
inputFormatters: [
WhitelistingTextInputFormatter(
RegExp("[a-zA-ZĞğÜüÖöŞşçÇİı]"),
),
],
decoration: InputDecoration(
labelText: 'Ad',
counterText: '',
border: OutlineInputBorder(
borderSide: BorderSide(
color: Colors.blue,
width: 1,
),
),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Colors.black26,
width: 1,
),
),
),
),
),
),
SizedBox(
width: 8,
),
Expanded(
child: Form(
onChanged: () {
_soyadFormKey.currentState.validate();
},
key: _soyadFormKey,
child: TextFormField(
controller: _soyadController,
maxLength: 64,
validator: (String value) {
if (value.isEmpty) {
return 'Zorunlu alan';
}
},
inputFormatters: [
WhitelistingTextInputFormatter(
RegExp("[a-zA-ZĞğÜüÖöŞşçÇİı]"),
),
],
decoration: InputDecoration(
labelText: 'Soyad',
counterText: '',
border: OutlineInputBorder(
borderSide: BorderSide(
color: Colors.blue,
width: 1,
),
),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Colors.black26,
width: 1,
),
),
),
),
),
),
],
),
SizedBox(
height: 12,
),
Form(
onChanged: () {
_telFormKey.currentState.validate();
},
key: _telFormKey,
child: TextFormField(
controller: _telController,
maxLength: 10,
validator: (String val) {
if (val.isEmpty) {
return 'Zorunlu alan';
}
},
inputFormatters: <TextInputFormatter>[
WhitelistingTextInputFormatter.digitsOnly,
],
keyboardType: TextInputType.numberWithOptions(),
decoration: InputDecoration(
errorStyle: TextStyle(color: Colors.red),
hintText: '10 Haneli Telefon Numarası',
labelText: 'Telefon Numarası',
hintStyle: TextStyle(color: Colors.black38),
suffixIcon: Icon(Icons.phone_iphone),
counterText: '',
border: OutlineInputBorder(
borderSide: BorderSide(
color: Colors.blue,
width: 1,
),
),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Colors.black26,
width: 1,
),
),
),
),
),
SizedBox(
height: 12,
),
OutlineButton(
highlightColor: Colors.transparent,
splashColor: Colors.blue.shade50,
shape: BeveledRectangleBorder(borderRadius: BorderRadius.circular(2)),
borderSide: BorderSide(color: !emptyDateError ? Colors.black26 : Colors.red),
onPressed: () {
selectedBDate = '';
DatePicker.showDatePicker(context,
showTitleActions: true,
minTime: DateTime(1910, 1, 1),
maxTime: DateTime.now(),
onChanged: (date) {}, onConfirm: (date) {
int y = int.parse(DateFormat.y().format(date));
int m = int.parse(DateFormat.M().format(date));
int d = int.parse(DateFormat.d().format(date));
setState(() {
selectedBDate = '$y-$m-$d';
emptyDateError = false;
});
print('confirm $date');
}, currentTime: DateTime.now(), locale: LocaleType.tr);
},
child: Padding(
padding: const EdgeInsets.only(left: 2, right: 2, top: 16, bottom: 16),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Expanded(
child: Row(
children: <Widget>[
Icon(Icons.calendar_today, size: 16,),
Padding(
padding: const EdgeInsets.only(top: 2),
child: Text(
' Doğum Tarihi',
style: TextStyle(fontSize: 15),
),
),
],
),
),
selectedBDate != ''
? Expanded(
child: Align(
alignment: Alignment.centerRight,
child: Text('$selectedBDate'),
),
)
: emptyDateError
? Expanded(
child: Align(
alignment: Alignment.centerRight,
child: Text(
'Zorunlu Alan',
style: TextStyle(color: Colors.red),
),
),
)
: Container(),
],
),
),
),
SizedBox(
height: 12,
),
Form(
onChanged: () {
_mailFormKey.currentState.validate();
},
key: _mailFormKey,
child: TextFormField(
controller: _mailController,
validator: (String val) {
if (val.isEmpty) {
return 'Zorunlu alan';
}
if(!Functions.isEmail(val)){
return 'Geçerli bir mail adresi belirtiniz';
}
},
decoration: InputDecoration(
suffixIcon: Icon(Icons.mail_outline),
labelText: 'Mail Adresi',
border: OutlineInputBorder(
borderSide: BorderSide(color: Colors.blue, width: 1),
),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.black26, width: 1),
),
),
),
),
SizedBox(
height: 12,
),
Material(
elevation: 8,
shadowColor: Colors.green,
borderRadius: BorderRadius.circular(4),
color: Colors.green,
child: InkWell(
onTap: () {
if (_tcController.text != '' &&
_uavtController.text != '' &&
_adController.text != '' &&
_soyadController.text != '' &&
_telController.text != '' &&
_mailController.text != '' &&
selectedBDate != '' &&
Functions.validateTC(_tcController.text)) {
_tcFormKey.currentState.validate();
_uavtFormKey.currentState.validate();
_adFormKey.currentState.validate();
_soyadFormKey.currentState.validate();
_telFormKey.currentState.validate();
_mailFormKey.currentState.validate();
print(_telController.text.length);
var oprt = _telController.text.trim().split(' ')[0];
oprt = oprt.replaceAll('(', '');
oprt = oprt.replaceAll(')', '');
print(oprt);
_pageController.nextPage(duration: Duration(milliseconds: 300), curve: Curves.ease);
} else {
if (selectedBDate == '') {
setState(() {
emptyDateError = true;
});
}
_tcFormKey.currentState.validate();
_uavtFormKey.currentState.validate();
_adFormKey.currentState.validate();
_soyadFormKey.currentState.validate();
_telFormKey.currentState.validate();
_mailFormKey.currentState.validate();
}
},
child: Container(
width: double.infinity,
height: 48,
child: Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'İlerle ',
textAlign: TextAlign.center,
style: TextStyle(color: Colors.white, fontSize: 18),
),
Icon(
Icons.arrow_forward,
color: Colors.white,
),
],
),
),
),
),
),
],
),
],
),
),
),
),

How to position elements inside a ListView?

Good morning. I made this screen and it works like a charm on high resolutions. Problem is, I want to support lower resolutions like Nexus 4 (768x1280).
So when I run this on an emulator (Nexus 4 size) and I touch the input fields, the keyboard either: blocks the inputs, or moves the two buttons at the bottom and overlaps them on something else.
So, to solve it I wrapped the entire layout on a ListView(), but now the bottom buttons, which are wrapped on a Row(), just won't stay at the bottom.
This is my code without the ListView and working on high res, but not on low:
return Form(
Stack(
Center(
Column(
...
),
),
Align(
alignment: Alignment.bottomCenter,
child: Row(
...
),
),
),
);
This is how it looks with resizeToAvoidBottomPadding: false
And this is how it looks with the value set to true
Thanks, everyone.
Did you try to use SingleChildScrollView ?
It is a widget for making the page able to resize the height and as well scrolling , for the listview thats not what is the listview for , you should add listview when you get an unknown amount of data,
We don't normally use it to just adjust the view.
ok so i edited the code as in here and i can scroll normally after the keyboard pop up and the view is good and i can click on the button normally try it.
Widget formWidget(){
return new Scaffold(
// appBar: AppBar(
// // Here we take the value from the MyHomePage object that was created by
// // the App.build method, and use it to set our appbar title.
// title: Text(widget.title),
// ),
body:Column(
children: <Widget> [
Expanded(
child:SingleChildScrollView(
child: Form(
child:
// Stack(
// children: <Widget>[
// Center(
// child: SingleChildScrollView(
// child:
Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
children: [
Padding(
padding: (MediaQuery.of(context).size.height) > 600
? const EdgeInsets.only(top: 0.0)
: const EdgeInsets.only(top: 30.0),
child: Image(
image: AssetImage('assets/favIcon.png'),
width: 88.0,
height: 88.0,
),
),
Padding(
padding: const EdgeInsets.fromLTRB(0, 28.0, 0, 12.0),
child: Text(
'Delegados',
style: TextStyle(
fontFamily: 'Archia',
fontSize: 32.0,
),
),
),
Text(
'Introduce tus datos de acceso aquí.',
style: TextStyle(
color: Color(0xff83868F),
fontFamily: 'Brutal',
fontSize: 14.0,
),
),
Padding(
padding:
const EdgeInsets.fromLTRB(16.0, 26.0, 16.0, 12.0),
child: TextFormField(
decoration: InputDecoration(
labelText: 'Correo',
filled: true,
fillColor: Color(0xffF0F1F5),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8.0),
borderSide: BorderSide(
width: 0,
style: BorderStyle.none,
),
),
),
style: TextStyle(
fontFamily: 'Brutal',
color: Color(0xff1A1B1F),
),
controller: TextEditingController() ,
textInputAction: TextInputAction.next,
),
),
Padding(
padding: const EdgeInsets.fromLTRB(16.0, 0, 16.0, 12.0),
child: TextFormField(
keyboardType: TextInputType.emailAddress,
decoration: InputDecoration(
labelText: 'Contraseña',
filled: true,
fillColor: Color(0xffF0F1F5),
suffixIcon: Icon(Icons.remove_red_eye),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8.0),
borderSide: BorderSide(
width: 0,
style: BorderStyle.none,
),
),
),
style: TextStyle(
fontFamily: 'Brutal',
color: Color(0xff1A1B1F),
),
controller: TextEditingController() ,
//focusNode:FocusNode(),
obscureText: true,
),
),
Align(
alignment: Alignment.centerRight,
child: Padding(
padding: const EdgeInsets.fromLTRB(0, 0, 0, 26.0),
child: CupertinoButton(
onPressed: () {},
child: Text(
'Olvidé mi Contraseña',
style: TextStyle(
color: Color(0xff565A66),
fontFamily: 'Brutal',
fontSize: 14.0,
),
),
),
),
),
Padding(
padding: const EdgeInsets.fromLTRB(16.0, 0, 16.0, 0),
child: ButtonTheme(
minWidth: double.infinity,
child: InkWell(
// onTap: state is! LoginLoading
// ? _onLoginButtonPressed
// : null,
child: Container(
height: 48.0,
width: 500.0,
decoration: BoxDecoration(
color: Color(0xff00CC36),
borderRadius: BorderRadius.circular(8.0),
),
child: Align(
alignment: Alignment.center,
child: Container(
child:
// state is LoginLoading
// ? CircularProgressIndicator():
Text(
'INGRESAR AHORA ›',
style: TextStyle(
color: Colors.white,
fontFamily: 'Brutal',
fontSize: 14.0,
),
),
)),
),
),
),
),
],
),
// ),
)
,
// aqui va <<<<<<<<<<<<
// ],
// ),
)
),
Align(
alignment: Alignment.bottomCenter,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
CupertinoButton(
onPressed: () {},
child: Text(
'¿No tienes cuenta?',
style: TextStyle(
color: Color(0xff83868F),
fontFamily: 'Brutal',
fontSize: 14.0,
),
),
),
InkWell(
onTap: null,
child: Container(
height: 32.0,
width: 112.0,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(6.0),
border: Border.all(
color: Color(0xffD7D9E0),
width: 1.0,
),
),
child: Align(
alignment: Alignment.center,
child: Text(
'CONTACTANOS',
style: TextStyle(
color: Color(0xff565A66),
fontFamily: 'Brutal',
fontSize: 11.0),
),
),
),
),
],
),
),
]
)
,
// )
);
}
In your Scaffold can you try this.
Scaffold(
resizeToAvoidBottomInset: false,
...
);
I position two elements in the center and bottom of the screen by this code.
body: Column(
children: [
Expanded(
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
SizedBox(
height: 80,
width: 80,
child:
Image(image: AssetImage("assets/images/logo.png"))),
SizedBox(height: 10),
Text(
"Tings App",
style: TextStyle(fontSize: 36),
),
SizedBox(height: 10),
TextFormField(
controller: _emailController,
decoration: InputDecoration(
border: OutlineInputBorder(),
isDense: true,
labelText: 'Email/phone'),
validator: (value) {
if (value.isEmpty) {
return 'Please enter a valid email';
}
return null;
},
),
],
),
),
),
Align(
alignment: Alignment.bottomCenter,
child: Container(
padding: EdgeInsets.all(20),
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
_isLoading
? CircularProgressIndicator()
: SizedBox(
width: MediaQuery.of(context).size.width * 0.7,
height: 60.0,
child: ElevatedButton(
style: ButtonStyle(
shape: MaterialStateProperty.all<
RoundedRectangleBorder>(
RoundedRectangleBorder(
borderRadius: BorderRadius.circular(100.0),
),
),
),
child: Text(
"SignIn",
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.w800,
fontSize: 18),
),
onPressed: () {
_login(context);
},
),
),
SizedBox(height: 16),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
"Don't have account?",
style: TextStyle(fontSize: 16),
),
SizedBox(width: 6),
TextButton(
onPressed: () {
Navigator.push(
context, SlideRightRoute(page: Signup()));
},
child: Text("SignUp"),
),
],
)
],
),
),
)
],
),

padding between divider and row is big

i have an edit text and icon .. and i want a line under them .. so i added a divider after them like this:
new Column(
children: <Widget>[
new Row(
children: <Widget>[
new Image.asset(
'assets/sa-logo.png',
width: 20.0,
height: 13.0,
),
Padding(
padding: EdgeInsets.only(left: 5.0, right: 5.0),
child: new Text(
'+966',
style: TextStyle(
fontSize: 15.0, color: Colors.grey),
),
),
new Flexible(
child: new TextField(
style: new TextStyle(
fontSize: 20.0,
color: Colors.black,
),
decoration: new InputDecoration(
border: InputBorder.none,
hintText: '5xxxxxxxx',
hintStyle: new TextStyle(
fontSize: 20.0,
),
),
keyboardType: TextInputType.number,
onChanged: (String value) {
this._data.phone = value;
setState(() {
phonelength = value.length;
done();
});
}),
),
],
),
Divider()
],
),
but the space between the line and the other widgets is big as shown:
how to make it smaller?
I just added this to the TextField:
contentPadding: EdgeInsets.symmetric(vertical: 0),
and that solved the problem.

Resources