PanModal/PanModal/Presentable/PanModalPresentable+LayoutH...

103 lines
3.2 KiB
Swift
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// PanModalPresentable+LayoutHelpers.swift
// PanModal
//
// Copyright © 2018 Tiny Speck, Inc. All rights reserved.
//
import UIKit
/**
[Internal Only]
Helper extensions that handle layout in the PanModalPresentationController
*/
extension PanModalPresentable where Self: UIViewController {
/**
Cast the presentation controller to PanModalPresentationController
so we can access PanModalPresentationController properties and methods
*/
var presentedVC: PanModalPresentationController? {
return presentationController as? PanModalPresentationController
}
/**
Length of the top layout guide of the presenting view controller.
Gives us the safe area inset from the top.
*/
var topLayoutOffset: CGFloat {
return UIApplication.shared.keyWindow?.rootViewController?.topLayoutGuide.length ?? 0
}
/**
Length of the bottom layout guide of the presenting view controller.
Gives us the safe area inset from the bottom.
*/
var bottomLayoutOffset: CGFloat {
return UIApplication.shared.keyWindow?.rootViewController?.bottomLayoutGuide.length ?? 0
}
/**
Returns the short form Y position
- Note: If voiceover is on, the `longFormYPos` is returned.
We do not support short form when voiceover is on as it would make it difficult for user to navigate.
*/
var shortFormYPos: CGFloat {
guard !UIAccessibility.isVoiceOverRunning
else { return longFormYPos }
let shortFormYPos = topMargin(from: shortFormHeight) + topOffset
// shortForm shouldn't exceed longForm
return max(shortFormYPos, longFormYPos)
}
/**
Returns the long form Y position
- Note: We cap this value to the max possible height
to ensure content is not rendered outside of the view bounds
*/
var longFormYPos: CGFloat {
return max(topMargin(from: longFormHeight), topMargin(from: .maxHeight)) + topOffset
}
/**
Use the container view for relative positioning as this view's frame
is adjusted in PanModalPresentationController
*/
var bottomYPos: CGFloat {
guard let container = presentedVC?.containerView
else { return view.bounds.height }
return container.bounds.size.height - topOffset
}
/**
Converts a given pan modal height value into a y position value
calculated from top of view
*/
func topMargin(from: PanModalHeight) -> CGFloat {
switch from {
case .maxHeight:
return 0.0
case .maxHeightWithTopInset(let inset):
return inset
case .contentHeight(let height):
return bottomYPos - (height + bottomLayoutOffset)
case .contentHeightIgnoringSafeArea(let height):
return bottomYPos - height
case .intrinsicHeight:
view.layoutIfNeeded()
let targetSize = CGSize(width: (presentedVC?.containerView?.bounds ?? UIScreen.main.bounds).width,
height: UIView.layoutFittingCompressedSize.height)
let intrinsicHeight = view.systemLayoutSizeFitting(targetSize).height
return bottomYPos - (intrinsicHeight + bottomLayoutOffset)
}
}
}