Skip to content

Instantly share code, notes, and snippets.

@mhijack
Last active April 28, 2021 06:29
Show Gist options
  • Save mhijack/b67c28a6a44e300bcfbadb1bec60c7fe to your computer and use it in GitHub Desktop.
Save mhijack/b67c28a6a44e300bcfbadb1bec60c7fe to your computer and use it in GitHub Desktop.
class HomeOptionsManager: NSObject, OptionsManager {
/// Use private(set) to mark the setter private
private(set) var options: [String]
private let TABLE_CELL_HEIGHT: CGFloat = 44
private var tableViewHeight: CGFloat {
return TABLE_CELL_HEIGHT * CGFloat(options.count) + (UIApplication.shared.windows.first?.safeAreaInsets.bottom ?? 0) /// Taking into account the bottom safe area for full-screen iphones
}
/// Views
private var backgroundView: UIView?
private var optionsView: UITableView?
/// Action handler
public var optionsDidOpen: (() -> ())?
public var optionsDidDismiss: (() -> ())?
public var didSelectOption: ((String) -> ())?
init(options: [String] = []) {
self.options = options
}
/// Configures options view and add to screen
public func showOptions() {
guard backgroundView == nil else { return }
guard let window = UIApplication.shared.windows.first else { return }
/// The background view that covers the entire screen
let backgroundView = UIView(frame: window.bounds)
backgroundView.backgroundColor = .black
backgroundView.alpha = 0
window.subviews(backgroundView)
backgroundView.fillContainer()
/// The actual clickable options table view
let optionsTableView = UITableView(frame: .zero, style: .plain)
optionsTableView.isScrollEnabled = false
optionsTableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
optionsTableView.delegate = self
optionsTableView.dataSource = self
backgroundView.subviews(optionsTableView)
optionsTableView
.height(tableViewHeight)
.leading(0)
.trailing(0)
optionsTableView.Width == backgroundView.Width
optionsTableView.Bottom == backgroundView.Bottom + tableViewHeight
optionsTableView.backgroundColor = .white
optionsTableView.alpha = 1
let backgroundTapGesture = UITapGestureRecognizer(target: self, action: #selector(didTapBackground))
backgroundView.isUserInteractionEnabled = true
/// Ensures the tap is passed on to its subviews
backgroundTapGesture.cancelsTouchesInView = false
backgroundView.addGestureRecognizer(backgroundTapGesture)
self.backgroundView = backgroundView
self.optionsView = optionsTableView
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
optionsTableView.bottomConstraint?.constant = 0
UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 0.8, initialSpringVelocity: 0.8, animations: {
/// Introduces half alpha and forces a layout pass
backgroundView.alpha = 0.5
backgroundView.layoutIfNeeded()
}) { (complete) in
self.optionsDidOpen?()
}
}
}
/// Dismiss background view and options view when background is tapped
@objc private func didTapBackground() {
dismiss()
}
}
extension HomeOptionsManager {
/// Dismiss options view
private func dismiss() {
self.optionsView?.bottomConstraint?.constant = tableViewHeight
UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 0.8, initialSpringVelocity: 0.8, animations: {
self.backgroundView?.alpha = 0
self.backgroundView?.layoutIfNeeded()
}) { (complete) in
self.backgroundView?.removeFromSuperview()
self.backgroundView = nil
self.optionsDidDismiss?()
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment