UINavigationController+CCProgress.m 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  1. //
  2. // UINavigationController+SGProgress.m
  3. // NavigationProgress
  4. //
  5. // Created by Shawn Gryschuk on 2013-09-19.
  6. // Copyright (c) 2013 Shawn Gryschuk. All rights reserved.
  7. //
  8. #import "UINavigationController+CCProgress.h"
  9. #import "CCProgressView.h"
  10. #define SGMaskColor [UIColor colorWithWhite:0 alpha:0.4]
  11. NSInteger const SGProgressMasktagId = 221222322;
  12. NSInteger const SGProgressMiniMasktagId = 221222321;
  13. CGFloat const SGProgressBarHeight = 2.0;
  14. @implementation UINavigationController (SGProgress)
  15. - (CCProgressView *)progressView
  16. {
  17. CCProgressView *_progressView;
  18. for (UIView *subview in [self.navigationBar subviews])
  19. {
  20. if ([subview isKindOfClass:[CCProgressView class]])
  21. {
  22. _progressView = (CCProgressView *)subview;
  23. }
  24. }
  25. if (!_progressView)
  26. {
  27. CGRect slice, remainder;
  28. CGRectDivide(self.navigationBar.bounds, &slice, &remainder, SGProgressBarHeight, CGRectMaxYEdge);
  29. _progressView = [[CCProgressView alloc] initWithFrame:slice];
  30. _progressView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin;
  31. [self.navigationBar addSubview:_progressView];
  32. }
  33. return _progressView;
  34. }
  35. - (UIView *)topMask
  36. {
  37. UIView *topMask;
  38. for (UIView *subview in [self.view subviews])
  39. {
  40. if (subview.tag == SGProgressMiniMasktagId)
  41. {
  42. topMask = subview;
  43. }
  44. }
  45. return topMask;
  46. }
  47. - (UIView *)bottomMask
  48. {
  49. UIView *bottomMask;
  50. for (UIView *subview in [self.view subviews])
  51. {
  52. if (subview.tag == SGProgressMasktagId)
  53. {
  54. bottomMask = subview;
  55. }
  56. }
  57. return bottomMask;
  58. }
  59. - (BOOL)hasCCProgressMask
  60. {
  61. for (UIView *subview in [self.view subviews])
  62. {
  63. if (subview.tag == SGProgressMiniMasktagId || subview.tag == SGProgressMasktagId)
  64. {
  65. return YES;
  66. }
  67. }
  68. return NO;
  69. }
  70. - (void)setupCCProgressMask
  71. {
  72. self.view.tintAdjustmentMode = UIViewTintAdjustmentModeDimmed;
  73. UIView *topMask = [self topMask];
  74. UIView *bottomMask = [self bottomMask];
  75. if (!topMask)
  76. {
  77. topMask = [[UIView alloc] init];
  78. topMask.tag = SGProgressMiniMasktagId;
  79. topMask.backgroundColor = SGMaskColor;
  80. topMask.alpha = 0;
  81. [self.view addSubview:topMask];
  82. }
  83. if (!bottomMask)
  84. {
  85. bottomMask = [[UIView alloc] init];
  86. bottomMask.tag = SGProgressMasktagId;
  87. bottomMask.backgroundColor = SGMaskColor;
  88. bottomMask.alpha = 0;
  89. [self.view addSubview:bottomMask];
  90. }
  91. [self updateCCProgressMaskFrame];
  92. [UIView animateWithDuration:0.3 animations:^{
  93. topMask.alpha = 1;
  94. bottomMask.alpha = 1;
  95. }];
  96. }
  97. - (void)updateCCProgressMaskFrame
  98. {
  99. CGFloat width = CGRectGetWidth(self.view.bounds);
  100. CGFloat height = CGRectGetMaxY(self.navigationBar.frame) - CGRectGetHeight([[self progressView] frame]);
  101. [[self topMask] setFrame:CGRectMake(0, 0, width, height)];
  102. CGRect slice, remainder;
  103. CGRectDivide(self.view.bounds, &slice, &remainder, CGRectGetMaxY(self.navigationBar.frame) + 0.5, CGRectMinYEdge);
  104. [[self bottomMask] setFrame:remainder];
  105. }
  106. - (void)removeCCMask
  107. {
  108. for (UIView *subview in [self.view subviews])
  109. {
  110. if (subview.tag == SGProgressMasktagId || subview.tag == SGProgressMiniMasktagId)
  111. {
  112. [UIView animateWithDuration:0.3 animations:^{
  113. subview.alpha = 0;
  114. } completion:^(BOOL finished) {
  115. [subview removeFromSuperview];
  116. self.view.tintAdjustmentMode = UIViewTintAdjustmentModeNormal;
  117. }];
  118. }
  119. }
  120. }
  121. - (void)resetTitle
  122. {
  123. BOOL titleChanged = [[[NSUserDefaults standardUserDefaults] objectForKey:kSGProgressTitleChanged] boolValue];
  124. if(titleChanged)
  125. {
  126. NSString *oldTitle = [[NSUserDefaults standardUserDefaults] objectForKey:kSGProgressOldTitle];
  127. //add animation
  128. self.visibleViewController.navigationItem.title = oldTitle;
  129. }
  130. [[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithBool:NO] forKey:kSGProgressTitleChanged];
  131. [[NSUserDefaults standardUserDefaults] setObject:@"" forKey:kSGProgressOldTitle];
  132. [[NSUserDefaults standardUserDefaults] synchronize];
  133. }
  134. - (void)changeCCProgressWithTitle:(NSString *)title
  135. {
  136. BOOL titleAlreadyChanged = [[[NSUserDefaults standardUserDefaults] objectForKey:kSGProgressTitleChanged] boolValue];
  137. if(!titleAlreadyChanged)
  138. {
  139. NSString *oldTitle = self.visibleViewController.navigationItem.title;
  140. [[NSUserDefaults standardUserDefaults] setObject:oldTitle forKey:kSGProgressOldTitle];
  141. [[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithBool:YES] forKey:kSGProgressTitleChanged];
  142. [[NSUserDefaults standardUserDefaults] synchronize];
  143. //add animation
  144. self.visibleViewController.navigationItem.title = title;
  145. }
  146. }
  147. #pragma mark - UIViewController
  148. - (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
  149. {
  150. if ([self hasCCProgressMask])
  151. {
  152. __weak typeof(self)weakSelf = self;
  153. __block NSTimeInterval timeInterval = 0;
  154. dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
  155. while (timeInterval <= duration) {
  156. [NSThread sleepForTimeInterval:0.1];
  157. timeInterval += 0.1;
  158. dispatch_async(dispatch_get_main_queue(), ^{
  159. [weakSelf updateCCProgressMaskFrame];
  160. });
  161. }
  162. });
  163. }
  164. }
  165. #pragma mark user functions
  166. - (void)showCCProgress
  167. {
  168. [self showCCProgressWithDuration:3];
  169. }
  170. - (void)showCCProgressWithDuration:(float)duration
  171. {
  172. CCProgressView *progressView = [self progressView];
  173. [UIView animateWithDuration:duration delay:0 options:UIViewAnimationOptionCurveEaseIn animations:^{
  174. progressView.progress = 1;
  175. } completion:^(BOOL finished) {
  176. [UIView animateWithDuration:0.5 animations:^{
  177. progressView.alpha = 0;
  178. } completion:^(BOOL finished) {
  179. [progressView removeFromSuperview];
  180. [self removeCCMask];
  181. [self resetTitle];
  182. }];
  183. }];
  184. }
  185. - (void)showCCProgressWithDuration:(float)duration andTintColor:(UIColor *)tintColor
  186. {
  187. [[self progressView] setTintColor:tintColor];
  188. [self showCCProgressWithDuration:duration];
  189. }
  190. - (void)showCCProgressWithDuration:(float)duration andTintColor:(UIColor *)tintColor andTitle:(NSString *)title
  191. {
  192. [self changeCCProgressWithTitle:title];
  193. [self showCCProgressWithDuration:duration andTintColor:tintColor];
  194. }
  195. - (void)showCCProgressWithMaskAndDuration:(float)duration
  196. {
  197. [self setupCCProgressMask];
  198. [self showCCProgressWithDuration:duration];
  199. }
  200. - (void)showCCProgressWithMaskAndDuration:(float)duration andTitle:(NSString *) title
  201. {
  202. [self changeCCProgressWithTitle:title];
  203. [self showCCProgressWithMaskAndDuration:duration];
  204. }
  205. - (void)finishCCProgress
  206. {
  207. CCProgressView *progressView = [self progressView];
  208. [UIView animateWithDuration:0.1 animations:^{
  209. progressView.progress = 1;
  210. }];
  211. }
  212. - (void)cancelCCProgress
  213. {
  214. CCProgressView *progressView = [self progressView];
  215. [UIView animateWithDuration:0.5 animations:^{
  216. progressView.alpha = 0;
  217. } completion:^(BOOL finished) {
  218. [progressView removeFromSuperview];
  219. [self removeCCMask];
  220. [self resetTitle];
  221. }];
  222. }
  223. - (void)setCCProgressPercentage:(float)percentage
  224. {
  225. CCProgressView *progressView = [self progressView];
  226. [UIView animateWithDuration:0.1 delay:0 options:UIViewAnimationOptionCurveLinear animations:^{
  227. progressView.progress = percentage / 100.f;
  228. } completion:^(BOOL finished) {
  229. if (percentage >= 100)
  230. {
  231. [UIView animateWithDuration:0.5 animations:^{
  232. progressView.alpha = 0;
  233. } completion:^(BOOL finished) {
  234. [progressView removeFromSuperview];
  235. [self removeCCMask];
  236. [self resetTitle];
  237. }];
  238. }
  239. }];
  240. }
  241. - (void)setCCProgressPercentage:(float)percentage andTitle:(NSString *)title
  242. {
  243. [self changeCCProgressWithTitle:title];
  244. [self setCCProgressPercentage:percentage];
  245. }
  246. - (void)setCCProgressPercentage:(float)percentage andTintColor:(UIColor *)tintColor
  247. {
  248. [[self progressView] setTintColor:tintColor];
  249. [self setCCProgressPercentage:percentage];
  250. }
  251. - (void)setCCProgressMaskWithPercentage:(float)percentage
  252. {
  253. [self setCCProgressPercentage:percentage];
  254. [self setupCCProgressMask];
  255. }
  256. - (void)setCCProgressMaskWithPercentage:(float)percentage andTitle:(NSString *)title
  257. {
  258. [self changeCCProgressWithTitle:title];
  259. [self setCCProgressMaskWithPercentage:percentage];
  260. }
  261. @end