Hibit_iOS/Pods/HWPanModal/Sources/Presentable/UIViewController+LayoutHelper.m
2024-06-07 11:41:02 +08:00

131 lines
4.4 KiB
Objective-C

//
// 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