GKPhotoRotationHandler.m 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. //
  2. // GKPhotoRotationHandler.m
  3. // GKPhotoBrowser
  4. //
  5. // Created by QuintGao on 2023/3/2.
  6. //
  7. #import "GKPhotoRotationHandler.h"
  8. #import "GKPhotoBrowser.h"
  9. @interface GKPhotoRotationHandler()
  10. // 在浏览器显示前是否已经添加过屏幕旋转监测
  11. @property (nonatomic, assign) BOOL isGeneratingDeviceOrientation;
  12. // 是否添加过屏幕方向改变通知
  13. @property (nonatomic, assign) BOOL isOrientationNotificationAdded;
  14. @end
  15. @implementation GKPhotoRotationHandler
  16. - (instancetype)init {
  17. if (self = [super init]) {
  18. self.isGeneratingDeviceOrientation = [UIDevice currentDevice].isGeneratingDeviceOrientationNotifications;
  19. }
  20. return self;
  21. }
  22. - (void)addDeviceOrientationObserver {
  23. if (self.browser.isFollowSystemRotation) return;
  24. // 默认设备方向:竖屏
  25. self.originalOrientation = UIDeviceOrientationPortrait;
  26. self.currentOrientation = UIDeviceOrientationPortrait;
  27. if (!self.isOrientationNotificationAdded) {
  28. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(deviceOrientationDidChange) name:UIDeviceOrientationDidChangeNotification object:nil];
  29. self.isOrientationNotificationAdded = YES;
  30. }
  31. if (self.isGeneratingDeviceOrientation) return;
  32. if (![UIDevice currentDevice].isGeneratingDeviceOrientationNotifications) {
  33. [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
  34. }
  35. }
  36. - (void)delDeviceOrientationObserver {
  37. if (self.browser.isFollowSystemRotation) return;
  38. if (self.isOrientationNotificationAdded) {
  39. [[NSNotificationCenter defaultCenter] removeObserver:self name:UIDeviceOrientationDidChangeNotification object:nil];
  40. self.isOrientationNotificationAdded = NO;
  41. }
  42. if (self.isGeneratingDeviceOrientation) return;
  43. if ([UIDevice currentDevice].isGeneratingDeviceOrientationNotifications) {
  44. [[UIDevice currentDevice] endGeneratingDeviceOrientationNotifications];
  45. }
  46. }
  47. - (void)deviceOrientationDidChange {
  48. if (self.browser.isFollowSystemRotation) return;
  49. if (self.browser.isScreenRotateDisabled) return;
  50. // 旋转之后当前的设备方向
  51. UIDeviceOrientation currentOrientation = [UIDevice currentDevice].orientation;
  52. if (currentOrientation == UIDeviceOrientationUnknown || currentOrientation == UIDeviceOrientationFaceUp) {
  53. if (self.originalOrientation == UIDeviceOrientationUnknown) {
  54. currentOrientation = UIDeviceOrientationPortrait;
  55. }else {
  56. currentOrientation = self.originalOrientation;
  57. }
  58. }
  59. // 修复bug #117,从后台进入前台会执行此方法 导致缩放变化,所以此处做下处理
  60. if (self.currentOrientation == currentOrientation) return;
  61. self.currentOrientation = currentOrientation;
  62. self.isRotation = YES;
  63. GKPhotoView *photoView = self.browser.curPhotoView;
  64. if (!photoView) return;
  65. // 恢复当前视图的缩放
  66. GKPhoto *photo = photoView.photo;
  67. photo.isZooming = NO;
  68. photo.zoomRect = CGRectZero;
  69. if (UIDeviceOrientationIsPortrait(self.originalOrientation)) {
  70. if (UIDeviceOrientationIsLandscape(currentOrientation)) {
  71. [photoView.scrollView setZoomScale:1.0 animated:YES];
  72. }
  73. }
  74. if (UIDeviceOrientationIsLandscape(self.originalOrientation)) {
  75. if (UIDeviceOrientationIsPortrait(currentOrientation)) {
  76. [photoView.scrollView setZoomScale:1.0 animated:YES];
  77. }
  78. }
  79. CGRect screenBounds = [UIScreen mainScreen].bounds;
  80. // 旋转之后是横屏
  81. if (UIDeviceOrientationIsLandscape(currentOrientation)) {
  82. self.isLandscape = YES;
  83. [self deviceOrientationChangedDelegate];
  84. // 横屏移除pan手势
  85. if ([self.delegate respondsToSelector:@selector(willRotation:)]) {
  86. [self.delegate willRotation:YES];
  87. }
  88. NSTimeInterval duration = UIDeviceOrientationIsLandscape(self.originalOrientation) ? 2 * self.browser.animDuration : self.browser.animDuration;
  89. [UIView animateWithDuration:duration delay:0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{
  90. // 旋转状态栏
  91. if (@available(iOS 13.0, *)) {} else {
  92. #pragma clang diagnostic push
  93. #pragma clang diagnostic ignored "-Wdeprecated-declarations"
  94. [[UIApplication sharedApplication] setStatusBarOrientation:(UIInterfaceOrientation)currentOrientation animated:YES];
  95. #pragma clang diagnostic pop
  96. }
  97. float rotation = currentOrientation == UIDeviceOrientationLandscapeRight ? 1.5 : 0.5;
  98. // 旋转contentView
  99. self.browser.contentView.transform = CGAffineTransformMakeRotation(M_PI * rotation);
  100. CGFloat width = MAX(screenBounds.size.width, screenBounds.size.height);
  101. // 设置frame
  102. self.browser.contentView.bounds = CGRectMake(0, 0, width, MIN(screenBounds.size.width, screenBounds.size.height));
  103. self.browser.contentView.center = self.browser.view.center;
  104. [self.browser.view setNeedsLayout];
  105. [self.browser.view layoutIfNeeded];
  106. [self.browser layoutSubviews];
  107. } completion:^(BOOL finished) {
  108. // 记录设备方向
  109. self.originalOrientation = currentOrientation;
  110. self.isRotation = NO;
  111. if ([self.delegate respondsToSelector:@selector(didRotation:)]) {
  112. [self.delegate didRotation:YES];
  113. }
  114. }];
  115. }else if (currentOrientation == UIDeviceOrientationPortrait) {
  116. self.isLandscape = NO;
  117. [self deviceOrientationChangedDelegate];
  118. // 竖屏时添加pan手势
  119. if ([self.delegate respondsToSelector:@selector(willRotation:)]) {
  120. [self.delegate willRotation:NO];
  121. }
  122. NSTimeInterval duration = self.browser.animDuration;
  123. [UIView animateWithDuration:duration delay:0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{
  124. // 旋转状态栏
  125. if (@available(iOS 13.0, *)) {} else {
  126. #pragma clang diagnostic push
  127. #pragma clang diagnostic ignored "-Wdeprecated-declarations"
  128. [[UIApplication sharedApplication] setStatusBarOrientation:(UIInterfaceOrientation)currentOrientation animated:YES];
  129. #pragma clang diagnostic pop
  130. }
  131. // 旋转view
  132. self.browser.contentView.transform = currentOrientation == UIDeviceOrientationPortrait ? CGAffineTransformIdentity : CGAffineTransformMakeRotation(M_PI);
  133. CGFloat height = MAX(screenBounds.size.width, screenBounds.size.height);
  134. // 设置frame
  135. self.browser.contentView.bounds = CGRectMake(0, 0, MIN(screenBounds.size.width, screenBounds.size.height), height);
  136. self.browser.contentView.center = self.browser.view.center;
  137. [self.browser.view setNeedsLayout];
  138. [self.browser.view layoutIfNeeded];
  139. [self.browser layoutSubviews];
  140. } completion:^(BOOL finished) {
  141. // 记录设备方向
  142. self.originalOrientation = currentOrientation;
  143. self.isRotation = NO;
  144. if ([self.delegate respondsToSelector:@selector(didRotation:)]) {
  145. [self.delegate didRotation:NO];
  146. }
  147. }];
  148. }else {
  149. self.isRotation = NO;
  150. self.isLandscape = NO;
  151. [self.browser.view setNeedsLayout];
  152. [self.browser.view layoutIfNeeded];
  153. [self.browser layoutSubviews];
  154. [self deviceOrientationChangedDelegate];
  155. }
  156. }
  157. - (void)handleSystemRotation {
  158. if (!self.browser.isFollowSystemRotation) return;
  159. self.isRotation = YES;
  160. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.01f * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  161. [UIView animateWithDuration:0.3 animations:^{
  162. CGFloat width = self.browser.view.bounds.size.width;
  163. CGFloat height = self.browser.view.bounds.size.height;
  164. self.browser.contentView.bounds = CGRectMake(0, 0, width, height);
  165. self.browser.contentView.center = self.browser.view.center;
  166. [self.browser.view setNeedsLayout];
  167. [self.browser.view layoutIfNeeded];
  168. [self.browser layoutSubviews];
  169. } completion:^(BOOL finished) {
  170. self.isRotation = NO;
  171. }];
  172. });
  173. }
  174. - (void)deviceOrientationChangedDelegate {
  175. if ([self.browser.delegate respondsToSelector:@selector(photoBrowser:onDeciceChangedWithIndex:isLandscape:)]) {
  176. [self.browser.delegate photoBrowser:self.browser onDeciceChangedWithIndex:self.browser.currentIndex isLandscape:self.isLandscape];
  177. }
  178. }
  179. @end