UIViewController+LayoutHelper.m 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. //
  2. // UIViewController+LayoutHelper.m
  3. // HWPanModal
  4. //
  5. // Created by heath wang on 2019/4/26.
  6. //
  7. #import "UIViewController+LayoutHelper.h"
  8. #import "HWPanModalPresentationController.h"
  9. #import "UIViewController+PanModalDefault.h"
  10. @implementation UIViewController (LayoutHelper)
  11. - (CGFloat)topLayoutOffset {
  12. return [UIApplication sharedApplication].keyWindow.rootViewController.topLayoutGuide.length;
  13. }
  14. - (CGFloat)bottomLayoutOffset {
  15. return [UIApplication sharedApplication].keyWindow.rootViewController.bottomLayoutGuide.length;
  16. }
  17. - (HWPanModalPresentationController *)presentedVC {
  18. if ([self.presentationController isKindOfClass:HWPanModalPresentationController.class]) {
  19. return (HWPanModalPresentationController *) self.presentationController;
  20. }
  21. return nil;
  22. }
  23. /**
  24. Returns the short form Y postion
  25. - Note: If voiceover is on, the `longFormYPos` is returned.
  26. We do not support short form when voiceover is on as it would make it difficult for user to navigate.
  27. */
  28. - (CGFloat)shortFormYPos {
  29. if (UIAccessibilityIsVoiceOverRunning()) {
  30. return self.longFormYPos;
  31. } else {
  32. CGFloat shortFormYPos = [self topMarginFromPanModalHeight:[self shortFormHeight]] + [self topOffset];
  33. return MAX(shortFormYPos, self.longFormYPos);
  34. }
  35. }
  36. - (CGFloat)longFormYPos {
  37. return MAX([self topMarginFromPanModalHeight:[self longFormHeight]], [self topMarginFromPanModalHeight:PanModalHeightMake(PanModalHeightTypeMax, 0)]) + [self topOffset];
  38. }
  39. /**
  40. * Use the container view for relative positioning as this view's frame
  41. is adjusted in PanModalPresentationController
  42. */
  43. - (CGFloat)bottomYPos {
  44. if (self.presentedVC.containerView) {
  45. return self.presentedVC.containerView.bounds.size.height - [self topOffset];
  46. }
  47. return self.view.bounds.size.height;
  48. }
  49. - (CGFloat)topMarginFromPanModalHeight:(PanModalHeight)panModalHeight {
  50. switch (panModalHeight.heightType) {
  51. case PanModalHeightTypeMax:
  52. return 0.0f;
  53. case PanModalHeightTypeMaxTopInset:
  54. return panModalHeight.height;
  55. case PanModalHeightTypeContent:
  56. return self.bottomYPos - (panModalHeight.height + self.bottomLayoutOffset);
  57. case PanModalHeightTypeContentIgnoringSafeArea:
  58. return self.bottomYPos - panModalHeight.height;
  59. case PanModalHeightTypeIntrinsic:
  60. {
  61. [self.view layoutIfNeeded];
  62. CGSize targetSize = CGSizeMake(self.presentedVC.containerView ? self.presentedVC.containerView.bounds.size.width : [UIScreen mainScreen].bounds.size.width, UILayoutFittingCompressedSize.height);
  63. CGFloat intrinsicHeight = [self.view systemLayoutSizeFittingSize:targetSize].height;
  64. return self.bottomYPos - (intrinsicHeight + self.bottomLayoutOffset);
  65. }
  66. default:
  67. return 0;
  68. }
  69. }
  70. @end