Repository navigation
Description
Note
Workaround 1
The provided example sets two different colors, if you do not set colors, or allow for default behavior, this works as expected.
Alternatively...
Workaround 2
If your app is affected by this problem, consider disabling Liquid Glass for your app by updating your ios/Runner/Info.plist file:
<key>UIDesignRequiresCompatibility</key>
<true/>The UIDesignRequiresCompatibility property is a temporary workaround until Flutter fixes this issue. You will need to remove this property in the future.
For more details, see: https://developer.apple.com/documentation/BundleResources/Information-Property-List/UIDesignRequiresCompatibility
Steps to reproduce
Platforms
iOS
When you click on the text input box in the BottomSheet Modal, the color around the rounded corner at the top of the semi-transparent keyboard that pops up is incorrect
Expected results
.
Actual results
When using the keyboard inside an open Bottom Sheet Modal, the modal shifts upward to make room for the keyboard. However, this causes the semi-transparent keyboard on iOS 26 to display a black background instead of showing the modal's content. Please note, this is not a corner-radius issue—the entire keyboard, being semi-transparent, clearly shows a black background during dragging, which is inconsistent with the modal's color.
Code sample
Code sample
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Bottom Sheet Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
useMaterial3: true,
),
home: const HomeScreen(),
);
}
}
class HomeScreen extends StatefulWidget {
const HomeScreen({super.key});
@override
State<HomeScreen> createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
// Controller for the text input field
final TextEditingController _textController = TextEditingController();
// Focus node to manage keyboard focus
final FocusNode _textFocusNode = FocusNode();
// Store user input
String _userInput = '';
@override
void dispose() {
_textController.dispose();
_textFocusNode.dispose();
super.dispose();
}
// Method to show the bottom sheet
void _showBottomSheet(BuildContext context) {
// Clear previous input when opening
_textController.clear();
showModalBottomSheet(
context: context,
isScrollControlled: true, // Allows sheet to move up with keyboard
backgroundColor: Colors.transparent,
builder: (BuildContext context) {
return GestureDetector(
onTap: () {
// Dismiss keyboard when tapping outside
FocusScope.of(context).unfocus();
},
child: Container(
padding: EdgeInsets.only(
bottom: MediaQuery.of(context).viewInsets.bottom, // Make room for keyboard
),
child: _buildBottomSheetContent(context),
),
);
},
).then((value) {
// Handle when bottom sheet is closed
setState(() {
_userInput = _textController.text;
});
});
// Request focus for the text field after a short delay
Future.delayed(const Duration(milliseconds: 300), () {
FocusScope.of(context).requestFocus(_textFocusNode);
});
}
// Build the content of the bottom sheet
Widget _buildBottomSheetContent(BuildContext context) {
return Container(
decoration: const BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(20),
topRight: Radius.circular(20),
),
),
child: Padding(
padding: const EdgeInsets.all(20.0),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// Header with close button
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const Text(
'Enter Your Text',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
IconButton(
onPressed: () {
Navigator.pop(context);
},
icon: const Icon(Icons.close),
),
],
),
const SizedBox(height: 20),
// Text input field
TextField(
controller: _textController,
focusNode: _textFocusNode,
decoration: InputDecoration(
hintText: 'Type something here...',
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
),
filled: true,
fillColor: Colors.grey[100],
contentPadding: const EdgeInsets.symmetric(
horizontal: 16,
vertical: 16,
),
suffixIcon: IconButton(
onPressed: () {
_textController.clear();
},
icon: const Icon(Icons.clear),
),
),
maxLines: 3,
minLines: 1,
),
const SizedBox(height: 20),
// Action buttons
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
// Cancel button
TextButton(
onPressed: () {
Navigator.pop(context);
},
child: const Text('Cancel'),
),
const SizedBox(width: 10),
// Submit button
ElevatedButton(
onPressed: () {
setState(() {
_userInput = _textController.text;
});
Navigator.pop(context);
},
style: ElevatedButton.styleFrom(
backgroundColor: Colors.blue,
foregroundColor: Colors.white,
padding: const EdgeInsets.symmetric(
horizontal: 24,
vertical: 12,
),
),
child: const Text('Submit'),
),
],
),
],
),
),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Bottom Sheet Demo'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text(
'Bottom Sheet Example',
style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
),
const SizedBox(height: 20),
// Display user input
Container(
padding: const EdgeInsets.all(20),
margin: const EdgeInsets.symmetric(horizontal: 20),
decoration: BoxDecoration(
color: Colors.grey[100],
borderRadius: BorderRadius.circular(10),
),
child: Column(
children: [
const Text(
'Your Input:',
style: TextStyle(fontSize: 16, color: Colors.grey),
),
const SizedBox(height: 10),
Text(
_userInput.isEmpty ? 'No input yet' : _userInput,
style: const TextStyle(
fontSize: 18,
fontWeight: FontWeight.w500,
),
textAlign: TextAlign.center,
),
],
),
),
const SizedBox(height: 40),
// Instructions
Container(
padding: const EdgeInsets.all(16),
margin: const EdgeInsets.symmetric(horizontal: 20),
decoration: BoxDecoration(
color: Colors.blue[50],
borderRadius: BorderRadius.circular(10),
),
child: const Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Icon(Icons.info, color: Colors.blue, size: 20),
SizedBox(width: 8),
Text(
'How to use:',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
color: Colors.blue,
),
),
],
),
SizedBox(height: 8),
Text(
'Tap the button below to open a bottom sheet. The text field will automatically gain focus and the keyboard will appear.',
style: TextStyle(fontSize: 14, color: Colors.blue),
),
],
),
),
],
),
),
floatingActionButton: FloatingActionButton.extended(
onPressed: () => _showBottomSheet(context),
icon: const Icon(Icons.edit),
label: const Text('Open Bottom Sheet'),
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
);
}
}Screenshots or Video
Logs
Logs
[Paste your logs here]Flutter Doctor output
Doctor output
[Paste your output here]
Activity
tirth-patel-nc commentedon Dec 5, 2025
Thanks for the report. Seeing the same behaviour with latest SDK versions on iOS 26. Appears fine on iOS 18.
48 remaining items
Piinks commentedon May 1, 2026
I don't think users will want to have to manage their own padding, that would be a regression from the current behavior.
My understanding is that the layout, the content of the body will still respect resizeToAvoidBottomInset while the scaffold background color paints behind the keyboard.
victorsanni commentedon May 12, 2026
Hi @Lonely-ash, in your sample code, will moving the viewInsets padding of the modalBottomSheet to a lower position in the widget tree of showModalBottomSheet.builder (i.e to after the desired background color has been set) fix the issue?
The Material library bottom sheets all use the same underlying widget: BottomSheet. There are two kinds of
BottomSheets: persistent and modal. Persistent bottom sheets are visible even while interacting with other parts of the app (e.g ScaffoldState.showBottomSheet, showBottomSheet), while modal bottom sheets prevent users from interacting with the rest of the app.The way showModalBottomSheet prevents users from interacting with the rest of the app is by pushing a new route - ModalBottomSheetRoute - onto the Navigator. Because this is a new route, the entire region covered by the bottom sheet (including the area behind the keyboard) is within developer control via
showModalBottomSheet.builder.Say a developer wants a modalBottomSheet that has a red background. Then, their showModalBottomSheet will look like:
So as long as the viewInsets.bottom padding is done on a child/descendant of the widget that sets the background color, the background color will be shown behind the keyboard. Alternatively, setting showModalBottomSheet.backgroundColor will set the background color of the underlying Material for the entire modal, providing an easy + themable solution.
So IMO for showModalBottomSheet (and other modals like showCupertinoModalPopup) this is WAI.
victorsanni commentedon May 12, 2026
Hi @auradigitaldev, thanks for the response.
Could you provide a code sample so I can debug this?
So far in my investigation, I have found that
resizeToAvoidBottomInsetset to true has a more narrow impact, because the framework's dialogs (e.gshowDialog,showRawDialog) all push new routes (e.gDialogRoute) onto theNavigator, and so their barrier colors cover the area of the entire route, including the area behind the keyboard.Are you referring to custom implementations of widgets with barriers (dialogs, modals etc.) without pushing a route onto the
Navigator? In general some code to repro will be greatly appreciated.victorsanni commentedon Jun 4, 2026
Hi, I documented the results of my investigation in this doc: https://flutter.dev/go/ios-26-keyboard-bleed. Please read and leave comments. Thanks!
victorsanni commentedon Jul 23, 2026
TL;DR of the doc (https://flutter.dev/go/ios-26-keyboard-bleed)
The core problem is that
viewInsets.bottomis correctly used as a layout-avoidance boundary (e.g withresizeToAvoidBottomInset), but is often also treated as a paint boundary. The rounded, translucent iOS 26 keyboard makes the pixels behind that region visible, causing a visual seam that reads as a polish bug to end users.Broadly, the issue manifests in three ways:
Framework-owned persistent bottom sheets (
Scaffold.bottomSheet,showBottomSheet, andScaffoldState.showBottomSheet):Scaffoldpositions the sheet above the keyboard but paints its own background behind the keyboard. This is a framework issue. The proposed fix (#186365) is forScaffoldto continue painting the sheet’s surface through the inset without extending its interactive layout by adding a keyboard backdrop.Modals, including the
showModalBottomSheetrepro in this issue description: The application owns the entire route. For example, a transparent modal background combined with an opaque child and padding outside that child exposes the underlying route. This is an application composition issue. The modal background should match the intended surface (for example by settingshowModalBottomSheet.backgroundColorto the surface color), with keyboard padding applied inside that surface.Non-modal surfaces: Widgets that stop both layout and background paint at
viewInsets.bottomcan expose an unrelated surface. For example, this might happen if a widget expected to be contiguous with the keyboard is in the body of aScaffoldthat has itsScaffold.resizeToAvoidBottomInsetset to true. This is an application/package issue, and the fix depends on the specific widget/API. Consider usingOverlayPortalor similar to paint a pointer-ignored continuation through the keyboard inset. In general, the background should extend through the inset while interactive content continues to avoid it.To reflect the rounded/translucent keyboard reality, Flutter should also update the
viewInsetsdocumentation: it describes a region applications should generally avoid for interaction, not an area guaranteed to be visually opaque.The recommended general rule is: paint extends behind the keyboard; interactive layout does not.
[material_ui] Paint Scaffold persistent bottom sheet background color…
[material_ui] Paint Dialog.fullscreen background color behind the key…
victorsanni commentedon Nov 10, 2026
MediaQueryData.viewInsets might not be the right thing to use on iOS keyboard is related to this issue.