Boy
Boy

Reputation: 7519

Keyboard pushes the content up / resizes the screen

Edit:

I got a report that this is a duplicate of When the keyboard appears, the Flutter widgets resize. How to prevent this?. While this is related, it is a different issue. I want the keyboard to overlap the UI until it reaches the TextField that has focus. This is default behavior on Android

Original:

I am an Android developer and just started with Flutter. I wanted to create a log in screen. I wanted an image above the TextField's. So I thought, I use a Stack to have the image on the background and some TextField's below.

The issue is that as soon as the keyboard appears, it pushes all content up. On Android, usually the keyboard only pushes up if necessary and only until it reaches the EditText.

I tried setting resizeToAvoidBottomPadding to false, but then nothing moves (of course) and the TextField's get covered by the keyboard.

I remember from playing around with iOS in the past, this is default behavior, maybe I should reconsider my layout?

At the moment, I wrap it in a ListView so that the user is able to scroll when the keyboard appears.

This is my layout (just for testing)

@override
Widget build(BuildContext context) {
  this.context = context;
  return new Scaffold(
      key: _scaffoldKey,
      body: new Stack(
          children: <Widget>[loginImage(), new Column(
        crossAxisAlignment: CrossAxisAlignment.center,
        mainAxisAlignment: MainAxisAlignment.end,
        children: <Widget>[new TextField(), new TextField(),
        new TextField(), new TextField(),
        new TextField(), new TextField()],
      )])
  );
}

enter image description here: enter image description here

Upvotes: 18

Views: 64032

Answers (7)

devdoe
devdoe

Reputation: 4360

It's 2025. Flutter has evolved much and so are the workarounds to fix this problem. For mobile apps Scaffold's resizeToAvoidBottomInset property is enough but for mobile web browsers the issue is different on iOS and Android.

For iOS web, the trick is to listen to didChangeMetrics and remove focus when keyboard is hidden by the Done button on the keyboard accessory view.

For android web, you have to set resizeToAvoidBottomInset to false but only for android web and not others.

I know this is confusing but the solution is indeed complex but it handles all scenarios. See this post which explains it step by step: https://cleancodestack.com/flutter-keyboard-issues-fix-ios-android-and-web/

Upvotes: 1

tina abdallah
tina abdallah

Reputation: 31

Set this on scaffold:

  1. resizeToAvoidBottomInset: true

  2. Use stack to set your background.

    body: Stack(fit: StackFit.expand, children: <Widget>[
              Opacity(
                  opacity: 0.5,
                  child: Image.asset('lib/assets/images/background3.jpg',
                      fit: BoxFit.cover)),
              Padding(
                padding: EdgeInsets.all(20),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: <Widget>[
                    Header1(),
                    SizedBox(
                      height: 10,
                    ),
                    Tittle("Welcome to Bitetat's live repots"),
                    Expanded(
                      child: SingleChildScrollView(
                          physics: AlwaysScrollableScrollPhysics(),
                          child: Column(
                            mainAxisSize: MainAxisSize.min,
                            mainAxisAlignment: MainAxisAlignment.spaceAround,
                            children: <Widget>[
                              Container(

  1. There you can put your fields

Now you can enjoy nice background and your keyboard will not cover the fields and also scrollable.

Upvotes: 3

Rahul Sharma
Rahul Sharma

Reputation: 41

There also an alternate way instead of resizeToAvoidBottomInset

You can put the body of the Scaffold into SingleChildScrollView and apply physics to NeverScrollableScrollPhysics().

Scaffold(
        body: SingleChildScrollView(
          physics: NeverScrollableScrollPhysics(),
          child: Stack(
            children: [ ........

Upvotes: 0

Shubham Sharma
Shubham Sharma

Reputation: 186

It is default functionality of the Flutter. so, if you set resizeToAvoidBottomInset: false then you will lose the functionality of keeping your UI components above the keyboard. To have a background image in your application better way is to do it like this:

Container(
  decoration: BoxDecoration(
    color: primaryColor,
    image: DecorationImage(image: AssetImage(AppImages.appBg)),
  ),
  child: SafeArea(
    child: Scaffold(
      backgroundColor: Colors.transparent,
      body: //All Ui code here//
    ),
  ),
),

It is necessary to set Scaffold's backgroundColor: Colors.transparent otherwise, you won't be able to see your background image.

Upvotes: 1

Hahnemann
Hahnemann

Reputation: 4678

I had this problem while setting autoFocus: true in a CupertinoTextField() and fixed it by setting resizeToAvoidBottomInset: false in Scaffold().

resizeToAvoidBottomPadding is deprecated now.

Use resizeToAvoidBottomInset.

Upvotes: 57

The Billionaire Guy
The Billionaire Guy

Reputation: 3552

Also instead of Stack I suggest you use ListView. You could also on the other hand tryout SingleChildScrollView (but you might have to add extra codes for implementation).

Happy Coding...

Upvotes: 4

Kevin Walter
Kevin Walter

Reputation: 7186

I think this does what you want. The biggest problem is that you chose to use a Stack. A stack is only used if you want to stack things on top of each other. In this case you don't want that. Placing it in a Column and filling the open space with an Expanded (This Widget expands to usable space and pushes everything down) is the way I do it. I don't say it's the best way (Only 2 weeks of flutter experience). But it's a way. I hope it helps!

import 'package:flutter/material.dart';

void main() => runApp(new MyApp());

class MyApp extends StatelessWidget {
    // This widget is the root of your application.
    @override
    Widget build(BuildContext context) {
        return new MaterialApp(
            title: 'Flutter Demo',
            theme: new ThemeData(
                primarySwatch: Colors.blue,
            ),
            home: new Scaffold(
                body: new Column(
                    children: <Widget>[
                        new Center(
                            child: new Container(
                                height: 150.0,
                                width: 75.0,
                                color: Colors.red,
                            ),
                        ),
                        new Expanded(
                            child: new Container(),
                        ),
                        new Column(
                            crossAxisAlignment: CrossAxisAlignment.center,
                            mainAxisAlignment: MainAxisAlignment.end,
                            children: <Widget>[
                                new TextField(),
                                new TextField(),
                                new TextField(),
                                new TextField(),
                                new TextField(),
                                new TextField()
                            ],
                        ),
                    ],
                ),
            ),
        );
    }
}

Upvotes: 3

Related Questions