Instantly share code, notes, and snippets.
Last active
July 27, 2020 06:55
-
Save yoni-g/14c20051d0eac16eaa8ce754ca80c538 to your computer and use it in GitHub Desktop.
How to present a popup menu in iOS?
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
// | |
// MenuOption.swift | |
// | |
struct MenuOption { | |
var title: String = "" | |
var image: UIImage | |
var action: (()->()) | |
init(title: String, image: UIImage, action: @escaping (()->())) { | |
self.title = title | |
self.image = image | |
self.action = action | |
} | |
} |
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
// | |
// PopoverMenu.swift | |
// | |
import UIKit | |
class PopoverMenuController: UITableViewController { | |
static let MENU_CELL_HEIGHT = 45 | |
var menuOptions: [MenuOption]? | |
override func viewDidLoad() { | |
super.viewDidLoad() | |
} | |
override func viewWillAppear(_ animated: Bool) { | |
super.viewWillAppear(animated) | |
self.view.alpha = 0 | |
self.popoverPresentationController?.containerView?.alpha = 0 | |
} | |
override func viewDidAppear(_ animated: Bool) { | |
super.viewDidAppear(animated) | |
UIView.animate(withDuration: 0.2, delay: 0.0, options: .beginFromCurrentState, animations: { | |
self.view.alpha = 1 | |
self.popoverPresentationController?.containerView?.alpha = 1 | |
}, completion: nil) | |
} | |
override func didReceiveMemoryWarning() { | |
super.didReceiveMemoryWarning() | |
// Dispose of any resources that can be recreated. | |
} | |
// MARK: - Table view data source | |
override func numberOfSections(in tableView: UITableView) -> Int { | |
// #warning Incomplete implementation, return the number of sections | |
return 1 | |
} | |
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { | |
// #warning Incomplete implementation, return the number of rows | |
return menuOptions!.count | |
} | |
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { | |
return CGFloat(PopoverMenuController.MENU_CELL_HEIGHT) | |
} | |
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { | |
let cell = tableView.dequeueReusableCell(withIdentifier: "popoverMenuCell", for: indexPath) as! PopoverMenuCell | |
cell.title.text = menuOptions![indexPath.row].title.localized | |
cell.img.image = menuOptions![indexPath.row].image | |
return cell | |
} | |
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { | |
menuOptions![indexPath.row].action() | |
self.dismiss(animated: false, completion: nil) | |
} | |
} |
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
// | |
// PopoverMenuCell.swift | |
// | |
import UIKit | |
class PopoverMenuCell: UITableViewCell { | |
@IBOutlet weak var title: UILabel! | |
@IBOutlet weak var img: UIImageView! | |
override func awakeFromNib() { | |
super.awakeFromNib() | |
// Initialization code | |
} | |
override func setSelected(_ selected: Bool, animated: Bool) { | |
super.setSelected(selected, animated: animated) | |
// Configure the view for the selected state | |
} | |
} |
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
class PopoverUtils { | |
static func showPopoverMenu(_ sourceViewController: UIViewController, source: UIView, presentationDelegate: UIPopoverPresentationControllerDelegate, menuOptions: [MenuOption]) { | |
let vc = UIStoryboard(name: "Popover", bundle: Bundle.main).instantiateViewController(withIdentifier: "popoverMenuController") as! PopoverMenuController | |
vc.menuOptions = menuOptions | |
vc.modalPresentationStyle = .popover | |
vc.preferredContentSize = CGSize(width: 175, height: PopoverMenuController.MENU_CELL_HEIGHT * menuOptions.count) | |
if let presentationController = vc.popoverPresentationController { | |
presentationController.delegate = presentationDelegate | |
presentationController.backgroundColor = UIColor(hex: 0xEAEAEA) | |
presentationController.permittedArrowDirections = UIScreen.main.bounds.height - (source.superview?.convert(source.frame.origin, to: nil).y)! < 150 ? .down : .up | |
presentationController.sourceView = source | |
presentationController.sourceRect = source.bounds | |
sourceViewController.present(vc, animated: true, completion: { | |
vc.view.superview?.layer.cornerRadius = 0 | |
}) | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Example of how to use: