DKAnimationBaseView.m 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356
  1. //
  2. // ZLAnimationBaseView.m
  3. // ZLAssetsPickerDemo
  4. //
  5. //
  6. #import "DKAnimationBaseView.h"
  7. #import "DKPhotoPickerCommon.h"
  8. #import "UIView+Extension.h"
  9. @implementation DKAnimationBaseView
  10. // 当前的View
  11. static DKAnimationBaseView *_baseView = nil;
  12. // 参数
  13. static NSDictionary *_options = nil;
  14. static NSInteger _currentPage = 0;
  15. static NSIndexPath *_currentIndexPath = nil;
  16. static NSMutableDictionary *_attachParams = nil;
  17. // 单例
  18. static DKAnimationBaseView *_singleBaseView;
  19. + (instancetype) sharedManager{
  20. static dispatch_once_t onceToken;
  21. dispatch_once(&onceToken, ^{
  22. _singleBaseView = [[self alloc] init];
  23. _attachParams = [NSMutableDictionary dictionary];
  24. });
  25. return _singleBaseView;
  26. }
  27. // 补充空的字典
  28. + (NSDictionary *) supplementOptionsEmptyParamWithDict:(NSDictionary *)options{
  29. NSMutableDictionary *ops = [NSMutableDictionary dictionaryWithDictionary:options];
  30. // 开始的View/开始View的根View
  31. UIView *toView = options[UIViewAnimationToView];
  32. UIView *fromView = options[UIViewAnimationFromView];
  33. // 如果没有起始位置
  34. CGRect startFrame = [options[UIViewAnimationStartFrame] CGRectValue];
  35. if (!startFrame.size.width || !startFrame.size.height) {
  36. startFrame = [self initStartFrameToView:toView fromView:fromView];
  37. ops[UIViewAnimationStartFrame] = [NSValue valueWithCGRect:startFrame];
  38. }
  39. // 如果没有结束位置
  40. CGRect endFrame = [options[UIViewAnimationEndFrame] CGRectValue];
  41. if (!endFrame.size.width || !endFrame.size.height) {
  42. endFrame = [self initEndFrameFromView:fromView];
  43. ops[UIViewAnimationEndFrame] = [NSValue valueWithCGRect:endFrame];
  44. }
  45. // 如果没有动画时间
  46. if (![ops[UIViewAnimationDuration] floatValue]) {
  47. ops[UIViewAnimationDuration] = [NSNumber numberWithFloat:.35];
  48. }
  49. return ops;
  50. }
  51. #pragma mark -
  52. #pragma mark 补充开始的位置
  53. + (CGRect)initStartFrameToView:(UIView *)toView fromView:(UIView *)fromView{
  54. CGRect startFrame = CGRectZero;
  55. if ([toView isKindOfClass:[UITableViewCell class]]) {
  56. UITableViewCell *cell = (UITableViewCell *)toView;
  57. startFrame = [cell convertRect:cell.imageView.frame toView:fromView];
  58. }else{
  59. startFrame = [toView convertRect:toView.bounds toView:fromView];
  60. }
  61. // 如果是iOS7以下StartFrame需要y值需要加64
  62. if (!iOS7gt) startFrame.origin.y += 64;
  63. return startFrame;
  64. }
  65. #pragma mark 补充结束的位置
  66. + (CGRect)initEndFrameFromView:(UIView *)fromView{
  67. return fromView.bounds;
  68. }
  69. #pragma mark - 开始动画
  70. + (instancetype) animationViewWithOptions:(NSDictionary *)options animations:(void(^)())animations completion:(void (^)(DKAnimationBaseView *baseView)) completion{
  71. // 准备动画前的一些操作
  72. [self willStartAnimationOperation];
  73. // 补充没填的参数
  74. NSMutableDictionary *ops = [NSMutableDictionary dictionaryWithDictionary:[self supplementOptionsEmptyParamWithDict:options]];
  75. [ops addEntriesFromDictionary:_attachParams];
  76. _options = [NSMutableDictionary dictionaryWithDictionary:ops];
  77. // 起始位置、结束位置、动画时间
  78. CGRect startFrame = [_options[UIViewAnimationStartFrame] CGRectValue];
  79. if ([_options[UIViewAnimationFromView] isMemberOfClass:[UIScrollView class]]) {
  80. startFrame.origin.y -= [_options[UIViewAnimationFromView] contentOffset].y;
  81. }
  82. CGFloat duration = [_options[UIViewAnimationDuration] floatValue];
  83. DKAnimationBaseView *selfView = _options[UIViewAnimationSelfView];
  84. UIView *inView = _options[UIViewAnimationInView];
  85. // 如果已经有子类继承并且修改了selfView, 就用子类的
  86. if (selfView) {
  87. _baseView = selfView;
  88. }else{
  89. if (!([_options[UIViewAnimationToView] isKindOfClass:[UIImageView class]])) {
  90. _baseView = _options[UIViewAnimationToView];
  91. }else{
  92. _baseView = [self sharedManager];
  93. }
  94. }
  95. // 初始化baseView的参数
  96. _baseView.hidden = NO;
  97. _baseView.frame = startFrame;
  98. if ([_options[UIViewAnimationAnimationStatusType] integerValue] == UIViewAnimationAnimationStatusFade) {
  99. // 淡入淡出
  100. _baseView.alpha = 0.0;
  101. _baseView.frame = [self setMaxMinZoomScalesForCurrentBounds];
  102. }else{
  103. // 缩放/旋转
  104. _baseView.alpha = 1.0;
  105. _baseView.frame = startFrame;
  106. }
  107. // 避免重复添加View
  108. if (![inView.subviews.lastObject isKindOfClass:[DKAnimationBaseView class]]) {
  109. [inView addSubview:_baseView];
  110. }
  111. __weak typeof(_baseView) weakBaseView = _baseView;
  112. __weak typeof(self) weakSelf = self;
  113. // 隐藏状态栏
  114. if ([UIDevice currentDevice].systemVersion.floatValue >= 7.0){
  115. [UIApplication sharedApplication].statusBarHidden = YES;
  116. }
  117. // 开始动画
  118. [UIView animateWithDuration:duration animations:^{
  119. if (animations) {
  120. animations();
  121. }
  122. if ([ops[UIViewAnimationAnimationStatusType] integerValue] == UIViewAnimationAnimationStatusFade) {
  123. // 淡入淡出
  124. weakBaseView.alpha = 1.0;
  125. }else{
  126. // 缩放/旋转
  127. weakBaseView.frame = [weakSelf setMaxMinZoomScalesForCurrentBounds];
  128. }
  129. if (!iOS7gt) {
  130. // 在iOS6因为隐藏了状态栏。所以需要加上20的高度
  131. // weakBaseView.y += 20;
  132. }
  133. } completion:^(BOOL finished) {
  134. if (completion) {
  135. completion(nil);
  136. }
  137. [weakBaseView removeFromSuperview];
  138. }];
  139. return nil;
  140. }
  141. + (void) restoreAnimation:(void(^)()) completion{
  142. [self restoreWithOptions:_options animation:completion];
  143. }
  144. #pragma mark - 遍历view的父节点是不是TableViewCell 或者 UICollectionCell
  145. + (UIView *)traversalViewWithCell:(UIView *)view{
  146. if ([view isKindOfClass:[UITableViewCell class]] || [view isKindOfClass:[UICollectionViewCell class]] || view == nil) {
  147. return view;
  148. }
  149. return [self traversalViewWithCell:view.superview];
  150. }
  151. + (void) restoreWithOptions:(NSDictionary *)options animation:(void (^)())completion{
  152. // 即将消失调用
  153. [self willUnLoadAnimationOperation];
  154. // 补充没填的参数
  155. // _options = [self supplementOptionsEmptyParamWithDict:options];
  156. NSMutableDictionary *ops = [NSMutableDictionary dictionaryWithDictionary:[self supplementOptionsEmptyParamWithDict:options]];
  157. [ops addEntriesFromDictionary:_attachParams];
  158. if ([[self currentIndexPath] item] > KPhotoShowMaxCount) {
  159. ops[UIViewAnimationAnimationStatusType] = @(UIViewAnimationAnimationStatusFade);
  160. }
  161. _options = [NSMutableDictionary dictionaryWithDictionary:ops];
  162. CGRect endFrame = [_options[UIViewAnimationEndFrame] CGRectValue];
  163. if ([_options[UIViewAnimationFromView] isMemberOfClass:[UIScrollView class]]) {
  164. endFrame.origin.y -= [_options[UIViewAnimationFromView] contentOffset].y;
  165. }
  166. CGFloat duration = [_options[UIViewAnimationDuration] floatValue];
  167. // 把_baseView添加到Window上
  168. UIWindow *myWindow = [[[UIApplication sharedApplication] windows] firstObject];
  169. UIView *view = myWindow.subviews.lastObject;
  170. if (!([view isKindOfClass:[DKAnimationBaseView class]]) &&
  171. (![view isKindOfClass:[UIImageView class]]))
  172. {
  173. [myWindow addSubview:_baseView];
  174. }
  175. // if ([UIDevice currentDevice].systemVersion.floatValue < 7.0){
  176. // _baseView.frame = [_options[UIViewAnimationInView] frame];
  177. // }else{
  178. _baseView.frame = [self setMaxMinZoomScalesForCurrentBounds];
  179. // }
  180. UIViewAnimationAnimationStatus status = [_options[UIViewAnimationAnimationStatusType] intValue];
  181. __weak typeof(self) weakSelf = self;
  182. __weak UIView *weakBaseView = _baseView;
  183. [UIView animateWithDuration:duration animations:^{
  184. if (status == UIViewAnimationAnimationStatusRotate) {
  185. weakBaseView.transform = CGAffineTransformMakeScale(0.7, 0.7);
  186. weakBaseView.transform = CGAffineTransformRotate(_baseView.transform, M_PI_4);
  187. weakBaseView.alpha = 0;
  188. }else if(status == UIViewAnimationAnimationStatusFade){
  189. weakBaseView.alpha = 0.0;
  190. }else{
  191. weakBaseView.frame = endFrame;
  192. }
  193. myWindow.userInteractionEnabled = NO;
  194. } completion:^(BOOL finished) {
  195. if (completion) {
  196. completion();
  197. }
  198. [weakBaseView removeFromSuperview];
  199. [weakSelf unLoadStopAnimationOperation];
  200. if (status == UIViewAnimationAnimationStatusRotate || status == UIViewAnimationAnimationStatusFade) {
  201. weakBaseView.transform = CGAffineTransformIdentity;
  202. weakBaseView.alpha = 1;
  203. }
  204. }];
  205. }
  206. #pragma mark -
  207. #pragma mark 准备开始动画前的操作
  208. + (void) willStartAnimationOperation{
  209. // [[UIApplication sharedApplication] setStatusBarHidden:YES];
  210. // [_options[UIViewAnimationFromView] setUserInteractionEnabled:NO];
  211. }
  212. // 计算Frame根据屏幕的尺寸拉伸或缩小
  213. + (CGRect )setMaxMinZoomScalesForCurrentBounds {
  214. UIImageView *imageView = (UIImageView *) _baseView;
  215. if (!([imageView isKindOfClass:[UIImageView class]]) || imageView.image == nil) {
  216. if (!([imageView isKindOfClass:[UIImageView class]])) {
  217. return [_options[UIViewAnimationInView] frame];
  218. }
  219. }
  220. // Sizes
  221. CGSize boundsSize = [UIScreen mainScreen].bounds.size;
  222. CGSize imageSize = imageView.image.size;
  223. if (imageSize.width == 0 && imageSize.height == 0) {
  224. return [_options[UIViewAnimationInView] frame];
  225. }
  226. CGFloat xScale = boundsSize.width / imageSize.width; // the scale needed to perfectly fit the image width-wise
  227. CGFloat yScale = boundsSize.height / imageSize.height; // the scale needed to perfectly fit the image height-wise
  228. CGFloat minScale = MIN(xScale, yScale); // use minimum of these to allow the image to become fully visible
  229. // Image is smaller than screen so no zooming!
  230. if (xScale >= 1 && yScale >= 1) {
  231. minScale = MIN(xScale, yScale);
  232. }
  233. CGRect frameToCenter = CGRectMake(0, 0, imageSize.width * minScale, imageSize.height * minScale);
  234. // Horizontally
  235. if (frameToCenter.size.width < boundsSize.width) {
  236. frameToCenter.origin.x = floorf((boundsSize.width - frameToCenter.size.width) / 2.0);
  237. } else {
  238. frameToCenter.origin.x = 0;
  239. }
  240. // Vertically
  241. if (frameToCenter.size.height < boundsSize.height) {
  242. frameToCenter.origin.y = floorf((boundsSize.height - frameToCenter.size.height) / 2.0);
  243. } else {
  244. frameToCenter.origin.y = 0;
  245. }
  246. return frameToCenter;
  247. }
  248. + (void)setterParamsWithOrientation:(UIDevice *)device{
  249. if(device.orientation == UIDeviceOrientationLandscapeLeft || device.orientation == UIDeviceOrientationLandscapeRight){
  250. _attachParams[UIViewAnimationAnimationStatusType] = @(UIViewAnimationAnimationStatusRotate);
  251. }else{
  252. _attachParams[UIViewAnimationAnimationStatusType] = @(UIViewAnimationAnimationStatusZoom);
  253. }
  254. }
  255. #pragma mark -
  256. #pragma mark 开始动画
  257. + (void) willUnLoadAnimationOperation{
  258. // [[UIApplication sharedApplication] setStatusBarHidden:NO withAnimation:UIStatusBarAnimationNone];
  259. // [[UIApplication sharedApplication] setStatusBarHidden:NO];
  260. [UIApplication sharedApplication].statusBarHidden = NO;
  261. [UIApplication sharedApplication].keyWindow.userInteractionEnabled = NO;
  262. }
  263. #pragma mark 结束动画的操作
  264. + (void) unLoadStopAnimationOperation{
  265. [_options[UIViewAnimationFromView] setUserInteractionEnabled:YES];
  266. [UIApplication sharedApplication].keyWindow.userInteractionEnabled = YES;
  267. }
  268. #pragma mark -
  269. #pragma mark 设置分页/获取分页
  270. + (void) setCurrentPage:(NSInteger)currentPage{
  271. _currentPage = currentPage;
  272. }
  273. + (NSInteger) currentPage{
  274. return _currentPage;
  275. }
  276. + (void)setCurrentIndexPath:(NSIndexPath *)indexPath{
  277. _currentIndexPath = indexPath;
  278. }
  279. + (NSIndexPath *)currentIndexPath{
  280. return _currentIndexPath;
  281. }
  282. #pragma mark - 生命周期
  283. - (void)dealloc{
  284. _attachParams = nil;
  285. [UIApplication sharedApplication].statusBarHidden = NO;
  286. [_options[UIViewAnimationFromView] setUserInteractionEnabled:YES];
  287. [[NSNotificationCenter defaultCenter] removeObserver:self];
  288. }
  289. @end