How to align a Text to the bottom - flutter

I'm trying to build a very simple login page, and i want that the "sign up" text to be at the bottom of the screen.
I'm trying to align the text in the last column to the bottom of the screen, but somehow the aligment doesn't work.
When i try to use the Expanded widget, the IDE throw me an paint error.
class EmailLogin extends StatefulWidget {
#override
_EmailLoginState createState() => _EmailLoginState();
}
class _EmailLoginState extends State<EmailLogin> {
final Map<String, dynamic> _formData = {'email': null, 'password': null};
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
Widget _emailTextField() {
return TextFormField(
decoration: InputDecoration(
labelText: 'Email',
),
keyboardType: TextInputType.emailAddress,
},
onSaved: (String value) {
_formData['email'] = value;
},
);
}
Widget _passwordTextField() {
return TextFormField(
obscureText: true,
validator: (String value) {
if (value.isEmpty || value.length < 6) {
return "please enter valid password";
}
},
onSaved: (String value) {
_formData['password'] = value;
},
decoration: InputDecoration(
labelText: 'Password',
),
);
}
Widget _passwordConfirmTextField() {
return TextFormField(
obscureText: true,
validator: (String value) {
if (value.isEmpty || value.length < 6) {
return "please enter valid password";
}
},
onSaved: (String value) {
_formData['password'] = value;
},
decoration: InputDecoration(
labelText: 'Password',
),
);
}
void _submitForm() {
if (!_formKey.currentState.validate()) {
return;
}
_formKey.currentState.save();
print(_formData);
Navigator.of(context).pushNamed('/home');
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
fit: StackFit.expand,
children: <Widget>[
Image(
image: AssetImage("assets2/car.jpg"),
fit: BoxFit.cover,
color: Colors.black87,
colorBlendMode: BlendMode.darken,
),
SingleChildScrollView(
child: Form(
key: _formKey,
child: Container(
width: double.infinity,
child: Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.only(top: 80.0),
child: Logo(),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Padding(
padding: EdgeInsets.only(top: 8.0, bottom: 80.0),
child: Text(
"Airbnb",
style: TextStyle(fontSize: 30.0),
),
),
],
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 20.0),
child: _emailTextField()),
SizedBox(
height: 15.0,
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 20.0),
child: _passwordTextField()),
Row(
children: <Widget>[
Expanded(
child: Padding(
padding: const EdgeInsets.only(
left: 20.0, right: 5.0, top: 10.0),
child: GestureDetector(
onTap: () {
_submitForm();
},
child: Container(
alignment: Alignment.center,
height: 60.0,
decoration: BoxDecoration(
color: Color(0xFF18D191),
borderRadius: BorderRadius.circular(10.0)),
child: Text(
'login',
style: TextStyle(
fontSize: 20.0, color: Colors.white),
),
),
),
),
),
Expanded(
child: Padding(
padding: const EdgeInsets.only(
left: 10.0, right: 20.0, top: 10.0),
child: Container(
alignment: Alignment.center,
height: 70.0,
child: Text(
'Forgot Password?',
style: TextStyle(
fontSize: 15.0, color: Color(0xFF18D191)),
),
),
),
),
],
),
Column(
children: <Widget>[
Container(
child: Text("switch to sign up"),
alignment: Alignment.bottomCenter,
),

Related

Keyboard overflowed by * pixels. Unable to use SingleChildScrollView or ListView

On pressing on any of the TextFormField the pixels overflow and I tried using SingleChildScrollView and ListView but the content inside the container disappears. It is the registration page I am trying to make. Maybe its because I am using an expanded widget or something else in the code which is not allowing to use SingleChildScrollView or ListView.
import 'dart:io';
import 'package:cloud_firestore/cloud_firestore.dart' show FirebaseFirestore;
import 'package:comperio/constants.dart';
import 'package:comperio/screen/contacted_person_screen.dart';
import 'package:comperio/screen_app_logo.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:image_picker/image_picker.dart';
import 'package:modal_progress_hud/modal_progress_hud.dart';
class RegistrationScreen extends StatefulWidget {
final String id = 'RegistrationScreen';
#override
_RegistrationScreenState createState() => _RegistrationScreenState();
}
class _RegistrationScreenState extends State<RegistrationScreen> {
bool showSpinner = false;
final _auth = FirebaseAuth.instance;
String email;
String username;
String password;
File _image;
Future getImages() async {
PickedFile pickedFile =
await ImagePicker().getImage(source: ImageSource.gallery);
var image = File(pickedFile.path);
setState(() {
_image = image;
print('Image path $_image');
});
}
void _addToDatabase(String userName) {
List<String> splitList = username.split(" ");
List<String> indexList = [];
for (int i = 0; i < splitList.length; i++) {
for (int y = 1; y < splitList[i].length + 1; y++) {
indexList.add(splitList[i].substring(0, y).toLowerCase());
}
}
// print(indexList);
FirebaseFirestore.instance.collection('users').doc().set({
'username': userName,
'searchKeywords': indexList,
});
}
#override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('images/app-background.jpg'),
fit: BoxFit.cover,
),
),
constraints: BoxConstraints.expand(),
child: Scaffold(
resizeToAvoidBottomInset: true,
resizeToAvoidBottomPadding: false,
backgroundColor: Colors.transparent,
body: ModalProgressHUD(
inAsyncCall: showSpinner,
child: Container(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
padding: EdgeInsets.only(
top: 60.0, left: 30.0, right: 30.0, bottom: 30.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
ScreenAppLogo(),
Text(
'Comperio',
style: KAppNameTextStyle,
),
],
),
),
Expanded(
child: Container(
width: double.infinity,
padding: EdgeInsets.symmetric(horizontal: 20.0),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(20.0),
topRight: Radius.circular(20.0),
),
),
child: Padding(
padding: const EdgeInsets.only(
left: 16.0, right: 16.0, top: 25, bottom: 16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'New',
style: KCardTextStyle,
),
SizedBox(
height: 5.0,
),
Text(
'Account',
style: KCardTextStyle,
),
],
),
Container(
child: Stack(
alignment: Alignment.center,
overflow: Overflow.visible,
children: [
Container(
width: 80.0,
height: 80.0,
child: CircleAvatar(
radius: 40.0,
backgroundColor: Colors.black12,
child: ClipOval(
child: SizedBox(
width: 80.0,
height: 80.0,
child: (_image != null)
? Image.file(
_image,
fit: BoxFit.fill,
)
: Image.asset(
'images/default-profile.jpg',
fit: BoxFit.fill,
),
),
),
),
),
Positioned(
top: -1,
right: -30,
bottom: -40,
left: 40,
child: IconButton(
icon: Icon(
Icons.camera,
color: Colors.pinkAccent,
size: 20,
),
onPressed: () {
getImages();
},
),
),
],
),
),
],
),
SizedBox(
height: 10.0,
),
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
TextFormField(
keyboardType: TextInputType.emailAddress,
decoration: const InputDecoration(
icon: Icon(Icons.email),
hintText: 'Enter your Email',
hintStyle: TextStyle(
color: Colors.grey,
),
labelText: 'Email *',
),
onChanged: (String value) {
// This optional block of code can be used to run
// code when the user saves the form.
email = value;
},
),
TextFormField(
decoration: const InputDecoration(
icon: Icon(Icons.person),
hintText: 'Enter Username',
hintStyle: TextStyle(
color: Colors.grey,
),
labelText: 'Username *',
),
onChanged: (String value) {
// This optional block of code can be used to run
// code when the user saves the form.
username = value;
},
),
TextFormField(
decoration: const InputDecoration(
icon: Icon(Icons.lock),
hintText: 'Enter the password',
hintStyle: TextStyle(
color: Colors.grey,
),
labelText: 'Password *',
),
obscureText: true,
onChanged: (String value) {
// This optional block of code can be used to run
// code when the user saves the form.
password = value;
},
),
SizedBox(
height: 15.0,
),
Padding(
padding: const EdgeInsets.symmetric(
horizontal: 30.0,
),
child: RaisedButton(
elevation: 10.0,
shape: StadiumBorder(),
color: Colors.lightBlueAccent,
onPressed: () async {
setState(() {
showSpinner = true;
});
try {
final newUser = await _auth
.createUserWithEmailAndPassword(
email: email,
password: password);
_addToDatabase(username);
if (newUser != null) {
Navigator.pushNamed(context,
ContactedPersonScreen().id);
}
setState(() {
showSpinner = false;
});
} catch (e) {
print(e);
}
},
child: Text(
'Sign up',
style: KLoginRegistrationButtonStyle,
),
padding: EdgeInsets.symmetric(
vertical: 15.0,
horizontal: 60.0,
),
),
),
],
),
),
],
),
),
),
),
],
),
),
),
),
);
}
}
Try wrapping the body like this:
body: LayoutBuilder(
builder: (BuildContext context, BoxConstraints constraint) {
return SingleChildScrollView(
child: ConstrainedBox(
constraints: BoxConstraints(minHeight: constraint.maxHeight),
child: IntrinsicHeight(
child: Container(
[...]
)
)
)
);
});

How to implement dropdown inside popup menu in flutter

I need a popup menu or any other way to implement layout like this in flutter. I have tried to implememnt it in popup view but I wasn't successful. Please help me with this problem.
Here is the code I have tried, implementing it using any other method also will be fine. This code gives error no material widget found, if it can be fixed it'll also be helpful for me.
void showFilter() {
showGeneralDialog(
barrierLabel: "Barrier",
barrierDismissible: true,
barrierColor: Colors.black.withOpacity(0.5),
transitionDuration: Duration(milliseconds: 700),
context: context,
pageBuilder: (_, __, ___) {
return Align(
alignment: Alignment.center,
child: Container(
height: 300,
child: SizedBox.expand(
child:Column(
children: <Widget>[
Container(
padding: EdgeInsets.only( top: SizeConfig.blockSizeHorizontal*2, left: SizeConfig.blockSizeHorizontal*6),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Text("Monthly Summary", style: TextStyle(fontSize: SizeConfig.blockSizeHorizontal*6, color: Colors.black87,decoration: TextDecoration.none,),),
],
)
),
Container(
padding: EdgeInsets.only(top:SizeConfig.blockSizeHorizontal*2, left: SizeConfig.blockSizeHorizontal*3, right: SizeConfig.blockSizeHorizontal*3),
child: Divider(
color: Colors.black87,thickness: 2.0,
),
),
Container(
padding: EdgeInsets.only(left: SizeConfig.blockSizeHorizontal*6, top: SizeConfig.blockSizeHorizontal*4),
child: Row(
children: <Widget>[
Container(
child: Row(
children: <Widget>[
Text("Year - ", style: TextStyle(fontSize: SizeConfig.blockSizeHorizontal*4.5, color: Colors.black87,decoration: TextDecoration.none,),)
],
),
),
Container(
child: Row(
children: <Widget>[
Container(
child: DropdownButton(
value: _dpdValue,
underline: Container(),
isExpanded: true,
iconSize: 30.0,
items: _dropdownValues.map((val) {
return new DropdownMenuItem<String>(
value: val,
child: new Text(val),
);
}).toList(),
onChanged: (val) {
if (!mounted) return;
setState(
() {
_dpdValue = val;
},
);
},
),
)
],
),
)
],
)
)
],
)
),
margin: EdgeInsets.only(top: SizeConfig.blockSizeHorizontal*15, left: SizeConfig.blockSizeHorizontal*3, right: SizeConfig.blockSizeHorizontal*3),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(SizeConfig.blockSizeHorizontal*6),
),
),
);
},
transitionBuilder: (_, anim, __, child) {
return SlideTransition(
position: Tween(begin: Offset(0, 1), end: Offset(0, 0)).animate(anim),
child: child,
);
},
);
}
I have used an Alertdialog for this,, hope it offers insight to solving your problem,
int year = 1990;
List<String> months = ['January', 'February', 'March'];
List<String> years = [];
String option, month;
#override
void initState() {
super.initState();
for (int i = year; i < 2020; i++) {
years.add(i.toString());
}
}
Future<bool> errorDialog(context) async {
Size size = MediaQuery.of(context).size;
return showDialog(
context: context,
barrierDismissible: false,
builder: (BuildContext context) {
return StatefulBuilder(builder: (context, setState) {
return AlertDialog(
backgroundColor: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(20.0))),
content: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Padding(
padding: const EdgeInsets.all(8.0),
child: Text("Monthly Summary"),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text('Year-'),
Container(
width: size.width * 0.5,
decoration: BoxDecoration(
border: Border.all(
color:Colors.amber),
borderRadius:
BorderRadius.all(Radius.circular(5))),
child: DropdownButtonFormField<String>(
decoration: InputDecoration(
contentPadding:
EdgeInsets.fromLTRB(10, 0, 10, 0),
filled: true,
fillColor: Colors.white,
hintText: 'Select Year',
hintStyle:
TextStyle(fontWeight: FontWeight.normal)),
value: option,
icon: Icon(Icons.arrow_drop_down),
iconSize: 24,
elevation: 16,
style: TextStyle(color: Colors.black),
onChanged: (String newValue) {
setState(() {
option = newValue;
});
},
validator: (value) {
if (value == null) {
return "Select Year";
}
return null;
},
items: years
.map<DropdownMenuItem<String>>((String option) {
return DropdownMenuItem<String>(
value: option,
child: Text(option),
);
}).toList(),
),
),
],
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text('Month-'),
Container(
decoration: BoxDecoration(
border: Border.all(
color:Colors.amber),
borderRadius:
BorderRadius.all(Radius.circular(5))),
width: size.width * 0.5,
child: DropdownButtonFormField<String>(
decoration: InputDecoration(
contentPadding:
EdgeInsets.fromLTRB(10, 0, 10, 0),
filled: true,
fillColor: Colors.white,
hintText: 'Select Month',
hintStyle:
TextStyle(fontWeight: FontWeight.normal)),
value: month,
icon: Icon(Icons.arrow_drop_down),
iconSize: 24,
elevation: 16,
style: TextStyle(color: Colors.black),
onChanged: (String newValue) {
setState(() {
month = newValue;
});
},
validator: (value) {
if (value == null) {
return "Select Month";
}
return null;
},
items: months
.map<DropdownMenuItem<String>>((String option) {
return DropdownMenuItem<String>(
value: option,
child: Text(option),
);
}).toList(),
),
),
],
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Padding(
padding: const EdgeInsets.all(8.0),
child: RaisedButton(
color: Colors.amber,
shape: RoundedRectangleBorder(
borderRadius:
BorderRadius.all(Radius.circular(2.0))),
child: Text(
"CANCEL",
style: TextStyle(color: Colors.black),
),
onPressed: () {
Navigator.of(context).pop();
},
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: RaisedButton(
color: Colors.amber,
shape: RoundedRectangleBorder(
borderRadius:
BorderRadius.all(Radius.circular(2.0))),
child: Text(
"SEARCH",
style: TextStyle(color: Colors.black),
),
onPressed: () {
Navigator.of(context).pop();
},
),
),
],
),
),
],
),
),
);
});
});
}

Clicking in TextFormField causes rebuild and text field subsequently loses focus

My Flutter app has been working fine right up until yesterday at which point my login screen started acting strange. As soon as I click in either the username or password text fields the keyboard shows, immediately hides, and then everything rebuilds. I've seen several threads on similar issues online, but nothing that's helped me figure out what's going wrong here. This is the gist of the code:
static final _formKey = GlobalKey<FormState>();
TextEditingController _emailController = TextEditingController();
TextEditingController _passwordController = TextEditingController();
#override
Widget build(BuildContext context) {
return Scaffold(body: SingleChildScrollView(child: _buildBody()));
}
Widget _buildBody() {
return BlocProvider(create: (context) {
_loginBloc = LoginBloc(auth);
return _loginBloc;
}, child: BlocBuilder<LoginBloc, LoginState>(builder: (context, state) {
if (state is LoginFailure) {
_onWidgetDidBuild(() {
Scaffold.of(context).showSnackBar(
SnackBar(
content: Text('${state.error}'),
backgroundColor: Colors.red,
),
);
});
_showErrorMessage(state.error);
}
return Container(
height: Styles().height(),
child: LoadingOverlay(
color: Colors.black,
opacity: 0.5,
isLoading: (state is LoginLoading),
progressIndicator: SpinKitThreeBounce(color: Colors.white),
child: Container(
padding: EdgeInsets.fromLTRB(30, 50, 30, 0),
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [AppColors.DARK_BLUE, AppColors.GREEN])),
child: Column(children: <Widget>[
Padding(
padding: EdgeInsets.fromLTRB(0, 0, 0, 50),
child: _showLogo()),
Card(
color: Colors.white,
elevation: 5,
child: Padding(
padding: EdgeInsets.all(10),
child: Form(
key: _formKey,
child: ListView(
shrinkWrap: true,
children: <Widget>[
_buildEmailInput(),
_buildPasswordInput(),
Padding(
padding: EdgeInsets.only(top: 20),
child: ButtonTheme(
height: 50,
child: FlatButton(
color: AppColors.MEDIUM_GREEN,
child: Text(
_formMode == FormMode.LOGIN
? 'Sign in with Email'
: 'Create Account',
style: TextStyle(
color: Colors.white,
fontSize: 15,
fontWeight:
FontWeight.bold)),
onPressed: _validateAndSubmit,
))),
_showSecondaryButton(),
Align(
alignment: Alignment.center,
child: GestureDetector(
onTap: _showLoginRecoveryModal,
child: Text(
'Forgot Password?',
style: TextStyle(
color: AppColors.LIGHT_BLUE,
fontSize: 15,
fontWeight: FontWeight.bold),
))),
],
),
))),
Padding(
padding: const EdgeInsets.only(top: 20.0, bottom: 20.0),
child: Align(
alignment: Alignment.center,
child: Text(
'OR',
style: TextStyle(
color: Colors.white,
fontSize: 20,
fontWeight: FontWeight.bold),
)),
),
_buildGoogleButton()
]))));
}));
}
Widget _buildEmailInput() {
return Padding(
padding: const EdgeInsets.only(top: 20),
child: TextFormField(
maxLines: 1,
controller: _emailController,
keyboardType: TextInputType.emailAddress,
autofocus: false,
decoration: InputDecoration(
hintText: 'Email',
icon: Icon(
Icons.mail,
color: Colors.grey,
)),
validator: (value) => !EmailEditingRegexValidator().isValid(value)
? 'Invalid email address'
: null,
onSaved: (value) {
if (StringUtils.isNotNullOrEmpty(value)) {
_email = value.trim();
} else {
_email = null;
}
},
),
);
}
Widget _buildPasswordInput() {
return Padding(
padding: const EdgeInsets.fromLTRB(0.0, 15.0, 0.0, 0.0),
child: TextFormField(
maxLines: 1,
controller: _passwordController,
obscureText: _hidePassword,
autofocus: false,
decoration: InputDecoration(
hintText: 'Password',
icon: Icon(
Icons.lock,
color: Colors.grey,
),
suffix: GestureDetector(
onTap: _toggleShowPassword,
child: Icon(
AntIcons.eye,
color: Colors.grey,
))),
validator: (value) => !NonEmptyStringValidator().isValid(value)
? 'Password can\'t be empty'
: null,
onSaved: (value) {
if (StringUtils.isNotNullOrEmpty(value)) {
_password = value.trim();
} else {
_password = null;
}
},
),
);
}
I'm not sure what I need to do here to ensure that, as soon as the keyboard shows, everything does not get rebuilt.

Button overlaps on textfield when keyboard is open

Here is my issue: The button should Not overlap the textfield.
Notice that I added a SingleChildScrollView(). The user can still scroll up and achieve the desired the result but I want to make it automatic:
Here is my code:
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_masked_text/flutter_masked_text.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:talking_dodo/dodo/pages/payment/credit_card.dart';
class WithdrawPage extends StatefulWidget {
#override
WithdrawPageState createState() {
return new WithdrawPageState();
}
}
class WithdrawPageState extends State<WithdrawPage> {
bool isDataAvailable = true;
int _radioValue = 0;
MaskedTextController ccMask =
MaskedTextController(mask: "0000 0000 0000 0000");
Widget _buildBody() {
return Stack(
children: <Widget>[
SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.only(
left: 16.0, right: 16.0, top: 16.0, bottom: 16.0),
child: Column(
children: <Widget>[
Row(
children: <Widget>[
Padding(
padding: const EdgeInsets.only(left: 18.0),
child: Text('Please select withdrawal method below'),
),
],
),
Container(
margin: EdgeInsets.only(top: 12.0),
child: Row(
children: <Widget>[
new Radio(
value: 0,
groupValue: _radioValue,
onChanged: ((value) {
setState(() {
_radioValue = value;
});
}),
),
Text(
'ATM Withdrawal',
),
],
),
),
Container(
height: 220.0,
padding: EdgeInsets.only(left: 20.0, right: 10.0),
margin: const EdgeInsets.all(2.0),
decoration: BoxDecoration(
// color: Colors.white,
border: Border.all(color: Colors.black),
borderRadius: BorderRadius.all(Radius.circular(12.0)),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Bullet('Visit mcb Branch'),
Bullet('Select "Dodo Wallet" in the options'),
Bullet('Select the amount to withdraw'),
Bullet('Input your dodo wallet pin'),
Bullet(
'Input the code in the input box below and click withdraw'),
Padding(
padding: const EdgeInsets.only(top:18.0),
child: TextField(
controller: ccMask,
keyboardType: TextInputType.number,
maxLength: 19,
style:
TextStyle(fontFamily: 'Raleway', color: Colors.black),
decoration: InputDecoration(
labelText: "Code",
labelStyle: TextStyle(fontWeight: FontWeight.bold),
border: OutlineInputBorder()),
),
),
],
),
),
Row(
children: <Widget>[
new Radio(
value: 1,
groupValue: _radioValue,
onChanged: ((value) {
setState(() {
_radioValue = value;
});
}),
),
Text(
'Transfer to card',
),
],
),
],
),
),
),
Align(
alignment: Alignment.bottomCenter,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Container(
child: isDataAvailable
? Expanded(
child: ButtonTheme(
height: 65.0,
child: RaisedButton(
color: Theme.of(context).primaryColorLight,
child: Text('Withdraw funds'),
onPressed: () => showSuccessDialog()),
),
)
: Padding(
padding: EdgeInsets.only(bottom: 10.0),
child: CircularProgressIndicator()),
),
],
),
),
],
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Withdrawal"),
),
body: _buildBody(),
);
}
void showSuccessDialog() {
setState(() {
isDataAvailable = false;
Future.delayed(Duration(seconds: 1)).then((_) => goToDialog());
});
}
goToDialog() {
setState(() {
isDataAvailable = true;
});
showDialog(
context: context,
barrierDismissible: true,
builder: (context) => Center(
child: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
successTicket(),
SizedBox(
height: 10.0,
),
FloatingActionButton(
backgroundColor: Colors.black,
child: Icon(
Icons.clear,
color: Colors.white,
),
onPressed: () {
Navigator.pop(context);
Navigator.of(context).pushNamed('/chat');
},
)
],
),
),
));
}
successTicket() => Container(
width: double.infinity,
padding: const EdgeInsets.all(16.0),
child: Material(
clipBehavior: Clip.antiAlias,
elevation: 2.0,
borderRadius: BorderRadius.circular(4.0),
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
ProfileTile(
title: "Thank You!",
textColor: Colors.purple,
subtitle: "Your transaction was successful",
),
ListTile(
title: Text("Date"),
subtitle: Text("26 June 2018"),
trailing: Text("11:00 AM"),
),
ListTile(
title: Text("Daniel Daniel"),
subtitle: Text("gmail#daniel.com"),
trailing: CircleAvatar(
radius: 20.0,
backgroundImage: NetworkImage(
"https://avatars0.githubusercontent.com/u/12619420?s=460&v=4"),
),
),
ListTile(
title: Text("Amount"),
subtitle: Text("\$423.00"),
trailing: Text("Completed"),
),
Card(
clipBehavior: Clip.antiAlias,
elevation: 0.0,
color: Colors.grey.shade300,
child: ListTile(
leading: Icon(
FontAwesomeIcons.ccAmex,
color: Colors.blue,
),
title: Text("Credit/Debit Card"),
subtitle: Text("Amex Card ending ***6"),
),
),
],
),
),
),
);
}
class Bullet extends Text {
const Bullet(
String data, {
Key key,
TextStyle style,
TextAlign textAlign,
TextDirection textDirection,
Locale locale,
bool softWrap,
TextOverflow overflow,
double textScaleFactor,
int maxLines,
String semanticsLabel,
}) : super(
'• $data',
key: key,
style: style,
textAlign: textAlign,
textDirection: textDirection,
locale: locale,
softWrap: softWrap,
overflow: overflow,
textScaleFactor: textScaleFactor,
maxLines: maxLines,
semanticsLabel: semanticsLabel,
);
}
What you're looking for is the scrollPadding parameter of textfield. Flutter automatically scrolls the view to the top of the keyboard when the textfield is focused, but it has no idea about the fact that you've placed a button that sits at the bottom of the screen.
With your current code, you could simply replace scrollPadding with padding that has a larger bottom (i.e. the size of the yellow button) and flutter should do the rest for you.

Flutter keyboard done button causes textfield content to vanish

I have 2 textfields in a form. When i click on done button on keyboard in the second text field , keyboard hides and both the text fields get empty. The same happes when i closes the keyboard manually, then also the content of the textfields get lost.
It looks like the screen gets refresh evertime this happens. why is it so?
#override
Widget build(BuildContext context) {
TextEditingController nameTextFieldController = TextEditingController();
TextEditingController emailTextFieldController = TextEditingController();
FocusNode emailFocusNode = new FocusNode();
// TODO: implement build
return WillPopScope(
onWillPop: () {
moveToLastScreen();
},
child: Scaffold(
appBar: AppBar(
title: Text("Signup"),
leading: IconButton(
icon: Icon(Icons.arrow_back),
onPressed: () {
moveToLastScreen();
}),
),
body: Form(
key: _formKey,
child: Container(
child: ListView(
padding: EdgeInsets.only(top: 20, left: 35, right: 35),
children: <Widget>[
Center(
child: GestureDetector(
onTap: () {
imageSelectorGalary();
},
child: new Container(
width: 100.0,
height: 100.0,
child: _image == null
? new Image.asset(
'images/profilepic.png',
fit: BoxFit.fitWidth,
)
: new CircleAvatar(
backgroundImage: new FileImage(_image),
radius: 200.0,
)))),
Text(
"NAME",
style: TextStyle(fontWeight: FontWeight.bold),
),
Padding(
padding: EdgeInsets.only(top: 5, bottom: 10),
child: TextFormField(
inputFormatters:[
LengthLimitingTextInputFormatter(10),
],
onFieldSubmitted: (String value){
FocusScope.of(context).requestFocus(emailFocusNode);
},
keyboardType: TextInputType.text,
controller: nameTextFieldController,
validator: (String value) {
if (value.isEmpty) {
return 'Please enter the name';
}
},
decoration: InputDecoration(
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(5.0)),
contentPadding: EdgeInsets.only(
top: 15, bottom: 15, left: 20, right: 20))),
),
Text(
"EMAIL ID",
style: TextStyle(fontWeight: FontWeight.bold),
),
Padding(
padding: EdgeInsets.only(top: 5, bottom: 10),
child: TextFormField(
controller: emailTextFieldController,
focusNode: emailFocusNode ,
onFieldSubmitted: (String value){
FocusScope.of(context).requestFocus(new FocusNode());
},
validator: (String value){
if(value.isEmpty){
return "Please enter your email-id";
}
},
decoration: InputDecoration(
contentPadding: EdgeInsets.only(
top: 15, bottom: 15, left: 20, right: 20),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(5.0))),
),
),
Text(
"CITY AND AREA",
style: TextStyle(fontWeight: FontWeight.bold),
),
GestureDetector(
onTap: () {
CityAreasDialog cityAreasDialog =
new CityAreasDialog();
cityAreasDialog.information(context);
},
child: Container(
margin: EdgeInsets.only(top: 5, bottom: 10),
padding: EdgeInsets.only(left: 20, right: 20),
decoration: new BoxDecoration(
border: new Border.all(color: CustomColors.grey),
borderRadius: BorderRadius.all(Radius.circular(
5.0) // <--- border radius here
)),
child: Container(
padding: EdgeInsets.only(top: 10, bottom: 10),
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: <Widget>[
Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: <Widget>[
Text("Select Your City"),
Text(
"and area",
style: TextStyle(
color: Colors.grey, fontSize: 10),
)
],
),
Icon(
Icons.arrow_drop_down,
color: Colors.black,
)
],
)),
)),
Container(
margin: EdgeInsets.only(top: 20, left: 10, right: 10),
child: RaisedButton(
onPressed: () {
debugPrint("Next Click");
onSignup();
},
child: new Text(
"NEXT",
),
))
],
),
)),
));
}
This issue is because you are creating new TextEditingController every time your widget is rebuilt.
So to fix this issue, move these variables nameTextFieldController ,emailTextFieldController outside your build method.
Like this:
TextEditingController nameTextFieldController = TextEditingController();
TextEditingController emailTextFieldController = TextEditingController();
#override
Widget build(BuildContext context) {
...