3

I wanted to try out the new .presentationBackground modifier from iOS 16.4+ for a clear background in a Sheet. Stack Overflow posts like this suggest it's possible.

But the presentationBackground just seems to be overlaid over the default sheet background.

With this code:

import SwiftUI

struct ImmersionModeScreen: View {
    
    @State var presentSheet: Bool = false
    
    var body: some View {
        VStack(alignment: .center, spacing: 15) {
            Button {
                presentSheet = true
            } label: {
                Text("Present")
            }
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
        .background(.red)
        .sheet(isPresented: $presentSheet) {
            Text("Detail")
                .presentationBackground(.clear)
        }
        
    }
}

#Preview {
    ImmersionModeScreen()
}

I got this result:

enter image description here

The background of the sheet is not clear like we're telling it to be.

And when I use a shape for .presentationBackground:

.presentationBackground {
  UnevenRoundedRectangle(
    cornerRadii: RectangleCornerRadii(topLeading: 100, topTrailing: 100),
    style: .continuous
  )
  .fill(.orange)
}

Once again, it's not working properly—you can still see the default background behind.

enter image description here

What am I doing wrong?

My project is running on iOS 18.

0

2 Answers 2

4

Liquid Glass gives sheets a translucent appearance when they are presented at partial height. When the sheet expands to the large detent, its background becomes fully opaque.

With .presentationBackground(Color.clear), the new Liquid Glass effect is blocked, but the background doesn’t actually become clear, you still get the new default translucent background.

As a workaround, you can set

.presentationDetents([.fraction(0.98)])

This changes the background to translucent

struct ContentView: View {
    var body: some View {
        VStack {
            Text("View Body")
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
        .background(.pink)
        .ignoresSafeArea()
        .sheet(isPresented: .constant(true)) {
            Text("Sheet Content")
                .presentationDetents([.fraction(0.98)])
        }
    }
}

Other solutions no longer work, and unfortunately no proper new solution has been found yet.

Sign up to request clarification or add additional context in comments.

Comments

1

Using .presentationBackground(.clear) does work for sheets when running with iOS versions before iOS 26. However, with iOS 26, the background is always opaque when the sheet is the default .large detent size. Smaller detents have a glass effect.

Setting a clear background does still work for .fullScreenCover, so you could consider using this for showing a modal view with transparent or semi-transparent background. However, you will have to add your own drag gesture if you want to be able to drag to dismiss.

Here is an adaption of your example to show how it can be done:

struct ImmersionModeScreen: View {
    let loremIpsum = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
    @State private var presentSheet: Bool = false
    @GestureState private var dragOffset = CGFloat.zero

    var body: some View {
        VStack(alignment: .center, spacing: 15) {
            Text(loremIpsum)
                .font(.title)
                .padding()
            Button {
                presentSheet = true
            } label: {
                Text("Present")
            }
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
        .background(.red)
//        .sheet(isPresented: $presentSheet) {
        .fullScreenCover(isPresented: $presentSheet) {
            Text("Detail")
                .font(.largeTitle)
                .frame(maxWidth: .infinity, maxHeight: .infinity)
                .background {
                    UnevenRoundedRectangle(topLeadingRadius: 50, topTrailingRadius: 50)
                        .fill(.background.opacity(0.5))
                        .ignoresSafeArea(edges: .bottom)
                }
                .offset(y: dragOffset)
                .animation(.easeInOut, value: dragOffset)
                .gesture(
                    DragGesture()
                        .updating($dragOffset) { val, state, trans in
                            state = max(0, val.translation.height)
                        }
                        .onEnded { val in
                            if val.predictedEndTranslation.height > 300 {
                                presentSheet = false
                            }
                        }
                )
                .presentationBackground(.clear)
        }
    }
}

Animation

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.