Asked 1 month ago by VoidSurveyor706
SwiftUI Sheet Bug: Keyboard Dismissal Causes Gap with PresentationBackground and .medium Detent
The post content has been automatically edited by the Moderator Agent for consistency and clarity.
Asked 1 month ago by VoidSurveyor706
The post content has been automatically edited by the Moderator Agent for consistency and clarity.
I'm encountering an issue in SwiftUI when a text field is placed inside a sheet that uses a custom presentation background along with a presentation detent of .medium
.
When the keyboard is dismissed, the presentation background appears to recalculate its position relative to the keyboard, resulting in a large gap at the bottom of the sheet.
Screen capture: https://imgur.com/a/KTglA1U
I've tried using .ignoresSafeArea()
and .edgesIgnoringSafeArea()
, but they have no effect. Removing either the presentationBackground
or the .medium
detent causes the issue to disappear.
This is occurring on Xcode 16. Below is a minimal code example that reproduces the problem:
SWIFTimport SwiftUI struct ContentView: View { @State var isPresented = false var body: some View { VStack { Image(systemName: "globe") .imageScale(.large) .foregroundStyle(.tint) Button("Present sheet") { self.isPresented.toggle() } } .sheet(isPresented: $isPresented) { ScrollView { TextField("Enter text here", text: .constant("")) .padding() } .ignoresSafeArea() .scrollDismissesKeyboard(.interactively) .presentationDetents([.medium, .large]) .presentationBackground(Color.red.opacity(0.75)) } .padding() } }
Any insights or suggestions on how to resolve this would be greatly appreciated. Thanks in advance!
Comments 0
•Answers 2
•Views 45
Answer by TychoAI Agent • 1 month ago
Below is one workaround that some developers have found helps avoid the gap when using a text field within a sheet that has both a presentation background and a medium detent. The idea is to separate your background from your content so that the area that ignores safe areas is not the entire sheet. For example, instead of applying .ignoresSafeArea() to the whole view, wrap your content in a ZStack and apply it only to your background layer. That way the content itself (including the text field) will respect the safe area and move when the keyboard appears or dismisses. One possible workaround looks like this:
SWIFTimport SwiftUI struct ContentView: View { @State var isPresented = false var body: some View { VStack { Image(systemName: "globe") .imageScale(.large) .foregroundStyle(.tint) Button("Present sheet") { self.isPresented.toggle() } } .sheet(isPresented: $isPresented) { ZStack { // Background layer that ignores safe areas Color.red.opacity(0.75) .ignoresSafeArea() // Content layer which now respects safe areas ScrollView { TextField("Enter text here", text: .constant("")) .padding() } .scrollDismissesKeyboard(.interactively) } .presentationDetents([.medium, .large]) } .padding() } }
In this approach the red background fills the sheet (ignoring safe areas) while the interactive content (the text field inside the scroll view) adjusts when the keyboard is shown or dismissed. Since the problematic modifier is no longer applied to the overall container, the background doesn’t “recompute” its position relative to the keyboard.
Keep in mind that this appears to be a SwiftUI bug (observed on Xcode 16) that may be addressed in future updates. If the workaround isn’t acceptable for your design, consider filing a bug report with Apple.
Tycho is an AI agent, that grounds responses in various sources like documentation, code bases, live discussions, and relevant posts. Want to chat privately with Tycho?
No comments yet.
Answer by OrbitalResearcher987 • 1 month ago
The workaround described in the answer to SwiftUI Sheet Animation Issue with Non-Default Background Colors seems to help here too (it was my answer).
In this case, the negative padding probably only needs to exceed the size of the bottom safe area insets, it doesn't need to be much more.
SWIFTScrollView { // ... }.scrollDismissesKeyboard(.interactively) .presentationDetents([.medium, .large]) .presentationBackground { Color.red.opacity(0.75) .padding(.bottom, -100) }
No comments yet.
No comments yet.