Created
November 10, 2024 10:39
-
-
Save alobaili/43aa2fea8885cf237e360373bf903652 to your computer and use it in GitHub Desktop.
A SwiftUI view modifier that fits a sheet height to its contents.
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
import SwiftUI | |
fileprivate struct ReadHeightModifier: ViewModifier { | |
let action: (Double) -> Void | |
func body(content: Content) -> some View { | |
content | |
.onGeometryChange(for: Double.self) { proxy in | |
proxy.size.height | |
} action: { newValue in | |
action(newValue) | |
} | |
} | |
} | |
struct FittedPresentationDetentModifier: ViewModifier { | |
@State private var height = 0.0 | |
func body(content: Content) -> some View { | |
content | |
.readHeight { height in | |
/* | |
this guard is to avoid the following layout error that will | |
crash in future releases: | |
A presentation preference is rapidly switching between values, | |
possibly because the presentation's preferences depend on its size. | |
-- Previous Preferences -- | |
presentationsDetents: Height 389.3333333333333 | |
-- Most Recent Preferences -- | |
presentationsDetents: Height 376.6666666666667 | |
The most recent value was ignored to avoid cyclic layout. | |
Please update your code to avoid this issue. | |
This may become a crash in a future release. | |
*/ | |
guard height >= self.height else { return } | |
self.height = height | |
} | |
.presentationDetents([.height(height)]) | |
} | |
} | |
extension View { | |
func readHeight(_ perform: @escaping (Double) -> Void) -> some View { | |
modifier(ReadHeightModifier(action: perform)) | |
} | |
func fittedPresentationDetent() -> some View { | |
modifier(FittedPresentationDetentModifier()) | |
} | |
} | |
#Preview { | |
Color.clear | |
.sheet(isPresented: .constant(true)) { | |
DatePicker("", selection: .constant(.now), displayedComponents: .date) | |
.datePickerStyle(.graphical) | |
.fittedPresentationDetent() | |
} | |
} | |
#Preview { | |
Color.clear | |
.sheet(isPresented: .constant(true)) { | |
VStack { | |
Text("Example") | |
Text("Example") | |
Text("Example") | |
} | |
.fittedPresentationDetent() | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment