Flutter - Textfield not showing up when keyboard appears on android

2,254

Solution 1

android/app/src/main/res/values/styles.xml

For me changing below item property from true to false

<item name="android:windowFullscreen">false</item>

I had this issue, too. This line was added as a result of using the flutter_native_splash package.

Solution 2

You can wrap your BottomPlayerBar widget with the Transform Widget as shown below.

Transform.translate(
    offset: Offset(0.0, -1 * MediaQuery.of(context).viewInsets.bottom),
    child: BottomPlayerBar(),
    );

Solution 3

Resizing the page when the soft keyboard appears is handled through the android:windowSoftInputMode activity parameter in AndroidManifest. See the official documnetation

If you have android:windowSoftInputMode="adjustResize" in your AndroidManifest.xml, the textfield will automatically reposition when the softkeyboard appears. The same behaviour will not happen if the parameter is not there in AndroidManifest.xml

Could you recheck this by modifying your AndroidManifest. That will also explain why it is not working only in Android but works in iOS (Because iOS handles this implicitly)

P.S: When modifying the AndoridManifest.xml, hot reload may not work. You will need an actual stop and start running the app.

Share:
2,254
Simon B
Author by

Simon B

Updated on December 23, 2022

Comments

  • Simon B
    Simon B over 1 year

    My problem is that when I focus on the textfield, the keyboard appears but the layout doesn't resize to keep it in the view. This problem is only with android and not iOS: Here a screenshot of what I mean:

    Before and after on android:

    Before After

    Before and after on iOS:

    enter image description here enter image description here

    Here is my class :

    class PlayerSelectionPage extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        int itemCount = Provider.of<PlayerProvider>(context).getPlayerList.length;
        SystemChrome.setPreferredOrientations([
          DeviceOrientation.portraitUp,
        ]);
        return Scaffold(
          appBar: AppBar(
            title: Text(AppLocalizations.of(context).translate('player_selection_page_title')),
          ),
          floatingActionButton: FloatingActionButton(
            onPressed: (){
              HapticFeedback.mediumImpact();
              Navigator.push(context, MaterialPageRoute(builder: (context) => HomePage(), settings: RouteSettings(name: 'Home page')));
            },
            child: Icon(
              Icons.chevron_right,
              size: 30,
              color: Colors.white,
            ),
          ),
          body: itemCount > 0 ? ListView.builder(
              itemCount: itemCount,
              itemBuilder: (context, index) {
                return Column(
                  children: [
                    PlayerDismissible(index),
                    Divider(
                      height: 0,
                    )
                  ],
                );
              }) : Container(
              padding: EdgeInsets.all(20),
              alignment: Alignment.topCenter,
              child: Text(AppLocalizations.of(context).translate('player_selection_page_empty_text'), textAlign: TextAlign.center, style: Theme.of(context).textTheme.subtitle2)
          ),
          bottomSheet: BottomPlayerBar(),
        );
      }
    }
    
    

    And here is my BottomPlayerBar() :

    class BottomPlayerBar extends StatefulWidget{
      @override
      _BottomPlayerBarState createState() => _BottomPlayerBarState();
    }
    
    class _BottomPlayerBarState extends State<BottomPlayerBar> {
      String playerName;
      FocusNode myFocusNode;
    
    
      @override
      void initState() {
        super.initState();
        myFocusNode = FocusNode();
        SchedulerBinding.instance.addPostFrameCallback((_) {
          if (ModalRoute.of(context).isCurrent) {
            myFocusNode.requestFocus();
          }
        });
      }
    
      @override
      Widget build(BuildContext context) {
        return Container(
            height: 80, color: Theme.of(context).primaryColor,
            padding: EdgeInsets.only(top: 20, bottom: 25, left: 20, right: 70),
            child: TextField(
              focusNode: myFocusNode,
              textCapitalization: TextCapitalization.words,
              onChanged: (val) => playerName = val.trim(),
              onSubmitted: (val) {
                if (playerName != null && playerName != '') {
                  Provider.of<PlayerProvider>(context, listen: false).addPlayer(playerName);
                  HapticFeedback.lightImpact();
                  myFocusNode.requestFocus();
                } else {
                  myFocusNode.unfocus();
                }
              },
              maxLength: 19,
              autocorrect: false,
              decoration: new InputDecoration(
                  counterText: "",
                  border: new OutlineInputBorder(
                    borderSide: BorderSide.none,
                    borderRadius: const BorderRadius.all(
                      const Radius.circular(30.0),
                    ),
                  ),
                  filled: true,
                  contentPadding: EdgeInsets.symmetric(vertical: 0, horizontal: 20),
                  hintStyle: GoogleFonts.rubik(color: Colors.grey[500], fontWeight: FontWeight.bold),
                  hintText: AppLocalizations.of(context).translate('player_selection_page_hint'),
                  fillColor: Colors.white),
            )
        );
      }
    
      @override
      void dispose() {
        super.dispose();
        myFocusNode.dispose();
      }
    }
    
    

    Here is my android manifest:

    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="myApp">
        <application
            android:name="io.flutter.app.FlutterApplication"
            android:label="myApp !"
            android:icon="@mipmap/ic_launcher">
            <activity
                android:name=".MainActivity"
                android:launchMode="singleTop"
                android:theme="@style/LaunchTheme"
                android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
                android:hardwareAccelerated="true"
                android:windowSoftInputMode="adjustResize">
                <meta-data
                  android:name="io.flutter.embedding.android.LaunchTheme"
                  android:resource="@style/LaunchTheme"
                  />
                <meta-data
                  android:name="io.flutter.embedding.android.SplashScreenDrawable"
                  android:resource="@drawable/launch_background"
                  />
                <intent-filter>
                    <action android:name="android.intent.action.MAIN"/>
                    <category android:name="android.intent.category.LAUNCHER"/>
                </intent-filter>
                <intent-filter>
                    <action android:name="FLUTTER_NOTIFICATION_CLICK" />
                    <category android:name="android.intent.category.DEFAULT" />
                </intent-filter>
            </activity>
            <meta-data
                android:name="flutterEmbedding"
                android:value="2" />
        </application>
    </manifest>
    
    
    • Nemi Shah
      Nemi Shah over 3 years
      Can you post the setup in the android manifest file
    • Simon B
      Simon B over 3 years
      Here it is, but I don't really know how it'll help.
    • Rod
      Rod over 3 years
      Because of your 'android:windowSoftInputMode="adjustResize"'. It should be doing what you want.
    • Simon B
      Simon B over 3 years
      Should I delete this line ?
    • Simon B
      Simon B over 3 years
      It didn't work...
  • Simon B
    Simon B over 3 years
    Thanks a lot, this was exactly the problem !