Skip to content

Instantly share code, notes, and snippets.

@fatbobman
Created April 5, 2024 06:59
Show Gist options
  • Save fatbobman/8b4a17e94fd14653b48f3454b847f640 to your computer and use it in GitHub Desktop.
Save fatbobman/8b4a17e94fd14653b48f3454b847f640 to your computer and use it in GitHub Desktop.
a dynamic sheet demo
import SwiftUI
struct ContentView: View {
@State var show = false
@State var height: CGFloat = 250
var body: some View {
List {
Button("Pop Sheet") {
height = 250
show.toggle()
}
Button("Pop ScrollView Sheet") {
height = 1000
show.toggle()
}
}
.adaptiveSheet(isPresent: $show) {
ViewThatFits(in: .vertical) {
SheetView(height: height)
ScrollView {
SheetView(height: height)
}
}
}
}
}
struct SheetView: View {
let height: CGFloat
var body: some View {
Text("Hi")
.frame(maxWidth: .infinity, minHeight: height)
.presentationBackground(.orange)
}
}
extension View {
func adaptiveSheet<Content: View>(isPresent: Binding<Bool>, @ViewBuilder sheetContent: () -> Content) -> some View {
modifier(AdaptiveSheetModifier(isPresented: isPresent, sheetContent))
}
}
struct AdaptiveSheetModifier<SheetContent: View>: ViewModifier {
@Binding var isPresented: Bool
@State private var subHeight: CGFloat = 0
var sheetContent: SheetContent
init(isPresented: Binding<Bool>, @ViewBuilder _ content: () -> SheetContent) {
_isPresented = isPresented
sheetContent = content()
}
func body(content: Content) -> some View {
content
.background(
sheetContent // 在此获取尺寸,防止初次弹出抖动
.background(
GeometryReader { proxy in
Color.clear
.task(id: proxy.size.height) {
subHeight = proxy.size.height
}
}
)
.hidden()
)
.sheet(isPresented: $isPresented) {
sheetContent
.presentationDetents([.height(subHeight)])
}
.id(subHeight)
}
}
@DavidTiimo
Copy link

DavidTiimo commented Jun 6, 2024

Okay thank you @fatbobman. I understand.

This is my scenario, I have some view constrained in height that needs to present a sheet.
Now after your feedback: views that do no use a scrollview works fine, but yes scrollview does not work.

Do you think you have a solution for using a scrollview in a sheet presented in a height constrained view?

Thank you again, and totally fine if this is too time consuming, I will find another way. Thank you.

struct MainView: View {
    var body: some View {
        VStack {
            ChildView()
                .frame(maxWidth: .infinity, maxHeight: 400)
        }
    }
}

struct ChildView: View {
    var body: some View {
        VStack {
            Text("Text")
                .frame(maxWidth: .infinity, maxHeight: 400)
        }
        .adaptiveSheet(isPresented: .constant(true)) {
            SheetView()
        }
    }
}

struct SheetView: View {
    var body: some View {
       // VStack works fine, ScrollView does not work 
        VStack {
        // ScrollView {
            Rectangle()
                .frame(width: 200, height: 200)
                .padding(10)
                .foregroundStyle(.blue)
            
            Rectangle()
                .frame(width: 200, height: 200)
                .padding(10)
                .foregroundStyle(.blue)
            
            Rectangle()
                .frame(width: 200, height: 200)
                .padding(10)
                .foregroundStyle(.blue)
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment