Skip to content

Instantly share code, notes, and snippets.

@StefKors
Created April 4, 2024 20:46
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save StefKors/09c309435ac82105a4e94969dc6330d8 to your computer and use it in GitHub Desktop.
Save StefKors/09c309435ac82105a4e94969dc6330d8 to your computer and use it in GitHub Desktop.
ScrollView + Sheet
//
// ContentView.swift
// 324 Messenger
//
// Created by Stef Kors on 29/03/2024.
//
import SwiftUI
import SwiftData
/// https://stackoverflow.com/a/76915525/3199999
struct GetHeightModifier: ViewModifier {
@Binding var height: CGFloat
func body(content: Content) -> some View {
content.background(
GeometryReader { geo -> Color in
DispatchQueue.main.async {
height = geo.size.height
}
return Color.clear
}
)
}
}
struct ContentSizeSheetModifier<V>: ViewModifier where V: View {
@Binding var isPresented: Bool
let sheetContent: () -> V
@State private var sheetContentHeight: CGFloat = .zero
func body(content: Content) -> some View {
content
.sheet(isPresented: $isPresented, content: {
VStack {
ScrollView {
sheetContent()
.modifier(GetHeightModifier(height: $sheetContentHeight))
}
.scrollBounceBehavior(.basedOnSize)
.presentationDetents([.height(sheetContentHeight)])
}
})
}
}
extension View {
func contentSizeSheet<V>(
isPresented: Binding<Bool>,
@ViewBuilder sheetContent: @escaping () -> V
) -> some View where V: View {
modifier(ContentSizeSheetModifier(isPresented: isPresented, sheetContent: sheetContent))
}
}
struct SheetBlock1: View {
var body: some View {
VStack {
Text("Spatial Audio")
.font(.largeTitle)
.padding()
Image(systemName: "person.3.fill")
.symbolRenderingMode(.palette)
.resizable()
.aspectRatio(contentMode: .fit)
.frame(height: 160)
.foregroundStyle(.foreground, .tint)
.padding()
Button("Get Started") {
}
.padding()
}
.background(.background.secondary, in: RoundedRectangle(cornerRadius: 20))
}
}
struct SheetBlock2: View {
var body: some View {
VStack {
Text("Apple Pencil")
.font(.largeTitle)
.padding()
Image(systemName: "macbook.and.visionpro")
.symbolRenderingMode(.palette)
.resizable()
.aspectRatio(contentMode: .fit)
.frame(height: 160)
.foregroundStyle(.foreground, .tint)
.padding()
Button("Get Started") {
}
.padding()
}
.background(.background.secondary, in: RoundedRectangle(cornerRadius: 20))
}
}
struct ContentView: View {
@State private var sheet1: Bool = false
@State private var sheet2: Bool = false
var body: some View {
VStack {
VStack {
Button("Show Non Scrolling Sheet") {
sheet1.toggle()
}
.buttonBorderShape(.roundedRectangle)
.buttonStyle(.borderedProminent)
Button("Show Scrolling Sheet") {
sheet2.toggle()
}
.buttonBorderShape(.roundedRectangle)
.buttonStyle(.borderedProminent)
}
.contentSizeSheet(isPresented: $sheet1, sheetContent: {
VStack {
SheetBlock1()
}
.padding()
.presentationCornerRadius(40)
.presentationDragIndicator(.visible)
})
.contentSizeSheet(isPresented: $sheet2, sheetContent: {
VStack {
SheetBlock2()
SheetBlock1()
SheetBlock2()
SheetBlock1()
}
.padding()
.presentationCornerRadius(40)
.presentationDragIndicator(.visible)
})
}
}
}
#Preview {
ContentView()
}
@StefKors
Copy link
Author

StefKors commented Apr 4, 2024

Screen.Recording.2024-04-04.at.22.45.20_optimized.mp4

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