When clicking on the text input the web version of a Flutter app (iOS Safari), the soft keyboard covers the text input making it impossible to see what is being typed. (see gif below)
The expected behavior is that the text input would animate to remain visible above the soft keyboard, as it does in the iOS native version created by Flutter.
In Flutter 3.7, it appears that resizeToAvoidBottomInset (which defaults to true) should control this behavior:
if there is an onscreen keyboard displayed above the scaffold, the body can be resized to avoid overlapping the keyboard, which prevents widgets inside the body from being obscured by the keyboard.
However, in Safari on iOS this doesn't appear to be true.
Previous questions don't appear to fix this issue or introduce what appear to be unnecessary workarounds:
- Flutter TextFormField hidden by keyboard
- add
paddingto theTextField - use
SingleScrollView
- add
- Flutter Keyboard makes textfield hide
- create custom animation
- add
SizedBoxbelowTextField
- Flutter TextEditingController does not scroll above keyboard
- Flutter soft keyboard covering textfield and singlechildscrollview not working
View: soft keyboard obscures text input in Safari on iOS
Code:
import 'package:flutter/material.dart';
class TestScreen extends StatefulWidget {
const TestScreen({super.key});
@override
State<TestScreen> createState() => _TestScreenState();
}
class _TestScreenState extends State<TestScreen> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Chat')),
body: Column(
children: const [
Expanded(
child: Center(
child: Text('Send a message to start your conversation.'),
),
),
_MessageBar(),
],
),
);
}
}
class _MessageBar extends StatefulWidget {
const _MessageBar({Key? key}) : super(key: key);
@override
State<_MessageBar> createState() => __MessageBarState();
}
class __MessageBarState extends State<_MessageBar> {
late final TextEditingController _textController;
@override
Widget build(BuildContext context) {
return Material(
color: Colors.grey[200],
child: SafeArea(
child: Padding(
padding:
EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
child: Row(
children: [
Expanded(
child: TextFormField(
keyboardType: TextInputType.text,
maxLines: null,
autofocus: true,
controller: _textController,
decoration: const InputDecoration(
hintText: 'Type a message',
border: InputBorder.none,
focusedBorder: InputBorder.none,
contentPadding: EdgeInsets.all(8.0),
),
),
),
TextButton(
onPressed: () => _submitMessage(),
child: const Text('Send'),
)
],
),
),
),
);
}
@override
void initState() {
_textController = TextEditingController();
super.initState();
}
@override
void dispose() {
_textController.dispose();
super.dispose();
}
void _submitMessage() async {
final text = _textController.text;
if (text.isEmpty) {
return;
}
print({text});
_textController.clear();
}
}

SingleChildScrollViewand also at the same time add this property in scaffold to trueresizeToAvoidBottomInset:truethis may help or there is also another property ofSingleChildScrollViewi.ereverseset it totrueand check