testing not using popover viewcontroller
Signed-off-by: Matt Bruce <matt.bruce@verizon.com>
This commit is contained in:
parent
ce6aad5540
commit
aad70d2e40
@ -19,6 +19,10 @@ open class ClearPopoverViewController: UIViewController, UIPopoverPresentationCo
|
||||
/// 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.
|
||||
@ -35,6 +39,7 @@ open class ClearPopoverViewController: UIViewController, UIPopoverPresentationCo
|
||||
self.contentView = contentView
|
||||
self.spacing = spacing
|
||||
self.arrow = arrow
|
||||
self.sourceRect = sourceRect
|
||||
super.init(nibName: nil, bundle: nil)
|
||||
setupPopover(sourceView, sourceRect, barButtonItem)
|
||||
}
|
||||
@ -65,7 +70,6 @@ open class ClearPopoverViewController: UIViewController, UIPopoverPresentationCo
|
||||
popOver.popoverBackgroundViewClass = ClearPopoverBackgroundView.self
|
||||
popOver.sourceView = sourceView
|
||||
popOver.popoverLayoutMargins = .zero
|
||||
|
||||
if let sourceRect = sourceRect {
|
||||
popOver.sourceRect = sourceRect
|
||||
}
|
||||
@ -85,11 +89,8 @@ open class ClearPopoverViewController: UIViewController, UIPopoverPresentationCo
|
||||
|
||||
private func updatePopoverPosition() {
|
||||
guard let popoverPresentationController = popoverPresentationController else { return }
|
||||
if let sourceView = popoverPresentationController.sourceView {
|
||||
popoverPresentationController.sourceRect = .init(x: sourceView.bounds.origin.x,
|
||||
y: sourceView.bounds.origin.y,
|
||||
width: sourceView.bounds.width,
|
||||
height: sourceView.bounds.height + spacing)
|
||||
if let sourceView = popoverPresentationController.sourceView, let sourceRect {
|
||||
popoverPresentationController.sourceRect = sourceRect
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -117,10 +117,11 @@ open class DatePicker: EntryFieldBase {
|
||||
|
||||
NotificationCenter.default
|
||||
.publisher(for: UIDevice.orientationDidChangeNotification).sink { [weak self] _ in
|
||||
guard let self, let popoverController else { return }
|
||||
popoverController.dismiss(animated: true){ [weak self] in
|
||||
guard let self else { return }
|
||||
popoverController?.dismiss(animated: true){ [weak self] in
|
||||
guard let self else { return }
|
||||
}
|
||||
hidePopoverView()
|
||||
}
|
||||
.store(in: &subscribers)
|
||||
|
||||
@ -163,7 +164,7 @@ open class DatePicker: EntryFieldBase {
|
||||
selectedDateLabel.text = formatter.string(from: date)
|
||||
}
|
||||
|
||||
internal var popoverController: UIViewController?
|
||||
internal var popoverController: ClearPopoverViewController?
|
||||
|
||||
func didSelect(_ date: Date) {
|
||||
selectedDate = date
|
||||
@ -175,34 +176,179 @@ open class DatePicker: EntryFieldBase {
|
||||
}
|
||||
}
|
||||
|
||||
internal func togglePicker() {
|
||||
let calendar = CalendarBase()
|
||||
calendar.activeDates = calendarModel.activeDates
|
||||
calendar.hideContainerBorder = calendarModel.hideContainerBorder
|
||||
calendar.hideCurrentDateIndicator = calendarModel.hideCurrentDateIndicator
|
||||
calendar.inactiveDates = calendarModel.inactiveDates
|
||||
calendar.indicators = calendarModel.indicators
|
||||
calendar.maxDate = calendarModel.maxDate
|
||||
calendar.minDate = calendarModel.minDate
|
||||
calendar.surface = calendarModel.surface
|
||||
calendar.setNeedsLayout()
|
||||
calendar.layoutIfNeeded()
|
||||
calendar.onChange = { [weak self] control in
|
||||
guard let self else { return }
|
||||
didSelect(control.selectedDate)
|
||||
}
|
||||
private var overlayView = UIView().with {
|
||||
$0.backgroundColor = .clear;
|
||||
$0.isHidden = true
|
||||
}
|
||||
private var popoverView: UIView!
|
||||
private var popoverVisible = false
|
||||
private var outsideTapGesture: UITapGestureRecognizer?
|
||||
private var outsidePanGesture: UIPanGestureRecognizer?
|
||||
|
||||
// internal func togglePicker() {
|
||||
// calendar.activeDates = calendarModel.activeDates
|
||||
// calendar.hideContainerBorder = calendarModel.hideContainerBorder
|
||||
// calendar.hideCurrentDateIndicator = calendarModel.hideCurrentDateIndicator
|
||||
// calendar.inactiveDates = calendarModel.inactiveDates
|
||||
// calendar.indicators = calendarModel.indicators
|
||||
// calendar.maxDate = calendarModel.maxDate
|
||||
// calendar.minDate = calendarModel.minDate
|
||||
// calendar.surface = calendarModel.surface
|
||||
// calendar.setNeedsLayout()
|
||||
// calendar.layoutIfNeeded()
|
||||
// calendar.onChange = { [weak self] control in
|
||||
// guard let self else { return }
|
||||
// didSelect(control.selectedDate)
|
||||
// }
|
||||
//
|
||||
// popoverController = ClearPopoverViewController(contentView: calendar,
|
||||
// arrow: .any,
|
||||
// sourceView: containerView,
|
||||
// sourceRect: .init(x: 0, y: 0, width: 320, height: 45),
|
||||
// spacing: VDSLayout.space1X)
|
||||
// popoverController?.maxWidth = 320
|
||||
// if let viewController = UIApplication.topViewController(), let popoverController {
|
||||
// viewController.present(popoverController,
|
||||
// animated: true,
|
||||
// completion: nil)
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
extension DatePicker {
|
||||
|
||||
private func togglePicker() {
|
||||
guard let viewController = UIApplication.topViewController(), let parentView = viewController.view else { return }
|
||||
|
||||
if popoverVisible {
|
||||
hidePopoverView()
|
||||
} else {
|
||||
let calendar = CalendarBase()
|
||||
calendar.activeDates = calendarModel.activeDates
|
||||
calendar.hideContainerBorder = calendarModel.hideContainerBorder
|
||||
calendar.hideCurrentDateIndicator = calendarModel.hideCurrentDateIndicator
|
||||
calendar.inactiveDates = calendarModel.inactiveDates
|
||||
calendar.indicators = calendarModel.indicators
|
||||
calendar.maxDate = calendarModel.maxDate
|
||||
calendar.minDate = calendarModel.minDate
|
||||
calendar.surface = calendarModel.surface
|
||||
calendar.setNeedsLayout()
|
||||
calendar.layoutIfNeeded()
|
||||
calendar.onChange = { [weak self] control in
|
||||
guard let self else { return }
|
||||
selectedDate = control.selectedDate
|
||||
sendActions(for: .valueChanged)
|
||||
UIAccessibility.post(notification: .layoutChanged, argument: containerView)
|
||||
hidePopoverView()
|
||||
}
|
||||
|
||||
outsideTapGesture = UITapGestureRecognizer()
|
||||
outsidePanGesture = UIPanGestureRecognizer()
|
||||
|
||||
overlayView.publisher(for: outsideTapGesture!).sink { [weak self] _ in
|
||||
guard let self else { return }
|
||||
hidePopoverView()
|
||||
}.store(in: &subscribers)
|
||||
parentView.publisher(for: outsidePanGesture!).sink { [weak self] _ in
|
||||
guard let self else { return }
|
||||
hidePopoverView()
|
||||
}.store(in: &subscribers)
|
||||
|
||||
overlayView.frame = parentView.bounds
|
||||
overlayView.isHidden = false
|
||||
|
||||
parentView.addSubview(overlayView)
|
||||
|
||||
popoverView = UIView()
|
||||
popoverView.backgroundColor = .white
|
||||
popoverView.layer.cornerRadius = 10
|
||||
popoverView.layer.shadowColor = UIColor.black.cgColor
|
||||
popoverView.layer.shadowOpacity = 0.2
|
||||
popoverView.layer.shadowOffset = CGSize(width: 0, height: 5)
|
||||
popoverView.layer.shadowRadius = 10
|
||||
popoverView.isHidden = true
|
||||
popoverView.addSubview(calendar)
|
||||
calendar.pinToSuperView()
|
||||
popoverView.translatesAutoresizingMaskIntoConstraints = false
|
||||
parentView.addSubview(popoverView)
|
||||
|
||||
popoverView.width(calendar.frame.width)
|
||||
popoverView.height(calendar.frame.height)
|
||||
|
||||
let spacing: CGFloat = 4
|
||||
let (popoverX, popoverY) = calculatePopoverPosition(relativeTo: containerView, in: parentView, size: calendar.frame.size, with: spacing)
|
||||
popoverView.leadingAnchor.constraint(equalTo: parentView.leadingAnchor, constant: popoverX).isActive = true
|
||||
popoverView.topAnchor.constraint(equalTo: parentView.topAnchor, constant: popoverY).isActive = true
|
||||
|
||||
parentView.layoutIfNeeded()
|
||||
popoverView.alpha = 0
|
||||
popoverView.transform = CGAffineTransform(scaleX: 0.9, y: 0.9)
|
||||
popoverView.isHidden = false
|
||||
popoverVisible = true
|
||||
|
||||
popoverController = ClearPopoverViewController(contentView: calendar,
|
||||
arrow: .up,
|
||||
sourceView: containerView,
|
||||
sourceRect: containerView.bounds,
|
||||
spacing: VDSLayout.space1X)
|
||||
|
||||
if let viewController = UIApplication.topViewController(), let popoverController {
|
||||
viewController.present(popoverController,
|
||||
animated: true,
|
||||
completion: nil)
|
||||
UIView.animate(withDuration: 0.3, delay: 0, usingSpringWithDamping: 0.8, initialSpringVelocity: 0.2, options: .curveEaseOut, animations: { [weak self] in
|
||||
guard let self else { return }
|
||||
popoverView.alpha = 1
|
||||
popoverView.transform = CGAffineTransform.identity
|
||||
parentView.layoutIfNeeded()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
private func hidePopoverView() {
|
||||
overlayView.isHidden = true
|
||||
overlayView.removeFromSuperview()
|
||||
|
||||
outsideTapGesture = nil
|
||||
outsidePanGesture = nil
|
||||
UIView.animate(withDuration: 0.2, animations: {
|
||||
self.popoverView.alpha = 0
|
||||
self.popoverView.transform = CGAffineTransform(scaleX: 0.9, y: 0.9)
|
||||
}) { _ in
|
||||
self.popoverView.isHidden = true
|
||||
self.popoverView.removeFromSuperview()
|
||||
self.popoverVisible = false
|
||||
}
|
||||
}
|
||||
|
||||
private func calculatePopoverPosition(relativeTo sourceView: UIView, in parentView: UIView, size: CGSize, with spacing: CGFloat) -> (CGFloat, CGFloat) {
|
||||
let sourceFrameInParent = sourceView.convert(sourceView.bounds, to: parentView)
|
||||
let parentBounds = parentView.bounds
|
||||
let popoverWidth: CGFloat = size.width
|
||||
let popoverHeight: CGFloat = size.height
|
||||
|
||||
var popoverX: CGFloat = 0
|
||||
var popoverY: CGFloat = 0
|
||||
|
||||
// Calculate horizontal position
|
||||
if sourceFrameInParent.width < popoverWidth {
|
||||
if sourceFrameInParent.midX - popoverWidth / 2 < 0 {
|
||||
// Align to left
|
||||
popoverX = sourceFrameInParent.minX
|
||||
} else if sourceFrameInParent.midX + popoverWidth / 2 > parentBounds.width {
|
||||
// Align to right
|
||||
popoverX = sourceFrameInParent.maxX - popoverWidth
|
||||
} else {
|
||||
// Center on source view
|
||||
popoverX = sourceFrameInParent.midX - popoverWidth / 2
|
||||
}
|
||||
} else {
|
||||
popoverX = sourceFrameInParent.midX - popoverWidth / 2
|
||||
}
|
||||
|
||||
// Calculate vertical position
|
||||
if sourceFrameInParent.origin.y > parentBounds.height / 2 {
|
||||
// Show above
|
||||
popoverY = sourceFrameInParent.minY - popoverHeight - spacing
|
||||
} else {
|
||||
// Show below
|
||||
popoverY = sourceFrameInParent.maxY + spacing
|
||||
}
|
||||
|
||||
// Ensure the popover is within the parent's bounds
|
||||
popoverX = max(0, min(popoverX, parentBounds.width - popoverWidth))
|
||||
|
||||
return (popoverX, popoverY)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user