154 lines
5.5 KiB
Swift
154 lines
5.5 KiB
Swift
//
|
||
// DatePickerPopoverViewController.swift
|
||
// VDS
|
||
//
|
||
// Created by Matt Bruce on 5/14/24.
|
||
//
|
||
|
||
import Foundation
|
||
import UIKit
|
||
|
||
@objc(VDSClearPopoverViewController)
|
||
open class ClearPopoverViewController: UIViewController, UIPopoverPresentationControllerDelegate {
|
||
|
||
/// The view to be inserted inside the popover
|
||
private var contentView: UIView!
|
||
|
||
/// An object representing the arrow of the popover.
|
||
private var arrow: UIPopoverArrowDirection
|
||
|
||
/// Popover presentation controller of the popover
|
||
private var popOver: UIPopoverPresentationController!
|
||
|
||
open var maxWidth: CGFloat?
|
||
|
||
open var sourceRect: CGRect?
|
||
|
||
open var spacing: CGFloat = 0
|
||
/**
|
||
A controller that manages the popover.
|
||
- Parameter contentView: The view to be inserted inside the popover.
|
||
- Parameter design: An object used for defining visual attributes of the popover.
|
||
- Parameter arrow: An object representing the arrow in popover.
|
||
- Parameter sourceView: The view containing the anchor rectangle for the popover.
|
||
- Parameter sourceRect: The rectangle in the specified view in which to anchor the popover.
|
||
- Parameter barButtonItem: The bar button item on which to anchor the popover.
|
||
|
||
Assign a value to `barButton` to anchor the popover to the specified bar button item. When presented, the popover’s arrow points to the specified item. Alternatively, you may specify the anchor location for the popover using the `sourceView` and `sourceRect` properties.
|
||
*/
|
||
public init(contentView: UIView, arrow: UIPopoverArrowDirection, sourceView: UIView? = nil, sourceRect: CGRect? = nil, spacing: CGFloat = 0, barButtonItem: UIBarButtonItem? = nil) {
|
||
self.contentView = contentView
|
||
self.spacing = spacing
|
||
self.arrow = arrow
|
||
self.sourceRect = sourceRect
|
||
super.init(nibName: nil, bundle: nil)
|
||
setupPopover(sourceView, sourceRect, barButtonItem)
|
||
}
|
||
|
||
required public init?(coder aDecoder: NSCoder) {
|
||
fatalError("init(coder:) has not been implemented")
|
||
}
|
||
|
||
open override func viewIsAppearing(_ animated: Bool) {
|
||
super.viewIsAppearing(animated)
|
||
view.superview?.accessibilityIdentifier = "HadCornerRadius"
|
||
view.accessibilityIdentifier = "PopoverViewController.View"
|
||
contentView.accessibilityIdentifier = "PopoverViewController.ContentView"
|
||
view.superview?.layer.cornerRadius = 0
|
||
}
|
||
|
||
open override func viewDidLayoutSubviews() {
|
||
contentView.frame.origin = CGPoint(x: 0, y: 0)
|
||
}
|
||
|
||
///Sets up the Popover and starts the timer for its closing.
|
||
private func setupPopover(_ sourceView: UIView?, _ sourceRect: CGRect?, _ barButtonItem: UIBarButtonItem?) {
|
||
modalPresentationStyle = .popover
|
||
view.addSubview(contentView)
|
||
|
||
popOver = self.popoverPresentationController!
|
||
popOver.popoverLayoutMargins = .zero
|
||
popOver.popoverBackgroundViewClass = ClearPopoverBackgroundView.self
|
||
popOver.sourceView = sourceView
|
||
popOver.popoverLayoutMargins = .zero
|
||
if let sourceRect = sourceRect {
|
||
popOver.sourceRect = sourceRect
|
||
}
|
||
|
||
popOver.barButtonItem = barButtonItem
|
||
popOver.delegate = self
|
||
popOver.permittedArrowDirections = arrow
|
||
popOver.backgroundColor = .clear
|
||
|
||
}
|
||
|
||
open func popoverPresentationController(_ popoverPresentationController: UIPopoverPresentationController, willRepositionPopoverTo rect: UnsafeMutablePointer<CGRect>, in view: AutoreleasingUnsafeMutablePointer<UIView>) {
|
||
if let presentedView = popoverPresentationController.presentedViewController.view.superview {
|
||
presentedView.layer.cornerRadius = 0
|
||
}
|
||
}
|
||
|
||
private func updatePopoverPosition() {
|
||
guard let popoverPresentationController = popoverPresentationController else { return }
|
||
if let sourceView = popoverPresentationController.sourceView, let sourceRect {
|
||
popoverPresentationController.sourceRect = sourceRect
|
||
}
|
||
}
|
||
|
||
// Ensure to handle rotations
|
||
open override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
|
||
super.viewWillTransition(to: size, with: coordinator)
|
||
coordinator.animate(alongsideTransition: { [weak self] _ in
|
||
self?.updatePopoverPosition()
|
||
})
|
||
}
|
||
|
||
open func adaptivePresentationStyle(for controller: UIPresentationController, traitCollection: UITraitCollection) -> UIModalPresentationStyle {
|
||
return .none
|
||
}
|
||
|
||
// Returns presentation controller of the popover
|
||
open func getPopoverPresentationController() -> UIPopoverPresentationController {
|
||
return popOver
|
||
}
|
||
}
|
||
|
||
open class ClearPopoverBackgroundView: UIPopoverBackgroundView {
|
||
open override var arrowOffset: CGFloat {
|
||
get { 0 }
|
||
set { }
|
||
}
|
||
|
||
open override var arrowDirection: UIPopoverArrowDirection {
|
||
get { .any }
|
||
set { }
|
||
}
|
||
|
||
open override class var wantsDefaultContentAppearance: Bool {
|
||
false
|
||
}
|
||
|
||
open override class func contentViewInsets() -> UIEdgeInsets{
|
||
.zero
|
||
}
|
||
|
||
open override class func arrowHeight() -> CGFloat {
|
||
0
|
||
}
|
||
|
||
open override class func arrowBase() -> CGFloat{
|
||
0
|
||
}
|
||
|
||
open override func layoutSubviews() {
|
||
super.layoutSubviews()
|
||
layer.shadowOpacity = 0
|
||
layer.shadowRadius = 0
|
||
layer.cornerRadius = 0
|
||
}
|
||
|
||
open override func draw(_ rect: CGRect) {
|
||
|
||
}
|
||
}
|