flutterflutter-layoutflutter-listviewflutter-iosflutter-android

TextField hides behind Keyboard in Flutter 3.0.0


I cannot get CustomScrollView to work properly.

Before flutter 2.13.0-0.2.pre, tapping on a TextFields inside a CustomScrollView automatically adjusts the TextField above the keyboard as it opens.

On downgrading my flutter version to 2.11.0-0.1.pre and running the application on Android version 11, scrollview works as expected - even without tweaking the Scaffold widget by adding resizeToAvoidBottomInset: false - when a user taps a TextField, the keyboard comes out and the user can scroll to the bottom as it should be.

However after upgrading to Flutter 3.0.0, things changed. When i tap a TextField and the keyboard comes out, i cannot scroll to the bottom of the screen. Actually, scrolling doesn't work at all.

Here's an example of a very long Form with about 26 TextFields. Tapping the 25th TextField opens the keyboard which covers that TextField.

@override
Widget build(BuildContext context) {
  return Scaffold(
    backgroundColor: const Color(0xff185C66),
    resizeToAvoidBottomInset: true,
    body: CustomScrollView(
      shrinkWrap: true,
      clipBehavior: Clip.antiAlias,
      controller: ScrollController(),
      scrollDirection: Axis.vertical,
      slivers: [
        SliverPadding(
          padding: EdgeInsets.symmetric(horizontal: App.sidePadding),
          sliver: SliverList(
            delegate: SliverChildListDelegate.fixed([
              SafeArea(
                bottom: false,
                child: AdaptiveText(
                  'Welcome Back',
                  maxLines: 1,
                  fontSize: 24.sp,
                  maxFontSize: 25,
                  fontWeight: FontWeight.w600,
                  textColor: Colors.white,
                  textColorDark: Colors.white,
                ),
              ),
              //
              0.02.verticalh,
              //
              SizedBox(
                width: 0.71.w,
                child: AdaptiveText(
                  'Login with your email and password to continue to your account',
                  fontSize: 16.sp,
                  maxFontSize: 17,
                  textColor: Colors.white,
                  textColorDark: Colors.white,
                ),
              ),
              //
              0.045.verticalh,
              //
              TextFormField(keyboardType: TextInputType.name),
              const SizedBox(height: 12),
              TextFormField(keyboardType: TextInputType.visiblePassword),
              const SizedBox(height: 12),
              TextFormField(keyboardType: TextInputType.emailAddress),
              const SizedBox(height: 12),
              TextFormField(keyboardType: TextInputType.emailAddress),
              const SizedBox(height: 12),
              TextFormField(keyboardType: TextInputType.streetAddress),
              const SizedBox(height: 12),
              TextFormField(keyboardType: TextInputType.emailAddress),
              const SizedBox(height: 12),
              TextFormField(keyboardType: TextInputType.datetime),
              const SizedBox(height: 12),
              TextFormField(keyboardType: TextInputType.datetime),
              const SizedBox(height: 12),
              TextFormField(keyboardType: TextInputType.datetime),
              const SizedBox(height: 12),
              TextFormField(keyboardType: TextInputType.datetime),
              const SizedBox(height: 12),
              TextFormField(keyboardType: TextInputType.emailAddress),
              const SizedBox(height: 12),
              TextFormField(keyboardType: TextInputType.phone),
              const SizedBox(height: 12),
              TextFormField(keyboardType: TextInputType.emailAddress),
              const SizedBox(height: 12),
              TextFormField(keyboardType: TextInputType.phone),
              const SizedBox(height: 12),
              TextFormField(keyboardType: TextInputType.phone),
              const SizedBox(height: 12),
              TextFormField(keyboardType: TextInputType.phone),
              const SizedBox(height: 12),
              TextFormField(keyboardType: TextInputType.phone),
              const SizedBox(height: 12),
              TextFormField(keyboardType: TextInputType.emailAddress),
              const SizedBox(height: 12),
              TextFormField(keyboardType: TextInputType.emailAddress),
              const SizedBox(height: 12),
              TextFormField(keyboardType: TextInputType.emailAddress),
              const SizedBox(height: 12),
              TextFormField(keyboardType: TextInputType.text),
              const SizedBox(height: 12),
              TextFormField(keyboardType: TextInputType.text),
              const SizedBox(height: 12),
              TextFormField(keyboardType: TextInputType.text),
              const SizedBox(height: 12),
              TextFormField(keyboardType: TextInputType.text),
              const SizedBox(height: 12),
              TextFormField(keyboardType: TextInputType.text),
              const SizedBox(height: 12),
              TextFormField(keyboardType: TextInputType.text),
              const SizedBox(height: 12),
            ]),
          ),
        ),
        //
        SliverPadding(
          padding: EdgeInsets.symmetric(horizontal: App.sidePadding),
          sliver: SliverSafeArea(
            top: false,
            sliver: SliverList(
              delegate: SliverChildListDelegate.fixed([
                SizedBox(height: 16),
                //
                TextButton(
                  onPressed: () {},
                  child: Text('Login'),
                ),
              ]),
            ),
          ),
        ),
      ],
    ),
  );
}

I googled this behavior and found some answers,

And so many others just to list a few.

I tried all the above solutions, but they either don't fix the issue or just feels like a lot of work compared to the normal way scrollviews should work. On checking the Flutter 3.0.0 changelog, i couldn't find any reference to this change in scrollview.

Am I missing something? Was there a change to CustomScrollView in flutter 3.0.0? Any idea how i can resolve this issue?

Here is the result of flutter doctor -v

[✓] Flutter (Channel stable, 3.0.0, on macOS 12.3.1 21E258 darwin-x64, locale en-NG)
    • Flutter version 3.0.0 at /Users/brendan/src/flutter
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision ee4e09cce0 (2 weeks ago), 2022-05-09 16:45:18 -0700
    • Engine revision d1b9a6938a
    • Dart version 2.17.0
    • DevTools version 2.12.2

[✓] Android toolchain - develop for Android devices (Android SDK version 33.0.0-rc2)
    • Android SDK at /Users/brendan/Library/android/sdk
    • Platform android-31, build-tools 33.0.0-rc2
    • ANDROID_HOME = /Users/brendan/Library/android/sdk
    • Java binary at: /Applications/Android Studio.app/Contents/jre/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build 11.0.11+0-b60-7590822)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 13.2.1)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • CocoaPods version 1.11.3

[✓] Chrome - develop for the web
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 2021.1)
    • Android Studio at /Applications/Android Studio.app/Contents
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 11.0.11+0-b60-7590822)

[✓] VS Code (version 1.67.2)
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension version 3.40.0

[✓] Connected device (3 available)
    • Redmi Note 9S (mobile) • 702f6413 • android-arm64  • Android 11 (API 30)
    • macOS (desktop)        • macos    • darwin-x64     • macOS 12.3.1 21E258 darwin-x64
    • Chrome (web)           • chrome   • web-javascript • Google Chrome 101.0.4951.64
    ! Error: j@mon is not connected. Xcode will continue when j@mon is connected. (code -13)

[✓] HTTP Host Availability
    • All required HTTP hosts are available

• No issues found!

EDIT: This issue affects Android and iOS.


Solution

  • I found the solution. I had installed the flutter_screenutil package and inserted it above my widget tree - above MaterialApp and I'd also set useInheritedMediaQuery: true. This prevented widget rebuilds for things like keyboard state change.

    Moving the ScreenUtils widget below MaterialApp fixed it.