Last active
June 30, 2021 07:17
-
-
Save donnywals/3058ed489e35524dacfede1a3cc765ff to your computer and use it in GitHub Desktop.
This file contains 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 UIKit | |
import SwiftUI | |
// Hacky workaround, use at your own risk and all that | |
struct BottomSheetPresenter<Content>: UIViewRepresentable where Content: View{ | |
let label: String | |
let content: Content | |
let detents: [UISheetPresentationController.Detent] | |
init(_ label: String, detents: [UISheetPresentationController.Detent], @ViewBuilder content: () -> Content) { | |
self.label = label | |
self.content = content() | |
self.detents = detents | |
} | |
func makeUIView(context: UIViewRepresentableContext<BottomSheetPresenter>) -> UIButton { | |
let button = UIButton(type: .system) | |
button.setTitle(label, for: .normal) | |
button.addAction(UIAction { _ in | |
let hostingController = UIHostingController(rootView: content) | |
let viewController = UIBottomSheetWrapper(detents: detents) | |
viewController.addChild(hostingController) | |
viewController.view.addSubview(hostingController.view) | |
hostingController.view.pinToEdgesOf(viewController.view) | |
hostingController.didMove(toParent: viewController) | |
button.window?.rootViewController?.present(viewController, animated: true) | |
}, for: .touchUpInside) | |
print("make...") | |
return button | |
} | |
func updateUIView(_ uiView: UIButton, context: Context) { | |
// no updates | |
} | |
func makeCoordinator() -> Void { | |
return () | |
} | |
} | |
extension BottomSheetPresenter { | |
class UIBottomSheetWrapper: UIViewController { | |
let detents: [UISheetPresentationController.Detent] | |
init(detents: [UISheetPresentationController.Detent]) { | |
self.detents = detents | |
super.init(nibName: nil, bundle: nil) | |
} | |
required init?(coder: NSCoder) { | |
fatalError("No Storyboards") | |
} | |
override func viewDidLoad() { | |
super.viewDidLoad() | |
view.backgroundColor = .gray | |
if let sheetController = self.presentationController as? UISheetPresentationController { | |
sheetController.detents = detents | |
} | |
} | |
} | |
} | |
extension UIView { | |
func pinToEdgesOf(_ other: UIView) { | |
translatesAutoresizingMaskIntoConstraints = false | |
leftAnchor.constraint(equalTo: other.leftAnchor).isActive = true | |
topAnchor.constraint(equalTo: other.topAnchor).isActive = true | |
rightAnchor.constraint(equalTo: other.rightAnchor).isActive = true | |
bottomAnchor.constraint(equalTo: other.bottomAnchor).isActive = true | |
} | |
} | |
// Usage | |
struct ContentView: View { | |
var body: some View { | |
VStack { | |
BottomSheetPresenter("Tap me for a bottom sheet!!", detents: [.medium(), .large()]) { | |
VStack { | |
Text("This is a test") | |
Rectangle() | |
.frame(width: 300, height: 300, alignment: .leading) | |
.foregroundColor(.blue) | |
} | |
} | |
} | |
} | |
} |
Thanks! 😁 I'll modify the gist to use your suggestion
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
UIApplication.shared.windows.first?.rootViewController?.present
wouldn't work as intended for apps with multiple scenes,button.window?.rootViewController?.present
should work better (the button's window will be set at the time the button is tapped)That's the only "hacky" thing I see here, the rest looks good to me!