Push screen bottom on top of keyboard in flutter when TextField or TextFormField is focused

Viewed 4418

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 One : Without keyboard (TextField or TextFormField is not focused)

Screen Two : With keyboard (TextField or TextFormField is focused)

Screen Two : With keyboard (TextField or TextFormField is focused)

2 Answers

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)
            ),
          ],
        ),
      ),
    );

Wrap your screen with SingleChildScrollView

Related