Created
April 4, 2024 20:46
-
-
Save StefKors/09c309435ac82105a4e94969dc6330d8 to your computer and use it in GitHub Desktop.
ScrollView + Sheet
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// 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() | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Screen.Recording.2024-04-04.at.22.45.20_optimized.mp4