Skip to content

Instantly share code, notes, and snippets.

@wassupdoc
Last active May 7, 2021 04:45
Show Gist options
  • Save wassupdoc/67c2f36cbe335b521531dfef0a9d1f8b to your computer and use it in GitHub Desktop.
Save wassupdoc/67c2f36cbe335b521531dfef0a9d1f8b to your computer and use it in GitHub Desktop.
SwiftUI Popover
class PopupViewController:UIViewController{
let frame:CGRect
let content:AnyView
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewDidLoad() {
super.viewDidLoad()
createPopup()
}
func createPopup(){
let hostingViewController = UIHostingController(rootView: content)
hostingViewController.modalPresentationStyle = .popover
hostingViewController.popoverPresentationController?.delegate = self
hostingViewController.popoverPresentationController?.sourceView = self.view
hostingViewController.popoverPresentationController?.sourceRect = frame
hostingViewController.view.backgroundColor = nil
// need to manually set preferredContentSize for the popover
// but thankfully we can use sizeThatFits(:) to force the SwiftUI view to size itself
let popoverMaxSize = CGSize(width: 250, height: 500)
hostingViewController.preferredContentSize = hostingViewController.sizeThatFits(in: popoverMaxSize)
}
init(frame:CGRect,content:AnyView) {
self.frame = frame
self.content = content
super.init(nibName: nil, bundle:nil)
}
}
extension PopupViewController: UIPopoverPresentationControllerDelegate {
func adaptivePresentationStyle(for controller: UIPresentationController) -> UIModalPresentationStyle {
return .none // this is what forces popovers on iPhone
}
}
struct PopupRepresentation:UIViewControllerRepresentable{
var frame:CGRect
var view:AnyView
func makeUIViewController(context: Context) -> UIViewController {
let vc = PopupViewController(frame: frame, content:view)
return vc
}
func updateUIViewController(_ uiViewController: UIViewController, context: Context) {
print("update")
}
typealias UIViewControllerType = UIViewController
}
struct ContentView: View {
typealias PopoverPresenter = (CGRect, AnyView) -> Void
var showPopover: PopoverPresenter?
var body: some View {
VStack {
Spacer()
MeasuredButton(action: { frame in
let view = PopoverView(text: "This popover has determined its size based on its content and appears to be presented from a SwiftUI button.")
self.showPopover?(frame, AnyView(view))
}) {
Text("Show Popover")
}
}.padding()
}
}
struct PopoverView: View {
@State var text:String
var body: some View {
Text(text)
.padding()
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment