anonymous-dev
anonymous-dev

Reputation: 3529

Why do my containers size bigger than the screen size that causes the SingleChildScrollView() to scroll when the keyboard is down?

I am building a RegisterPage in flutter and I devided my scaffold into two containers. One for the top half and the other for the bottom half so that the logo/headline can be in the top half and the form be in the bottom half.

Now I noticed after testing on android that the keyboard overlaps the input fields. So I added a SingleChildScrollView() view to fix this. But there is a problem. The content appears to be too big and you can now always scroll even when the keyboard is down. I added a video to demonstrate what I mean.

I think that this space is responsible for that

enter image description here

It looks like that space is reserved for the android navigation bar. How do I remove that? Or how can I size my containers in such a way so that they account for that? Just to be clear the thing I want to know most is how I can stop my SingleChildScrollView() scrolling when the keyboard is down, which is probably cause by the containers being to big.

the_register_page.dart

  @override
  Widget build(BuildContext context) {
    final AuthenticationProvider authenticationProvider = Provider.of<AuthenticationProvider>(context);
    return Scaffold(
      backgroundColor: Theme.of(context).backgroundColor,
      body: Center(
        child: ScrollConfiguration(
          behavior: ScrollBehaviourWithoutGlow(),
          child: SingleChildScrollView(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              mainAxisSize: MainAxisSize.max,
              children: [
                Container(
                  decoration: BoxDecoration(color: Colors.red),
                  height: MediaQuery.of(context).size.height / 2,
                  child: _buildLogo(),
                ),
                Container(
                  decoration: BoxDecoration(color: Colors.green),
                  height: MediaQuery.of(context).size.height / 2,
                  child: _buildRegisterForm(authenticationProvider),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }

Notice that I used the SystemChrome.setEnabledSystemUIOverlays([]); in my main.dart.

main.dart

void main() {
  runApp(App());
}

class App extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    SystemChrome.setEnabledSystemUIOverlays([]);

    return MultiProvider(
      providers: [
        ChangeNotifierProvider<PreferencesProvider>(
            create: (_) => PreferencesProvider()),
        ChangeNotifierProvider<AuthenticationProvider>(
            create: (_) => AuthenticationProvider()),
        Provider<GroupProvider>(create: (_) => GroupProvider()),
        Provider<UserProvider>(
          create: (_) => UserProvider(),
        ),
      ],
      child: Consumer<PreferencesProvider>(
        builder: (context, preferences, _) => MaterialApp(
          home: TheSplashPage(),
          routes: <String, WidgetBuilder>{
            TheGroupPage.routeName: (BuildContext context) => TheGroupPage(),
            TheSettingsPage.routeName: (BuildContext context) =>
                TheSettingsPage(),
            TheProfilePage.routeName: (BuildContext context) =>
                TheProfilePage(),
            TheGroupCreationPage.routeName: (BuildContext context) =>
                TheGroupCreationPage(),
          },
          theme: preferences.isDarkMode
              ? DarkTheme.themeData
              : LightTheme.themeData,
          debugShowCheckedModeBanner: false,
        ),
      ),
    );
  }
}

Since this post didn't get any answers I decided to upload a video to show what I mean. Here is the video. As you can see you are able to swipe even when the keyboard is down which is not what I want.

https://www.youtube.com/watch?v=Rm91KMFqs60

Edit

This is tested on a android emulator

enter image description here

And my android device a Lenovo P2 with android 7

Edit

I can confirm that this bottom area is the cause. I looked at the pixel height on my pc screen and subtracted that from the container and now I can't scroll when the keyboard is down which is what I want.

So I would like to remove this area or get it's height any idea how?

Upvotes: 0

Views: 487

Answers (2)

Samuel Huff
Samuel Huff

Reputation: 698

You're very close. Setting the SystemChrome color to transparent just makes them see-through but won't draw your app over top of the navigation or status bars. The fix is a 2 step process.

  1. Set SystemChrome.setEnabledSystemUIOverlays([SystemUIOverlay.top]) to display only the notification bar or SystemChrome.setEnabledSystemUIOverlays([]) to display your app in full screen.

  2. In your Scaffold set the resizeToBottomInset property to false when you want the screen to display over top of the bottom system UI overlay and to true when the keyboard is up.

Full code example:

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  // Display your app in full-screen mode
  SystemChrome.setEnabledSystemUIOverlays([]);
  // Show the notification bar but not the navigation bar
  // SystemChrome.setEnabledSystemUIOverlays([SystemUiOverlay.top]);

  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'MyApp',
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {

  bool resizeToAvoidBottom;

  @override
  void initState() {
    super.initState();
    // Do not avoid bottom by default, this allows the display to paint over
    // where the Android button bar would be.
    resizeToAvoidBottom = false;
  }

  void setResize(bool resize) {
    setState(() {
      resizeToAvoidBottom = resize;
    });
  }

  @override
  Widget build(BuildContext context) {
    final height = MediaQuery.of(context).size.height / 2;

    return Scaffold(
      resizeToAvoidBottomInset: resizeToAvoidBottom,
      body: Container(
        height: MediaQuery.of(context).size.height,
        child: SingleChildScrollView(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            mainAxisSize: MainAxisSize.min,
            children: <Widget>[
              Placeholder(
                fallbackHeight: height,
              ),
              Container(
                height: height,
                  color: Colors.green,
                  child: Column(
                    children: <Widget>[
                      // Text fields update the resize property so that you
                      // can still scroll the display when the keyboard is up
                      // You will need to change when setResize(false) is
                      // called to suit the needs of your app
                      TextField(
                        onTap: () {
                          setResize(true);
                        },
                        onSubmitted: (str) {
                          setResize(false);
                        },
                      ),
                      TextField(
                        onTap: () {
                          setResize(true);
                        },
                        onSubmitted: (str) {
                          setResize(false);
                        },
                      ),
                    ],
                  ))
            ],
          ),
        ),
      ),
    );
  }
}

Upvotes: 0

vnztms
vnztms

Reputation: 21

This is actually a current Issue.

There is workaround which you could use, which is setting extendxBody: true in your Scaffold. But if it is not extremely critical I would wait for the fix to be deployed.

To clarify: My answer is about the empty space at the bottom.

Upvotes: 0

Related Questions