123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130 |
- //
- // UIViewController+LayoutHelper.m
- // HWPanModal
- //
- // Created by heath wang on 2019/4/26.
- //
- #import "UIViewController+LayoutHelper.h"
- #import "HWPanModalPresentationController.h"
- #import "UIViewController+PanModalDefault.h"
- @implementation UIViewController (LayoutHelper)
- - (CGFloat)topLayoutOffset {
- if (@available(iOS 11, *)) {
- return [UIApplication sharedApplication].keyWindow.safeAreaInsets.top;
- } else {
- return [UIApplication sharedApplication].keyWindow.rootViewController.topLayoutGuide.length;
- }
-
- }
- - (CGFloat)bottomLayoutOffset {
- if (@available(iOS 11, *)) {
- return [UIApplication sharedApplication].keyWindow.safeAreaInsets.bottom;
- } else {
- return [UIApplication sharedApplication].keyWindow.rootViewController.bottomLayoutGuide.length;
- }
- }
- - (HWPanModalPresentationController *)hw_presentedVC {
- /*
- * Fix iOS13 bug: if we access presentationController before present VC, this will lead `modalPresentationStyle` not working.
- * refer to: https://github.com/HeathWang/HWPanModal/issues/27
- * Apple Doc: If you have not yet presented the current view controller, accessing this property creates a presentation controller based on the current value in the modalPresentationStyle property.
- */
-
- /**
- * fix bug: https://github.com/HeathWang/HWPanModal/issues/37
- */
- if (self.presentingViewController) {
- return [self hw_getPanModalPresentationController];
- } else {
- return nil;
- }
- }
- - (HWPanModalPresentationController *)hw_getPanModalPresentationController {
- UIViewController *ancestorsVC;
-
- // seeking for the root presentation VC.
- if (self.splitViewController) {
- ancestorsVC = self.splitViewController;
- } else if (self.navigationController) {
- ancestorsVC = self.navigationController;
- } else if (self.tabBarController) {
- ancestorsVC = self.tabBarController;
- } else {
- ancestorsVC = self;
- }
-
- if ([ancestorsVC.presentationController isMemberOfClass:HWPanModalPresentationController.class]) {
- return (HWPanModalPresentationController *) ancestorsVC.presentationController;
- }
- return nil;
- }
- /**
- Returns the short form Y postion
- - 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.
- */
- - (CGFloat)shortFormYPos {
- if (UIAccessibilityIsVoiceOverRunning()) {
- return self.longFormYPos;
- } else {
- CGFloat shortFormYPos = [self topMarginFromPanModalHeight:[self shortFormHeight]] + [self topOffset];
- return MAX(shortFormYPos, self.longFormYPos);
- }
- }
- - (CGFloat)mediumFormYPos {
- if (UIAccessibilityIsVoiceOverRunning()) {
- return self.longFormYPos;
- } else {
- CGFloat mediumFormYPos = [self topMarginFromPanModalHeight:[self mediumFormHeight]] + [self topOffset];
- return MAX(mediumFormYPos, self.longFormYPos);
- }
- }
- - (CGFloat)longFormYPos {
- return MAX([self topMarginFromPanModalHeight:[self longFormHeight]], [self topMarginFromPanModalHeight:PanModalHeightMake(PanModalHeightTypeMax, 0)]) + [self topOffset];
- }
- /**
- * Use the container view for relative positioning as this view's frame
- is adjusted in PanModalPresentationController
- */
- - (CGFloat)bottomYPos {
- if (self.hw_presentedVC.containerView) {
- return self.hw_presentedVC.containerView.bounds.size.height - [self topOffset];
- }
- return self.view.bounds.size.height;
- }
- - (CGFloat)topMarginFromPanModalHeight:(PanModalHeight)panModalHeight {
- switch (panModalHeight.heightType) {
- case PanModalHeightTypeMax:
- return 0.0f;
- case PanModalHeightTypeMaxTopInset:
- return panModalHeight.height;
- case PanModalHeightTypeContent:
- return self.bottomYPos - (panModalHeight.height + self.bottomLayoutOffset);
- case PanModalHeightTypeContentIgnoringSafeArea:
- return self.bottomYPos - panModalHeight.height;
- case PanModalHeightTypeIntrinsic:
- {
- [self.view layoutIfNeeded];
- CGSize targetSize = CGSizeMake(self.hw_presentedVC.containerView ? self.hw_presentedVC.containerView.bounds.size.width : [UIScreen mainScreen].bounds.size.width, UILayoutFittingCompressedSize.height);
- CGFloat intrinsicHeight = [self.view systemLayoutSizeFittingSize:targetSize].height;
- return self.bottomYPos - (intrinsicHeight + self.bottomLayoutOffset);
- }
- default:
- return 0;
- }
- }
- @end
|