Skip to content

Instantly share code, notes, and snippets.

@sean-perkins
Created March 22, 2022 17:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sean-perkins/389d7f3445538edbe90441b283bd43ff to your computer and use it in GitHub Desktop.
Save sean-perkins/389d7f3445538edbe90441b283bd43ff to your computer and use it in GitHub Desktop.
iOS Modal Sheet (SwfitUI)
//
// ContentView.swift
// bottom-sheet
//
// Created by Sean Perkins on 3/22/22.
//
import SwiftUI
struct ContentView: View {
var body: some View {
Home()
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
struct Home: View {
@State var showSheet: Bool = false
var body: some View {
NavigationView {
Button {
showSheet.toggle()
} label: {
Text("Present Sheet")
}
.navigationTitle("Modal Sheet")
.halfSheet(showSheet: $showSheet) {
ZStack {
Color.red
VStack {
Text("Hello World")
.font(.title.bold())
.foregroundColor(.white)
Button {
showSheet.toggle()
} label: {
Text("Dismiss")
.foregroundColor(.white)
}
.padding()
}
}
.ignoresSafeArea()
} onEnd: {
print("Dismissed")
}
}
}
}
extension View {
func halfSheet<SheetView: View>(showSheet: Binding<Bool>, @ViewBuilder sheetView: @escaping ()->SheetView, onEnd: @escaping ()->())->some View {
return self
.background(
HalfSheetHelper(sheetView: sheetView(), showSheet: showSheet, onEnd: onEnd)
)
}
}
struct HalfSheetHelper<SheetView: View>: UIViewControllerRepresentable {
var sheetView: SheetView
@Binding var showSheet: Bool
var onEnd: () ->()
let controller = UIViewController()
func makeCoordinator()-> Coordinator {
return Coordinator(parent: self)
}
func makeUIViewController(context: Context) -> UIViewController {
controller.view.backgroundColor = .clear
return controller
}
func updateUIViewController(_ uiViewControlller: UIViewController, context: Context) {
if showSheet {
let sheetController = CustomHostingController(rootView: sheetView)
sheetController.presentationController?.delegate = context.coordinator
uiViewControlller.present(sheetController, animated: true)
} else {
uiViewControlller.dismiss(animated: true)
}
}
class Coordinator: NSObject, UISheetPresentationControllerDelegate {
var parent: HalfSheetHelper
init (parent: HalfSheetHelper) {
self.parent = parent
}
func presentationControllerDidDismiss(_ presentationController: UIPresentationController) {
parent.showSheet = false
parent.onEnd()
}
}
}
class CustomHostingController<Content: View>: UIHostingController<Content> {
override func viewDidLoad() {
view.backgroundColor = .clear
if let presentationController = presentationController as? UISheetPresentationController {
presentationController.detents = [
.medium(),
.large()
]
presentationController.prefersGrabberVisible = true
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment