PageRenderTime 52ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/GreenEnergyResearch/PopOver/UIViewController+MJPopupViewController.m

https://bitbucket.org/jamesfolk/greenenergyresearch-ios
Objective C | 375 lines | 300 code | 55 blank | 20 comment | 14 complexity | aa19f0f228e8be14217f31eb530fc47a MD5 | raw file
Possible License(s): BSD-3-Clause, CC-BY-3.0
  1. //
  2. // UIViewController+MJPopupViewController.m
  3. // MJModalViewController
  4. //
  5. // Created by Martin Juhasz on 11.05.12.
  6. // Copyright (c) 2012 martinjuhasz.de. All rights reserved.
  7. //
  8. #import "UIViewController+MJPopupViewController.h"
  9. #import <QuartzCore/QuartzCore.h>
  10. #import "MJPopupBackgroundView.h"
  11. #import <objc/runtime.h>
  12. #define kPopupModalAnimationDuration 0.35
  13. #define kMJPopupViewController @"kMJPopupViewController"
  14. #define kMJPopupBackgroundView @"kMJPopupBackgroundView"
  15. #define kMJSourceViewTag 23941
  16. #define kMJPopupViewTag 23942
  17. #define kMJOverlayViewTag 23945
  18. @interface UIViewController (MJPopupViewControllerPrivate)
  19. - (UIView*)topView;
  20. - (void)presentPopupView:(UIView*)popupView;
  21. @end
  22. static NSString *MJPopupViewDismissedKey = @"MJPopupViewDismissed";
  23. ////////////////////////////////////////////////////////////////////////////
  24. #pragma mark -
  25. #pragma mark Public
  26. @implementation UIViewController (MJPopupViewController)
  27. static void * const keypath = (void*)&keypath;
  28. - (UIViewController*)mj_popupViewController {
  29. return objc_getAssociatedObject(self, kMJPopupViewController);
  30. }
  31. - (void)setMj_popupViewController:(UIViewController *)mj_popupViewController {
  32. objc_setAssociatedObject(self, kMJPopupViewController, mj_popupViewController, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
  33. }
  34. - (MJPopupBackgroundView*)mj_popupBackgroundView {
  35. return objc_getAssociatedObject(self, kMJPopupBackgroundView);
  36. }
  37. - (void)setMj_popupBackgroundView:(MJPopupBackgroundView *)mj_popupBackgroundView {
  38. objc_setAssociatedObject(self, kMJPopupBackgroundView, mj_popupBackgroundView, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
  39. }
  40. - (void)presentPopupViewController:(UIViewController*)popupViewController animationType:(MJPopupViewAnimation)animationType dismissed:(void(^)(void))dismissed
  41. {
  42. self.mj_popupViewController = popupViewController;
  43. [self presentPopupView:popupViewController.view animationType:animationType dismissed:dismissed];
  44. }
  45. - (void)presentPopupViewController:(UIViewController*)popupViewController animationType:(MJPopupViewAnimation)animationType
  46. {
  47. [self presentPopupViewController:popupViewController animationType:animationType dismissed:nil];
  48. }
  49. - (void)dismissPopupViewControllerWithanimationType:(MJPopupViewAnimation)animationType
  50. {
  51. UIView *sourceView = [self topView];
  52. UIView *popupView = [sourceView viewWithTag:kMJPopupViewTag];
  53. UIView *overlayView = [sourceView viewWithTag:kMJOverlayViewTag];
  54. switch (animationType) {
  55. case MJPopupViewAnimationSlideBottomTop:
  56. case MJPopupViewAnimationSlideBottomBottom:
  57. case MJPopupViewAnimationSlideTopTop:
  58. case MJPopupViewAnimationSlideTopBottom:
  59. case MJPopupViewAnimationSlideLeftLeft:
  60. case MJPopupViewAnimationSlideLeftRight:
  61. case MJPopupViewAnimationSlideRightLeft:
  62. case MJPopupViewAnimationSlideRightRight:
  63. [self slideViewOut:popupView sourceView:sourceView overlayView:overlayView withAnimationType:animationType];
  64. break;
  65. default:
  66. [self fadeViewOut:popupView sourceView:sourceView overlayView:overlayView];
  67. break;
  68. }
  69. }
  70. ////////////////////////////////////////////////////////////////////////////
  71. #pragma mark -
  72. #pragma mark View Handling
  73. - (void)presentPopupView:(UIView*)popupView animationType:(MJPopupViewAnimation)animationType
  74. {
  75. [self presentPopupView:popupView animationType:animationType dismissed:nil];
  76. }
  77. - (void)presentPopupView:(UIView*)popupView animationType:(MJPopupViewAnimation)animationType dismissed:(void(^)(void))dismissed
  78. {
  79. UIView *sourceView = [self topView];
  80. sourceView.tag = kMJSourceViewTag;
  81. popupView.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleLeftMargin |UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleRightMargin;
  82. popupView.tag = kMJPopupViewTag;
  83. // check if source view controller is not in destination
  84. if ([sourceView.subviews containsObject:popupView]) return;
  85. // customize popupView
  86. popupView.layer.shadowPath = [UIBezierPath bezierPathWithRect:popupView.bounds].CGPath;
  87. popupView.layer.masksToBounds = NO;
  88. popupView.layer.shadowOffset = CGSizeMake(5, 5);
  89. popupView.layer.shadowRadius = 5;
  90. popupView.layer.shadowOpacity = 0.5;
  91. popupView.layer.shouldRasterize = YES;
  92. popupView.layer.rasterizationScale = [[UIScreen mainScreen] scale];
  93. // Add semi overlay
  94. UIView *overlayView = [[UIView alloc] initWithFrame:sourceView.bounds];
  95. overlayView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
  96. overlayView.tag = kMJOverlayViewTag;
  97. overlayView.backgroundColor = [UIColor clearColor];
  98. // BackgroundView
  99. self.mj_popupBackgroundView = [[MJPopupBackgroundView alloc] initWithFrame:sourceView.bounds];
  100. self.mj_popupBackgroundView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
  101. self.mj_popupBackgroundView.backgroundColor = [UIColor clearColor];
  102. self.mj_popupBackgroundView.alpha = 0.0f;
  103. [overlayView addSubview:self.mj_popupBackgroundView];
  104. // Make the Background Clickable
  105. UIButton * dismissButton = [UIButton buttonWithType:UIButtonTypeCustom];
  106. dismissButton.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
  107. dismissButton.backgroundColor = [UIColor clearColor];
  108. dismissButton.frame = sourceView.bounds;
  109. [overlayView addSubview:dismissButton];
  110. popupView.alpha = 0.0f;
  111. [overlayView addSubview:popupView];
  112. [sourceView addSubview:overlayView];
  113. [dismissButton addTarget:self action:@selector(dismissPopupViewControllerWithanimation:) forControlEvents:UIControlEventTouchUpInside];
  114. switch (animationType) {
  115. case MJPopupViewAnimationSlideBottomTop:
  116. case MJPopupViewAnimationSlideBottomBottom:
  117. case MJPopupViewAnimationSlideTopTop:
  118. case MJPopupViewAnimationSlideTopBottom:
  119. case MJPopupViewAnimationSlideLeftLeft:
  120. case MJPopupViewAnimationSlideLeftRight:
  121. case MJPopupViewAnimationSlideRightLeft:
  122. case MJPopupViewAnimationSlideRightRight:
  123. dismissButton.tag = animationType;
  124. [self slideViewIn:popupView sourceView:sourceView overlayView:overlayView withAnimationType:animationType];
  125. break;
  126. default:
  127. dismissButton.tag = MJPopupViewAnimationFade;
  128. [self fadeViewIn:popupView sourceView:sourceView overlayView:overlayView];
  129. break;
  130. }
  131. [self setDismissedCallback:dismissed];
  132. }
  133. -(UIView*)topView {
  134. UIViewController *recentView = self;
  135. while (recentView.parentViewController != nil) {
  136. recentView = recentView.parentViewController;
  137. }
  138. return recentView.view;
  139. }
  140. - (void)dismissPopupViewControllerWithanimation:(id)sender
  141. {
  142. if ([sender isKindOfClass:[UIButton class]]) {
  143. UIButton* dismissButton = sender;
  144. switch (dismissButton.tag) {
  145. case MJPopupViewAnimationSlideBottomTop:
  146. case MJPopupViewAnimationSlideBottomBottom:
  147. case MJPopupViewAnimationSlideTopTop:
  148. case MJPopupViewAnimationSlideTopBottom:
  149. case MJPopupViewAnimationSlideLeftLeft:
  150. case MJPopupViewAnimationSlideLeftRight:
  151. case MJPopupViewAnimationSlideRightLeft:
  152. case MJPopupViewAnimationSlideRightRight:
  153. [self dismissPopupViewControllerWithanimationType:dismissButton.tag];
  154. break;
  155. default:
  156. [self dismissPopupViewControllerWithanimationType:MJPopupViewAnimationFade];
  157. break;
  158. }
  159. } else {
  160. [self dismissPopupViewControllerWithanimationType:MJPopupViewAnimationFade];
  161. }
  162. }
  163. //////////////////////////////////////////////////////////////////////////////
  164. #pragma mark -
  165. #pragma mark Animations
  166. #pragma mark --- Slide
  167. - (void)slideViewIn:(UIView*)popupView sourceView:(UIView*)sourceView overlayView:(UIView*)overlayView withAnimationType:(MJPopupViewAnimation)animationType
  168. {
  169. // Generating Start and Stop Positions
  170. CGSize sourceSize = sourceView.bounds.size;
  171. CGSize popupSize = popupView.bounds.size;
  172. CGRect popupStartRect;
  173. switch (animationType) {
  174. case MJPopupViewAnimationSlideBottomTop:
  175. case MJPopupViewAnimationSlideBottomBottom:
  176. popupStartRect = CGRectMake((sourceSize.width - popupSize.width) / 2,
  177. sourceSize.height,
  178. popupSize.width,
  179. popupSize.height);
  180. break;
  181. case MJPopupViewAnimationSlideLeftLeft:
  182. case MJPopupViewAnimationSlideLeftRight:
  183. popupStartRect = CGRectMake(-sourceSize.width,
  184. (sourceSize.height - popupSize.height) / 2,
  185. popupSize.width,
  186. popupSize.height);
  187. break;
  188. case MJPopupViewAnimationSlideTopTop:
  189. case MJPopupViewAnimationSlideTopBottom:
  190. popupStartRect = CGRectMake((sourceSize.width - popupSize.width) / 2,
  191. -popupSize.height,
  192. popupSize.width,
  193. popupSize.height);
  194. break;
  195. default:
  196. popupStartRect = CGRectMake(sourceSize.width,
  197. (sourceSize.height - popupSize.height) / 2,
  198. popupSize.width,
  199. popupSize.height);
  200. break;
  201. }
  202. CGRect popupEndRect = CGRectMake((sourceSize.width - popupSize.width) / 2,
  203. (sourceSize.height - popupSize.height) / 2,
  204. popupSize.width,
  205. popupSize.height);
  206. // Set starting properties
  207. popupView.frame = popupStartRect;
  208. popupView.alpha = 1.0f;
  209. [UIView animateWithDuration:kPopupModalAnimationDuration delay:0.0f options:UIViewAnimationOptionCurveEaseOut animations:^{
  210. [self.mj_popupViewController viewWillAppear:NO];
  211. self.mj_popupBackgroundView.alpha = 1.0f;
  212. popupView.frame = popupEndRect;
  213. } completion:^(BOOL finished) {
  214. [self.mj_popupViewController viewDidAppear:NO];
  215. }];
  216. }
  217. - (void)slideViewOut:(UIView*)popupView sourceView:(UIView*)sourceView overlayView:(UIView*)overlayView withAnimationType:(MJPopupViewAnimation)animationType
  218. {
  219. // Generating Start and Stop Positions
  220. CGSize sourceSize = sourceView.bounds.size;
  221. CGSize popupSize = popupView.bounds.size;
  222. CGRect popupEndRect;
  223. switch (animationType) {
  224. case MJPopupViewAnimationSlideBottomTop:
  225. case MJPopupViewAnimationSlideTopTop:
  226. popupEndRect = CGRectMake((sourceSize.width - popupSize.width) / 2,
  227. -popupSize.height,
  228. popupSize.width,
  229. popupSize.height);
  230. break;
  231. case MJPopupViewAnimationSlideBottomBottom:
  232. case MJPopupViewAnimationSlideTopBottom:
  233. popupEndRect = CGRectMake((sourceSize.width - popupSize.width) / 2,
  234. sourceSize.height,
  235. popupSize.width,
  236. popupSize.height);
  237. break;
  238. case MJPopupViewAnimationSlideLeftRight:
  239. case MJPopupViewAnimationSlideRightRight:
  240. popupEndRect = CGRectMake(sourceSize.width,
  241. popupView.frame.origin.y,
  242. popupSize.width,
  243. popupSize.height);
  244. break;
  245. default:
  246. popupEndRect = CGRectMake(-popupSize.width,
  247. popupView.frame.origin.y,
  248. popupSize.width,
  249. popupSize.height);
  250. break;
  251. }
  252. [UIView animateWithDuration:kPopupModalAnimationDuration delay:0.0f options:UIViewAnimationOptionCurveEaseIn animations:^{
  253. [self.mj_popupViewController viewWillDisappear:NO];
  254. popupView.frame = popupEndRect;
  255. self.mj_popupBackgroundView.alpha = 0.0f;
  256. } completion:^(BOOL finished) {
  257. [popupView removeFromSuperview];
  258. [overlayView removeFromSuperview];
  259. [self.mj_popupViewController viewDidDisappear:NO];
  260. self.mj_popupViewController = nil;
  261. id dismissed = [self dismissedCallback];
  262. if (dismissed != nil)
  263. {
  264. ((void(^)(void))dismissed)();
  265. [self setDismissedCallback:nil];
  266. }
  267. }];
  268. }
  269. #pragma mark --- Fade
  270. - (void)fadeViewIn:(UIView*)popupView sourceView:(UIView*)sourceView overlayView:(UIView*)overlayView
  271. {
  272. // Generating Start and Stop Positions
  273. CGSize sourceSize = sourceView.bounds.size;
  274. CGSize popupSize = popupView.bounds.size;
  275. CGRect popupEndRect = CGRectMake((sourceSize.width - popupSize.width) / 2,
  276. (sourceSize.height - popupSize.height) / 2,
  277. popupSize.width,
  278. popupSize.height);
  279. // Set starting properties
  280. popupView.frame = popupEndRect;
  281. popupView.alpha = 0.0f;
  282. [UIView animateWithDuration:kPopupModalAnimationDuration animations:^{
  283. [self.mj_popupViewController viewWillAppear:NO];
  284. self.mj_popupBackgroundView.alpha = 0.5f;
  285. popupView.alpha = 1.0f;
  286. } completion:^(BOOL finished) {
  287. [self.mj_popupViewController viewDidAppear:NO];
  288. }];
  289. }
  290. - (void)fadeViewOut:(UIView*)popupView sourceView:(UIView*)sourceView overlayView:(UIView*)overlayView
  291. {
  292. [UIView animateWithDuration:kPopupModalAnimationDuration animations:^{
  293. [self.mj_popupViewController viewWillDisappear:NO];
  294. self.mj_popupBackgroundView.alpha = 0.0f;
  295. popupView.alpha = 0.0f;
  296. } completion:^(BOOL finished) {
  297. [popupView removeFromSuperview];
  298. [overlayView removeFromSuperview];
  299. [self.mj_popupViewController viewDidDisappear:NO];
  300. self.mj_popupViewController = nil;
  301. id dismissed = [self dismissedCallback];
  302. if (dismissed != nil)
  303. {
  304. ((void(^)(void))dismissed)();
  305. [self setDismissedCallback:nil];
  306. }
  307. }];
  308. }
  309. #pragma mark -
  310. #pragma mark Category Accessors
  311. #pragma mark --- Dismissed
  312. - (void)setDismissedCallback:(void(^)(void))dismissed
  313. {
  314. objc_setAssociatedObject(self, &MJPopupViewDismissedKey, dismissed, OBJC_ASSOCIATION_RETAIN);
  315. }
  316. - (void(^)(void))dismissedCallback
  317. {
  318. return objc_getAssociatedObject(self, &MJPopupViewDismissedKey);
  319. }
  320. @end