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.
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,
),
],
),
),
),
),
),
],
),
],
),
),
),
),
Here's a mockup of the dialog I'm trying to create in Flutter:
Here's what I have so far:
I'm unable to position my two button's with rounded bottom corners at the bottom of the dialog so that it looks like in the mockup.
I was able to make those buttons fit within the Dialog width, without the stack, but then it would be positioned at the top.
Here's the code for the dialog:
SimpleDialog carDialog = SimpleDialog(
contentPadding: EdgeInsets.all(0),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(6)),
children: <Widget>[
Container(
height: 400,
child: Stack(
children: <Widget>[
Positioned(
bottom: 0,
child: IntrinsicWidth(
child: Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Expanded(
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(6)),
color: Colors.lightBlueAccent,
),
height: 45,
child: Center(
child: Text(
allTranslations.text('wait_enroute').toUpperCase(),
textAlign: TextAlign.center,
style: Fonts.appFont(context,
bold: true, color: Colors.white),
),
),
),
),
Expanded(
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
bottomRight: Radius.circular(6)),
color: AppColors.action_button,
),
height: 45,
child: Center(
child: Padding(
padding:
const EdgeInsets.symmetric(horizontal: 8.0),
child: Text(
allTranslations.text('new_order').toUpperCase(),
textAlign: TextAlign.center,
style: Fonts.appFont(context,
bold: true, color: Colors.white),
),
),
),
),
),
],
),
),
),
],
),
),
],
);
showDialog(context: context, builder: (context) => carDialog);
I have found a working solution. It does not require the Stack widget, everything can be nested within a Column like so:
SimpleDialog carDialog = SimpleDialog(
contentPadding: EdgeInsets.all(0),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(6)),
children: <Widget>[
Column(
children: <Widget>[
SizedBox(
height: 400,
),
Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Expanded(
child: InkWell(
child: Container(
decoration: BoxDecoration(
borderRadius:
BorderRadius.only(bottomLeft: Radius.circular(6)),
color: Colors.lightBlueAccent,
),
height: 45,
child: Center(
child: Text(
allTranslations.text('wait_enroute').toUpperCase(),
textAlign: TextAlign.center,
style: Fonts.appFont(context,
bold: true, color: Colors.white),
),
),
),
),
),
Expanded(
child: Container(
decoration: BoxDecoration(
borderRadius:
BorderRadius.only(bottomRight: Radius.circular(6)),
color: AppColors.action_button,
),
height: 45,
child: Center(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 8.0),
child: Text(
allTranslations.text('new_order').toUpperCase(),
textAlign: TextAlign.center,
style: Fonts.appFont(context,
bold: true, color: Colors.white),
),
),
),
),
),
],
),
],
),
],
);
showDialog(context: context, builder: (context) => carDialog);
The result:
You can try this replacing with Row
LayoutBuilder(
builder:(BuildContext context, BoxConstraints constraints){
return Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
SizedBox(
width : constraints.maxWidth/2
child:Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(6)),
color: Colors.lightBlueAccent,
),
height: 45,
child: Center(
child: Text(
allTranslations.text('wait_enroute').toUpperCase(),
textAlign: TextAlign.center,
style: Fonts.appFont(context,
bold: true, color: Colors.white),
),
),
),
),
SizedBox(
width : constraints.maxWidth/2
child:Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
bottomRight: Radius.circular(6)),
color: AppColors.action_button,
),
height: 45,
child: Center(
child: Padding(
padding:
const EdgeInsets.symmetric(horizontal: 8.0),
child: Text(
allTranslations.text('new_order').toUpperCase(),
textAlign: TextAlign.center,
style: Fonts.appFont(context,
bold: true, color: Colors.white),
),
),
),
),
),
],
);
}
),
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.