In Flutter, when the keyboard appears (especially on mobile), it often covers the bottom part of the screen, hiding your TextField or buttons. To automatically add padding at the bottom when the keyboard is visible — and ensure your input field stays visible above the keyboard — here are the best and most common solutions:
Recommended Solution (2025 best practice): Use scaffoldResizeToAvoidBottomInset + Padding with MediaQuery.viewInsets
Wrap your main content (or just the input area) with padding that reacts to the keyboard:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
resizeToAvoidBottomInset: true, // This is important!
body: MyHomePage(),
),
);
}
}
class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return SafeArea(
child: Padding(
// This padding will automatically grow when keyboard appears
padding: EdgeInsets.only(
bottom: MediaQuery.of(context).viewInsets.bottom,
),
child: Column(
mainAxisAlignment: MainAxisAlignment.end, // Push content to bottom
children: [
// Your other widgets...
TextField(
decoration: InputDecoration(
labelText: "Enter text",
border: OutlineInputBorder(),
),
),
SizedBox(height: 20),
ElevatedButton(
onPressed: () {},
child: Text("Submit"),
),
SizedBox(height: 20), // Extra space so it doesn't stick to edge
],
),
),
);
}
}
Why this works perfectly:
MediaQuery.of(context).viewInsets.bottom→ returns the height of the keyboard (or 0 when hidden)resizeToAvoidBottomInset: true→ allows the Scaffold to shrink when keyboard appears- The
Paddingautomatically pushes your content up exactly by the keyboard height - Works perfectly with
Column+mainAxisAlignment: MainAxisAlignment.end
Alternative: Use SingleChildScrollView (for longer forms)
If your form is long and might need scrolling:
Scaffold(
resizeToAvoidBottomInset: false, // Set to false when using manual scroll
body: SafeArea(
child: SingleChildScrollView(
padding: EdgeInsets.only(
left: 16,
right: 16,
bottom: MediaQuery.of(context).viewInsets.bottom + 20,
),
child: Column(
children: [
// Many TextFields...
TextField(...),
TextField(...),
// ...
SizedBox(height: 20),
ElevatedButton(onPressed: () {}, child: Text("Submit")),
],
),
),
),
)
Bonus: Auto-scroll to focused field (optional but nice)
Add scrollPadding to your TextField:
TextField(
scrollPadding: EdgeInsets.only(bottom: 200), // Extra space when keyboard opens
decoration: InputDecoration(...),
)
Or use the flutter_keyboard_visibility package if you want to react to keyboard show/hide events explicitly.
Summary – Quick Copy-Paste Fix
Just add this to your Scaffold body:
padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
and make sure:
Scaffold(
resizeToAvoidBottomInset: true, // almost always want this
...
)
This is the standard, cleanest, and most reliable way in Flutter as of 2025.
@override
void didChangeMetrics() {
// Called when viewInsets (like keyboard height) changes
final bottomInset = WidgetsBinding.instance.window.viewInsets.bottom;
final newValue = bottomInset > 0.0;
if (newValue != _isKeyboardVisible) {
setState(() => _isKeyboardVisible = newValue);
}
}
if (_isKeyboardVisible)
Widget(...),
