Reputation:
I want to achieve a layout where only the main button widget will always remain at the bottom of the scaffold. Other widgets will be placed in a SingleChildScrollView
-> Column
.
But when the TextField
or TextFormField
is focused, the keyboard should push the full screen till the bottom of the layout, so that the button is visible.
Using SingleChildScrollView only keeps the TextField
or TextFormField
above the keyboard, not the button too.
My code:
body: SingleChildScrollView(
physics: BouncingScrollPhysics(),
child: Container(
height: screenHeight(context) - kToolbarHeight - 24,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
PlaceHolder(),
SizedBox(height: 20.0),
Text('Select Time'),
SizedBox(height: 10.0),
PlaceHolder(),
SizedBox(height: 20.0),
PlaceHolder(),
SizedBox(height: 20.0),
// InputField is a TextFormField
InputField(
controller: _dataController,
labelText: 'Enter Data',
fieldFocusNode: _dataFocusNode,
textInputType: TextInputType.text,
),
SizedBox(height: 20.0),
CheckboxListTile(),
SizedBox(height: 20.0),
PrimaryButton(
buttonText: 'Save',
onPressed: () {},
),
SizedBox(height: 20.0),
],
),
),
),
Here's two screen layout. You can ignore all the other widgets except TextFormField
and the Main Button
.
Screen One : Without keyboard (TextField
or TextFormField
is not focused)
Screen Two : With keyboard (TextField
or TextFormField
is focused)
Upvotes: 8
Views: 12668
Reputation: 7119
Follow this steps:
1. Remove the Container
with fixed height.
2. Add a Padding
widget to the bottom of the page and set its bottom
padding to MediaQuery.of(context).viewInsets.bottom
.
3. Add reverse: true
to the SingleChildScrollView
.
4. Add resizeToAvoidBottomInset: false
to the Scaffold
.
5. Add resizeToAvoidBottomPadding: false
to the Scaffold
.
Full code: (changes are marked with comments)
return Scaffold(
resizeToAvoidBottomInset: false, // this is new
resizeToAvoidBottomPadding: false, // this is new
body: SingleChildScrollView(
reverse: true, // this is new
physics: BouncingScrollPhysics(),
child: Column( // the container is removed
mainAxisAlignment: MainAxisAlignment.spaceBetween,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
PlaceHolder(),
SizedBox(height: 20.0),
Text('Select Time'),
SizedBox(height: 10.0),
PlaceHolder(),
SizedBox(height: 20.0),
PlaceHolder(),
SizedBox(height: 20.0),
// InputField is a TextFormField
InputField(
controller: _dataController,
labelText: 'Enter Data',
fieldFocusNode: _dataFocusNode,
textInputType: TextInputType.text,
),
SizedBox(height: 20.0),
CheckboxListTile(),
SizedBox(height: 20.0),
PrimaryButton(
buttonText: 'Save',
onPressed: null, // changed this since it had a syntax error
),
Padding( // this is new
padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom)
),
],
),
),
);
Upvotes: 19