skip to Main Content

I’m having trouble getting a sheet to expand past the safe area and touch the leading and trailing edges of the screen when the device is in landscape.

Ideally the sheet would have all the benefits of using .presentationCompactAdaptation(.sheet) and the white background would touch the horizontal edges of the screen – similar to how a sheet operates in portrait.

See image highlighting the leading and trailing edges I would like the sheet to ignore.

Using fullScreenCover is not an option.

sheet landscape example

import SwiftUI

struct LandscapeSheetTest: View {
    @State private var isSheetPresented: Bool = false
    var body: some View {
        VStack {
            Button {
                isSheetPresented.toggle()
            } label: {
                Text("show sheet")
            }

        }
        .sheet(isPresented: $isSheetPresented) {
            VStack {
                Text("Some content here")
            }
            .frame(width: UIScreen.main.bounds.width) // Not necessary, but highlights how the sheet only stretches up to the safe area bounds
            .presentationContentInteraction(.resizes)
            .presentationCompactAdaptation(.sheet)
            .presentationDetents([.height(200), .large])
        }
    }
}

#Preview {
    LandscapeSheetTest()
}

2

Answers


  1. This simply isn’t possible using the built in .sheet modifier. You would need to build your own sheet implementation or use a third-party dependency like ManySheets (https://github.com/GlennBrann/ManySheets) which does support this. Note – I’m not affiliated w/ManySheets and am simply making a suggestion to use it.

    Login or Signup to reply.
  2. 
    struct ContentView: View {
        @State private var showSheet = false
    
        var body: some View {
            Button("Show Full-Screen Sheet") {
                showSheet.toggle()
            }
            .fullScreenAdaptiveSheet(isPresented: $showSheet) {
                VStack {
                    Text("Full-Screen Adaptive Sheet")
                        .font(.title)
                        .foregroundColor(.white)
                        .padding(.top, 50)
                    Text(UIDevice.current.orientation.isLandscape ? "Landscape" : "Portrait")
                        .foregroundColor(.white)
                    Spacer()
                }
                .frame(maxWidth: .infinity, maxHeight: .infinity)
                .background(Color.green)
            }
        }
    }
    
    struct FullScreenAdaptiveSheet<SheetContent: View>: ViewModifier {
        @Binding var isPresented: Bool
        let sheetContent: () -> SheetContent
    
        func body(content: Content) -> some View {
            content
            .fullScreenCover(isPresented: $isPresented) {
                ZStack(alignment: .bottomTrailing) {
                    sheetContent()
                        .ignoresSafeArea()
    
                    Button(action: {
                        isPresented = false
                    }) {
                        Image(systemName: "xmark")
                            .foregroundColor(.black)
                            .font(.system(size: 20, weight: .bold))
                            .padding()
                            .background(.regularMaterial)
                            .clipShape(Circle())
                    }
                    .padding(.bottom, 20)
                    .padding(.trailing, 20)
                }
            }
        }
    }
    
    extension View {
        func fullScreenAdaptiveSheet<SheetContent: View>(
            isPresented: Binding<Bool>,
            @ViewBuilder content: @escaping () -> SheetContent
        ) -> some View {
            self.modifier(
                FullScreenAdaptiveSheet(
                    isPresented: isPresented,
                    sheetContent: content
                )
            )
        }
    }
    
    

    Landscape View with Full-screen support

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search